Bug Summary

File:sdb.c
Warning:line 563, column 5
Value stored to 'sqlerr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name sdb.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/nss/cmd/dbtool -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/nss/cmd/dbtool -resource-dir /usr/lib/llvm-22/lib/clang/22 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D NSS_USE_STATIC_LIBS -I ../../../dist/Linux6.1_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-11-22-110252-3806607-1 -x c sdb.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4/*
5 * This file implements PKCS 11 on top of our existing security modules
6 *
7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8 * This implementation has two slots:
9 * slot 1 is our generic crypto support. It does not require login.
10 * It supports Public Key ops, and all they bulk ciphers and hashes.
11 * It can also support Private Key ops for imported Private keys. It does
12 * not have any token storage.
13 * slot 2 is our private key support. It requires a login before use. It
14 * can store Private Keys and Certs as token objects. Currently only private
15 * keys and their associated Certificates are saved on the token.
16 *
17 * In this implementation, session objects are only visible to the session
18 * that created or generated them.
19 */
20
21#include "sdb.h"
22#include "pkcs11t.h"
23#include "seccomon.h"
24#include <sqlite3.h>
25#include "prthread.h"
26#include "prio.h"
27#include <stdio.h>
28#include "secport.h"
29#include "prmon.h"
30#include "prenv.h"
31#include "prprf.h"
32#include "prsystem.h" /* for PR_GetDirectorySeparator() */
33#include <sys/stat.h>
34#if defined(_WIN32)
35#include <io.h>
36#include <windows.h>
37#elif defined(XP_UNIX1)
38#include <unistd.h>
39#endif
40#if defined(LINUX1) && !defined(ANDROID)
41#include <linux1/magic.h>
42#include <sys/vfs.h>
43#endif
44#include "utilpars.h"
45
46#ifdef SQLITE_UNSAFE_THREADS
47#include "prlock.h"
48/*
49 * SQLite can be compiled to be thread safe or not.
50 * turn on SQLITE_UNSAFE_THREADS if the OS does not support
51 * a thread safe version of sqlite.
52 */
53static PRLock *sqlite_lock = NULL((void*)0);
54
55#define LOCK_SQLITE() PR_Lock(sqlite_lock);
56#define UNLOCK_SQLITE() PR_Unlock(sqlite_lock);
57#else
58#define LOCK_SQLITE()
59#define UNLOCK_SQLITE()
60#endif
61
62typedef enum {
63 SDB_CERT = 1,
64 SDB_KEY = 2
65} sdbDataType;
66
67/*
68 * defines controlling how long we wait to acquire locks.
69 *
70 * SDB_SQLITE_BUSY_TIMEOUT specifies how long (in milliseconds)
71 * sqlite will wait on lock. If that timeout expires, sqlite will
72 * return SQLITE_BUSY.
73 * SDB_BUSY_RETRY_TIME specifies how many seconds the sdb_ code waits
74 * after receiving a busy before retrying.
75 * SDB_MAX_BUSY_RETRIES specifies how many times the sdb_ will retry on
76 * a busy condition.
77 *
78 * SDB_SQLITE_BUSY_TIMEOUT affects all opertions, both manual
79 * (prepare/step/reset/finalize) and automatic (sqlite3_exec()).
80 * SDB_BUSY_RETRY_TIME and SDB_MAX_BUSY_RETRIES only affect manual operations
81 *
82 * total wait time for automatic operations:
83 * 1 second (SDB_SQLITE_BUSY_TIMEOUT/1000).
84 * total wait time for manual operations:
85 * (1 second + SDB_BUSY_RETRY_TIME) * 30 = 30 seconds.
86 * (SDB_SQLITE_BUSY_TIMEOUT/1000 + SDB_BUSY_RETRY_TIME)*SDB_MAX_BUSY_RETRIES
87 */
88#define SDB_SQLITE_BUSY_TIMEOUT1000 1000 /* milliseconds */
89#define SDB_BUSY_RETRY_TIME5 5 /* 'ticks', varies by platforms */
90#define SDB_MAX_BUSY_RETRIES30 30
91
92/*
93 * known attributes
94 */
95// clang-format off
96const CK_ATTRIBUTE_TYPE sftkdb_known_attributes[] = {
97 CKA_CLASS0x00000000UL, CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_LABEL0x00000003UL, CKA_UNIQUE_ID0x00000004UL,
98 CKA_APPLICATION0x00000010UL, CKA_VALUE0x00000011UL, CKA_OBJECT_ID0x00000012UL, CKA_CERTIFICATE_TYPE0x00000080UL, CKA_ISSUER0x00000081UL,
99 CKA_SERIAL_NUMBER0x00000082UL, CKA_AC_ISSUER0x00000083UL, CKA_OWNER0x00000084UL, CKA_ATTR_TYPES0x00000085UL, CKA_TRUSTED0x00000086UL,
100 CKA_CERTIFICATE_CATEGORY0x00000087UL, CKA_JAVA_MIDP_SECURITY_DOMAIN0x00000088UL, CKA_URL0x00000089UL,
101 CKA_HASH_OF_SUBJECT_PUBLIC_KEY0x0000008AUL, CKA_HASH_OF_ISSUER_PUBLIC_KEY0x0000008BUL,
102 CKA_NAME_HASH_ALGORITHM0x0000008cUL, CKA_CHECK_VALUE0x00000090UL, CKA_KEY_TYPE0x00000100UL, CKA_SUBJECT0x00000101UL,
103 CKA_ID0x00000102UL, CKA_SENSITIVE0x00000103UL, CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL,
104 CKA_SIGN0x00000108UL, CKA_SIGN_RECOVER0x00000109UL, CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, CKA_DERIVE0x0000010CUL,
105 CKA_START_DATE0x00000110UL, CKA_END_DATE0x00000111UL, CKA_MODULUS0x00000120UL, CKA_MODULUS_BITS0x00000121UL,
106 CKA_PUBLIC_EXPONENT0x00000122UL, CKA_PRIVATE_EXPONENT0x00000123UL, CKA_PRIME_10x00000124UL, CKA_PRIME_20x00000125UL,
107 CKA_EXPONENT_10x00000126UL, CKA_EXPONENT_20x00000127UL, CKA_COEFFICIENT0x00000128UL, CKA_PUBLIC_KEY_INFO0x00000129UL,
108 CKA_PRIME0x00000130UL, CKA_SUBPRIME0x00000131UL, CKA_BASE0x00000132UL, CKA_PRIME_BITS0x00000133UL, CKA_SUB_PRIME_BITS0x00000134UL,
109 CKA_VALUE_BITS0x00000160UL, CKA_VALUE_LEN0x00000161UL, CKA_EXTRACTABLE0x00000162UL, CKA_LOCAL0x00000163UL,
110 CKA_NEVER_EXTRACTABLE0x00000164UL, CKA_ALWAYS_SENSITIVE0x00000165UL, CKA_KEY_GEN_MECHANISM0x00000166UL,
111 CKA_MODIFIABLE0x00000170UL, CKA_COPYABLE0x00000171UL, CKA_DESTROYABLE0x00000172UL, CKA_EC_PARAMS0x00000180UL, CKA_EC_POINT0x00000181UL,
112 CKA_SECONDARY_AUTH0x00000200UL, CKA_AUTH_PIN_FLAGS0x00000201UL, CKA_ALWAYS_AUTHENTICATE0x00000202UL,
113 CKA_WRAP_WITH_TRUSTED0x00000210UL, CKA_WRAP_TEMPLATE(0x40000000UL | 0x00000211UL), CKA_UNWRAP_TEMPLATE(0x40000000UL | 0x00000212UL),
114 CKA_DERIVE_TEMPLATE(0x40000000UL | 0x00000213UL), CKA_OTP_FORMAT0x00000220UL, CKA_OTP_LENGTH0x00000221UL, CKA_OTP_TIME_INTERVAL0x00000222UL,
115 CKA_OTP_USER_FRIENDLY_MODE0x00000223UL, CKA_OTP_CHALLENGE_REQUIREMENT0x00000224UL,
116 CKA_OTP_TIME_REQUIREMENT0x00000225UL, CKA_OTP_COUNTER_REQUIREMENT0x00000226UL,
117 CKA_OTP_PIN_REQUIREMENT0x00000227UL, CKA_OTP_COUNTER0x0000022EUL, CKA_OTP_TIME0x0000022FUL,
118 CKA_OTP_USER_IDENTIFIER0x0000022AUL, CKA_OTP_SERVICE_IDENTIFIER0x0000022BUL, CKA_OTP_SERVICE_LOGO0x0000022CUL,
119 CKA_OTP_SERVICE_LOGO_TYPE0x0000022DUL, CKA_GOSTR3410_PARAMS0x00000250UL, CKA_GOSTR3411_PARAMS0x00000251UL,
120 CKA_GOST28147_PARAMS0x00000252UL, CKA_HW_FEATURE_TYPE0x00000300UL, CKA_RESET_ON_INIT0x00000301UL,
121 CKA_HAS_RESET0x00000302UL, CKA_PIXEL_X0x00000400UL, CKA_PIXEL_Y0x00000401UL, CKA_RESOLUTION0x00000402UL, CKA_CHAR_ROWS0x00000403UL,
122 CKA_CHAR_COLUMNS0x00000404UL, CKA_COLOR0x00000405UL, CKA_BITS_PER_PIXEL0x00000406UL, CKA_CHAR_SETS0x00000480UL,
123 CKA_ENCODING_METHODS0x00000481UL, CKA_MIME_TYPES0x00000482UL, CKA_MECHANISM_TYPE0x00000500UL,
124 CKA_REQUIRED_CMS_ATTRIBUTES0x00000501UL, CKA_DEFAULT_CMS_ATTRIBUTES0x00000502UL,
125 CKA_SUPPORTED_CMS_ATTRIBUTES0x00000503UL, CKA_PROFILE_ID0x00000601UL, CKA_X2RATCHET_BAG0x00000602UL,
126 CKA_X2RATCHET_BAGSIZE0x00000603UL, CKA_X2RATCHET_BOBS1STMSG0x00000604UL, CKA_X2RATCHET_CKR0x00000605UL,
127 CKA_X2RATCHET_CKS0x00000606UL, CKA_X2RATCHET_DHP0x00000607UL, CKA_X2RATCHET_DHR0x00000608UL,
128 CKA_X2RATCHET_DHS0x00000609UL, CKA_X2RATCHET_HKR0x0000060aUL, CKA_X2RATCHET_HKS0x0000060bUL,
129 CKA_X2RATCHET_ISALICE0x0000060cUL, CKA_X2RATCHET_NHKR0x0000060dUL, CKA_X2RATCHET_NHKS0x0000060eUL,
130 CKA_X2RATCHET_NR0x0000060fUL, CKA_X2RATCHET_NS0x00000610UL, CKA_X2RATCHET_PNS0x00000611UL, CKA_X2RATCHET_RK0x00000612UL,
131 CKA_HSS_LEVELS0x00000617UL, CKA_HSS_LMS_TYPE0x00000618UL, CKA_HSS_LMOTS_TYPE0x00000619UL, CKA_HSS_LMS_TYPES0x0000061aUL,
132 CKA_HSS_LMOTS_TYPES0x0000061bUL, CKA_HSS_KEYS_REMAINING0x0000061cUL, CKA_PARAMETER_SET0x0000061dUL,
133 CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL, CKA_VALIDATION_TYPE0x0000061fUL, CKA_VALIDATION_VERSION0x00000620UL,
134 CKA_VALIDATION_LEVEL0x00000621UL, CKA_VALIDATION_MODULE_ID0x00000622UL, CKA_VALIDATION_FLAG0x00000623UL,
135 CKA_VALIDATION_AUTHORITY_TYPE0x00000624UL, CKA_VALIDATION_COUNTRY0x00000625UL,
136 CKA_VALIDATION_CERTIFICATE_IDENTIFIER0x00000626UL, CKA_VALIDATION_CERTIFICATE_URI0x00000627UL,
137 CKA_VALIDATION_PROFILE0x00000629UL, CKA_VALIDATION_VENDOR_URI0x00000628UL, CKA_ENCAPSULATE_TEMPLATE0x0000062aUL,
138 CKA_DECAPSULATE_TEMPLATE0x0000062bUL, CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL,
139 CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL, CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL,
140 CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL, CKA_TRUST_IPSEC_IKE0x00000630UL,
141 CKA_PKCS_TRUST_TIME_STAMPING0x00000631UL, CKA_PKCS_TRUST_OCSP_SIGNING0x00000632UL, CKA_ENCAPSULATE0x00000633UL,
142 CKA_DECAPSULATE0x00000634UL, CKA_HASH_OF_CERTIFICATE0x00000635UL, CKA_PUBLIC_CRC64_VALUE0x00000636UL, CKA_SEED0x00000637UL,
143 CKA_NSS_TRUST0x80000001L, CKA_NSS_URL((0x80000000UL | 0x4E534350) + 1), CKA_NSS_EMAIL((0x80000000UL | 0x4E534350) + 2), CKA_NSS_SMIME_INFO((0x80000000UL | 0x4E534350) + 3),
144 CKA_NSS_SMIME_TIMESTAMP((0x80000000UL | 0x4E534350) + 4), CKA_NSS_PKCS8_SALT((0x80000000UL | 0x4E534350) + 5), CKA_NSS_PASSWORD_CHECK((0x80000000UL | 0x4E534350) + 6),
145 CKA_NSS_EXPIRES((0x80000000UL | 0x4E534350) + 7), CKA_NSS_KRL((0x80000000UL | 0x4E534350) + 8), CKA_NSS_PQG_COUNTER((0x80000000UL | 0x4E534350) + 20), CKA_NSS_PQG_SEED((0x80000000UL | 0x4E534350) + 21),
146 CKA_NSS_PQG_H((0x80000000UL | 0x4E534350) + 22), CKA_NSS_PQG_SEED_BITS((0x80000000UL | 0x4E534350) + 23), CKA_NSS_MODULE_SPEC((0x80000000UL | 0x4E534350) + 24),
147 CKA_NSS_OVERRIDE_EXTENSIONS((0x80000000UL | 0x4E534350) + 25), CKA_NSS_SERVER_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 35),
148 CKA_NSS_EMAIL_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 36), CKA_NSS_TRUST_DIGITAL_SIGNATURE(((0x80000000UL | 0x4E534350) + 0x2000) + 1),
149 CKA_NSS_TRUST_NON_REPUDIATION(((0x80000000UL | 0x4E534350) + 0x2000) + 2), CKA_NSS_TRUST_KEY_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 3),
150 CKA_NSS_TRUST_DATA_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 4), CKA_NSS_TRUST_KEY_AGREEMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 5),
151 CKA_NSS_TRUST_KEY_CERT_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 6), CKA_NSS_TRUST_CRL_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 7),
152 CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8), CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9),
153 CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10), CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11),
154 CKA_NSS_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12), CKA_NSS_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13),
155 CKA_NSS_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14), CKA_NSS_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15),
156 CKA_NSS_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16), CKA_NSS_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100),
157 CKA_NSS_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101), CKA_NSS_DB0xD5A0DB00L,
158};
159// clang-format on
160
161const size_t sftkdb_known_attributes_size = PR_ARRAY_SIZE(sftkdb_known_attributes)(sizeof(sftkdb_known_attributes)/sizeof((sftkdb_known_attributes
)[0]))
;
162
163/*
164 * Note on use of sqlReadDB: Only one thread at a time may have an actual
165 * operation going on given sqlite3 * database. An operation is defined as
166 * the time from a sqlite3_prepare() until the sqlite3_finalize().
167 * Multiple sqlite3 * databases can be open and have simultaneous operations
168 * going. We use the sqlXactDB for all write operations. This database
169 * is only opened when we first create a transaction and closed when the
170 * transaction is complete. sqlReadDB is open when we first opened the database
171 * and is used for all read operation. It's use is protected by a monitor. This
172 * is because an operation can span the use of FindObjectsInit() through the
173 * call to FindObjectsFinal(). In the intermediate time it is possible to call
174 * other operations like NSC_GetAttributeValue */
175
176struct SDBPrivateStr {
177 char *sqlDBName; /* invariant, path to this database */
178 sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
179 * by the transaction. Current transaction db*/
180 PRThread *sqlXactThread; /* protected by dbMon,
181 * current transaction thread */
182 sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
183 PRIntervalTime lastUpdateTime; /* last time the cache was updated */
184 PRIntervalTime updateInterval; /* how long the cache can go before it
185 * must be updated again */
186 sdbDataType type; /* invariant, database type */
187 char *table; /* invariant, SQL table which contains the db */
188 char *cacheTable; /* invariant, SQL table cache of db */
189 PRMonitor *dbMon; /* invariant, monitor to protect
190 * sqlXact* fields, and use of the sqlReadDB */
191 CK_ATTRIBUTE_TYPE *schemaAttrs; /* Attribute columns that exist in the table. */
192 unsigned int numSchemaAttrs;
193};
194
195typedef struct SDBPrivateStr SDBPrivate;
196
197/* Magic for an explicit NULL. NOTE: ideally this should be
198 * out of band data. Since it's not completely out of band, pick
199 * a value that has no meaning to any existing PKCS #11 attributes.
200 * This value is 1) not a valid string (imbedded '\0'). 2) not a U_LONG
201 * or a normal key (too short). 3) not a bool (too long). 4) not an RSA
202 * public exponent (too many bits).
203 */
204const unsigned char SQLITE_EXPLICIT_NULL[] = { 0xa5, 0x0, 0x5a };
205#define SQLITE_EXPLICIT_NULL_LEN3 3
206
207/*
208 * determine when we've completed our tasks
209 */
210static int
211sdb_done(int err, int *count)
212{
213 /* allow as many rows as the database wants to give */
214 if (err == SQLITE_ROW100) {
215 *count = 0;
216 return 0;
217 }
218 if (err != SQLITE_BUSY5) {
219 return 1;
220 }
221 /* err == SQLITE_BUSY, Dont' retry forever in this case */
222 if (++(*count) >= SDB_MAX_BUSY_RETRIES30) {
223 return 1;
224 }
225 return 0;
226}
227
228#if defined(_WIN32)
229/*
230 * NSPR functions and narrow CRT functions do not handle UTF-8 file paths that
231 * sqlite3 expects.
232 */
233
234static int
235sdb_chmod(const char *filename, int pmode)chmod((const char *filename), (int pmode))
236{
237 int result;
238
239 if (!filename) {
240 return -1;
241 }
242
243 wchar_t *filenameWide = _NSSUTIL_UTF8ToWide(filename);
244 if (!filenameWide) {
245 return -1;
246 }
247 result = _wchmod(filenameWide, pmode);
248 PORT_FreePORT_Free_Util(filenameWide);
249
250 return result;
251}
252#else
253#define sdb_chmod(filename, pmode)chmod((filename), (pmode)) chmod((filename), (pmode))
254#endif
255
256/*
257 * find out where sqlite stores the temp tables. We do this by replicating
258 * the logic from sqlite.
259 */
260#if defined(_WIN32)
261static char *
262sdb_getFallbackTempDir(void)
263{
264 /* sqlite uses sqlite3_temp_directory if it is not NULL. We don't have
265 * access to sqlite3_temp_directory because it is not exported from
266 * sqlite3.dll. Assume sqlite3_win32_set_directory isn't called and
267 * sqlite3_temp_directory is NULL.
268 */
269 char path[MAX_PATH];
270 DWORD rv;
271 size_t len;
272
273 rv = GetTempPathA(MAX_PATH, path);
274 if (rv > MAX_PATH || rv == 0)
275 return NULL((void*)0);
276 len = strlen(path);
277 if (len == 0)
278 return NULL((void*)0);
279 /* The returned string ends with a backslash, for example, "C:\TEMP\". */
280 if (path[len - 1] == '\\')
281 path[len - 1] = '\0';
282 return PORT_StrdupPORT_Strdup_Util(path);
283}
284#elif defined(XP_UNIX1)
285static char *
286sdb_getFallbackTempDir(void)
287{
288 const char *azDirs[] = {
289 NULL((void*)0),
290 NULL((void*)0),
291 "/var/tmp",
292 "/usr/tmp",
293 "/tmp",
294 NULL((void*)0) /* List terminator */
295 };
296 unsigned int i;
297 struct stat buf;
298 const char *zDir = NULL((void*)0);
299
300 azDirs[0] = sqlite3_temp_directory;
301 azDirs[1] = PR_GetEnvSecure("TMPDIR");
302
303 for (i = 0; i < PR_ARRAY_SIZE(azDirs)(sizeof(azDirs)/sizeof((azDirs)[0])); i++) {
304 zDir = azDirs[i];
305 if (zDir == NULL((void*)0))
306 continue;
307 if (stat(zDir, &buf))
308 continue;
309 if (!S_ISDIR(buf.st_mode)((((buf.st_mode)) & 0170000) == (0040000)))
310 continue;
311 if (access(zDir, 07))
312 continue;
313 break;
314 }
315
316 if (zDir == NULL((void*)0))
317 return NULL((void*)0);
318 return PORT_StrdupPORT_Strdup_Util(zDir);
319}
320#else
321#error "sdb_getFallbackTempDir not implemented"
322#endif
323
324#ifndef SQLITE_FCNTL_TEMPFILENAME16
325/* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */
326#define SQLITE_FCNTL_TEMPFILENAME16 16
327#endif
328
329static char *
330sdb_getTempDir(sqlite3 *sqlDB)
331{
332 int sqlrv;
333 char *result = NULL((void*)0);
334 char *tempName = NULL((void*)0);
335 char *foundSeparator = NULL((void*)0);
336
337 /* Obtain temporary filename in sqlite's directory for temporary tables */
338 sqlrv = sqlite3_file_control(sqlDB, 0, SQLITE_FCNTL_TEMPFILENAME16,
339 (void *)&tempName);
340 if (sqlrv == SQLITE_NOTFOUND12) {
341 /* SQLITE_FCNTL_TEMPFILENAME not implemented because we are using
342 * an older SQLite. */
343 return sdb_getFallbackTempDir();
344 }
345 if (sqlrv != SQLITE_OK0) {
346 return NULL((void*)0);
347 }
348
349 /* We'll extract the temporary directory from tempName */
350 foundSeparator = PORT_Strrchrstrrchr(tempName, PR_GetDirectorySeparator());
351 if (foundSeparator) {
352 /* We shorten the temp filename string to contain only
353 * the directory name (including the trailing separator).
354 * We know the byte after the foundSeparator position is
355 * safe to use, in the shortest scenario it contains the
356 * end-of-string byte.
357 * By keeping the separator at the found position, it will
358 * even work if tempDir consists of the separator, only.
359 * (In this case the toplevel directory will be used for
360 * access speed testing). */
361 ++foundSeparator;
362 *foundSeparator = 0;
363
364 /* Now we copy the directory name for our caller */
365 result = PORT_StrdupPORT_Strdup_Util(tempName);
366 }
367
368 sqlite3_free(tempName);
369 return result;
370}
371
372/*
373 * Map SQL_LITE errors to PKCS #11 errors as best we can.
374 */
375static CK_RV
376sdb_mapSQLError(sdbDataType type, int sqlerr)
377{
378 switch (sqlerr) {
379 /* good matches */
380 case SQLITE_OK0:
381 case SQLITE_DONE101:
382 return CKR_OK0x00000000UL;
383 case SQLITE_NOMEM7:
384 return CKR_HOST_MEMORY0x00000002UL;
385 case SQLITE_READONLY8:
386 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
387 /* close matches */
388 case SQLITE_AUTH23:
389 case SQLITE_PERM3:
390 /*return CKR_USER_NOT_LOGGED_IN; */
391 case SQLITE_CANTOPEN14:
392 case SQLITE_NOTFOUND12:
393 /* NSS distiguishes between failure to open the cert and the key db */
394 return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED((0x80000000UL | 0x4E534350) + 1) : CKR_NSS_KEYDB_FAILED((0x80000000UL | 0x4E534350) + 2);
395 case SQLITE_IOERR10:
396 return CKR_DEVICE_ERROR0x00000030UL;
397 default:
398 break;
399 }
400 return CKR_GENERAL_ERROR0x00000005UL;
401}
402
403/*
404 * build up database name from a directory, prefix, name, version and flags.
405 */
406static char *
407sdb_BuildFileName(const char *directory,
408 const char *prefix, const char *type,
409 int version)
410{
411 char *dbname = NULL((void*)0);
412 /* build the full dbname */
413 dbname = sqlite3_mprintf("%s%c%s%s%d.db", directory,
414 (int)(unsigned char)PR_GetDirectorySeparator(),
415 prefix, type, version);
416 return dbname;
417}
418
419/*
420 * find out how expensive the access system call is for non-existant files
421 * in the given directory. Return the number of operations done in 33 ms.
422 */
423static PRUint32
424sdb_measureAccess(const char *directory)
425{
426 PRUint32 i;
427 PRIntervalTime time;
428 PRIntervalTime delta;
429 PRIntervalTime duration = PR_MillisecondsToInterval(33);
430 const char *doesntExistName = "_dOeSnotExist_.db";
431 char *temp, *tempStartOfFilename;
432 size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
433#ifdef SDB_MEASURE_USE_TEMP_DIR1
434 /*
435 * on some OS's and Filesystems, creating a bunch of files and deleting
436 * them messes up the systems's caching, but if we create the files in
437 * a temp directory which we later delete, then the cache gets cleared
438 * up. This code uses several OS dependent calls, and it's not clear
439 * that temp directory use won't mess up other filesystems and OS caching,
440 * so if you need this for your OS, you can turn on the
441 * 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf
442 */
443 const char template[] = "dbTemp.XXXXXX";
444 tmpdirLength = sizeof(template);
445#endif
446 /* no directory, just return one */
447 if (directory == NULL((void*)0)) {
448 return 1;
449 }
450
451 /* our calculation assumes time is a 4 bytes == 32 bit integer */
452 PORT_Assert(sizeof(time) == 4)((sizeof(time) == 4)?((void)0):PR_Assert("sizeof(time) == 4",
"sdb.c",452))
;
453
454 directoryLength = strlen(directory);
455
456 maxTempLen = directoryLength + 1 /* dirname + / */
457 + tmpdirLength /* tmpdirname includes / */
458 + strlen(doesntExistName) /* filename base */
459 + 11 /* max chars for 32 bit int plus potential sign */
460 + 1; /* zero terminator */
461
462 temp = PORT_ZAllocPORT_ZAlloc_Util(maxTempLen);
463 if (!temp) {
464 return 1;
465 }
466
467 /* We'll copy directory into temp just once, then ensure it ends
468 * with the directory separator. */
469
470 strcpy(temp, directory);
471 if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
472 temp[directoryLength++] = PR_GetDirectorySeparator();
473 }
474
475#ifdef SDB_MEASURE_USE_TEMP_DIR1
476 /* add the template for a temporary subdir, and create it */
477 strcat(temp, template);
478 if (!mkdtemp(temp)) {
479 PORT_FreePORT_Free_Util(temp);
480 return 1;
481 }
482 /* and terminate that tmp subdir with a / */
483 strcat(temp, "/");
484#endif
485
486 /* Remember the position after the last separator, and calculate the
487 * number of remaining bytes. */
488 tempStartOfFilename = temp + directoryLength + tmpdirLength;
489 maxFileNameLen = maxTempLen - directoryLength;
490
491 /* measure number of Access operations that can be done in 33 milliseconds
492 * (1/30'th of a second), or 10000 operations, which ever comes first.
493 */
494 time = PR_IntervalNow();
495 for (i = 0; i < 10000u; i++) {
496 PRIntervalTime next;
497
498 /* We'll use the variable part first in the filename string, just in
499 * case it's longer than assumed, so if anything gets cut off, it
500 * will be cut off from the constant part.
501 * This code assumes the directory name at the beginning of
502 * temp remains unchanged during our loop. */
503 PR_snprintf(tempStartOfFilename, maxFileNameLen,
504 ".%lu%s", (PRUint32)(time + i), doesntExistName);
505 PR_Access(temp, PR_ACCESS_EXISTS);
506 next = PR_IntervalNow();
507 delta = next - time;
508 if (delta >= duration)
509 break;
510 }
511
512#ifdef SDB_MEASURE_USE_TEMP_DIR1
513 /* turn temp back into our tmpdir path by removing doesntExistName, and
514 * remove the tmp dir */
515 *tempStartOfFilename = '\0';
516 (void)rmdir(temp);
517#endif
518 PORT_FreePORT_Free_Util(temp);
519
520 /* always return 1 or greater */
521 return i ? i : 1u;
522}
523
524/*
525 * some file sytems are very slow to run sqlite3 on, particularly if the
526 * access count is pretty high. On these filesystems is faster to create
527 * a temporary database on the local filesystem and access that. This
528 * code uses a temporary table to create that cache. Temp tables are
529 * automatically cleared when the database handle it was created on
530 * Is freed.
531 */
532static const char DROP_CACHE_CMD[] = "DROP TABLE %s";
533static const char CREATE_CACHE_CMD[] =
534 "CREATE TEMPORARY TABLE %s AS SELECT * FROM %s";
535static const char CREATE_ISSUER_INDEX_CMD[] =
536 "CREATE INDEX issuer ON %s (a81)";
537static const char CREATE_SUBJECT_INDEX_CMD[] =
538 "CREATE INDEX subject ON %s (a101)";
539static const char CREATE_LABEL_INDEX_CMD[] = "CREATE INDEX label ON %s (a3)";
540static const char CREATE_ID_INDEX_CMD[] = "CREATE INDEX ckaid ON %s (a102)";
541
542static CK_RV
543sdb_buildCache(sqlite3 *sqlDB, sdbDataType type,
544 const char *cacheTable, const char *table)
545{
546 char *newStr;
547 int sqlerr = SQLITE_OK0;
548
549 newStr = sqlite3_mprintf(CREATE_CACHE_CMD, cacheTable, table);
550 if (newStr == NULL((void*)0)) {
551 return CKR_HOST_MEMORY0x00000002UL;
552 }
553 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
554 sqlite3_free(newStr);
555 if (sqlerr != SQLITE_OK0) {
556 return sdb_mapSQLError(type, sqlerr);
557 }
558 /* failure to create the indexes is not an issue */
559 newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, cacheTable);
560 if (newStr == NULL((void*)0)) {
561 return CKR_OK0x00000000UL;
562 }
563 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
Value stored to 'sqlerr' is never read
564 sqlite3_free(newStr);
565 newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, cacheTable);
566 if (newStr == NULL((void*)0)) {
567 return CKR_OK0x00000000UL;
568 }
569 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
570 sqlite3_free(newStr);
571 newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, cacheTable);
572 if (newStr == NULL((void*)0)) {
573 return CKR_OK0x00000000UL;
574 }
575 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
576 sqlite3_free(newStr);
577 newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, cacheTable);
578 if (newStr == NULL((void*)0)) {
579 return CKR_OK0x00000000UL;
580 }
581 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
582 sqlite3_free(newStr);
583 return CKR_OK0x00000000UL;
584}
585
586/*
587 * update the cache and the data records describing it.
588 * The cache is updated by dropping the temp database and recreating it.
589 */
590static CK_RV
591sdb_updateCache(SDBPrivate *sdb_p)
592{
593 int sqlerr = SQLITE_OK0;
594 CK_RV error = CKR_OK0x00000000UL;
595 char *newStr;
596
597 /* drop the old table */
598 newStr = sqlite3_mprintf(DROP_CACHE_CMD, sdb_p->cacheTable);
599 if (newStr == NULL((void*)0)) {
600 return CKR_HOST_MEMORY0x00000002UL;
601 }
602 sqlerr = sqlite3_exec(sdb_p->sqlReadDB, newStr, NULL((void*)0), 0, NULL((void*)0));
603 sqlite3_free(newStr);
604 if ((sqlerr != SQLITE_OK0) && (sqlerr != SQLITE_ERROR1)) {
605 /* something went wrong with the drop, don't try to refresh...
606 * NOTE: SQLITE_ERROR is returned if the table doesn't exist. In
607 * that case, we just continue on and try to reload it */
608 return sdb_mapSQLError(sdb_p->type, sqlerr);
609 }
610
611 /* set up the new table */
612 error = sdb_buildCache(sdb_p->sqlReadDB, sdb_p->type,
613 sdb_p->cacheTable, sdb_p->table);
614 if (error == CKR_OK0x00000000UL) {
615 /* we have a new cache! */
616 sdb_p->lastUpdateTime = PR_IntervalNow();
617 }
618 return error;
619}
620
621/*
622 * The sharing of sqlite3 handles across threads is tricky. Older versions
623 * couldn't at all, but newer ones can under strict conditions. Basically
624 * no 2 threads can use the same handle while another thread has an open
625 * stmt running. Once the sqlite3_stmt is finalized, another thread can then
626 * use the database handle.
627 *
628 * We use monitors to protect against trying to use a database before
629 * it's sqlite3_stmt is finalized. This is preferable to the opening and
630 * closing the database each operation because there is significant overhead
631 * in the open and close. Also continually opening and closing the database
632 * defeats the cache code as the cache table is lost on close (thus
633 * requiring us to have to reinitialize the cache every operation).
634 *
635 * An execption to the shared handle is transations. All writes happen
636 * through a transaction. When we are in a transaction, we must use the
637 * same database pointer for that entire transation. In this case we save
638 * the transaction database and use it for all accesses on the transaction
639 * thread. Other threads use the common database.
640 *
641 * There can only be once active transaction on the database at a time.
642 *
643 * sdb_openDBLocal() provides us with a valid database handle for whatever
644 * state we are in (reading or in a transaction), and acquires any locks
645 * appropriate to that state. It also decides when it's time to refresh
646 * the cache before we start an operation. Any database handle returned
647 * just eventually be closed with sdb_closeDBLocal().
648 *
649 * The table returned either points to the database's physical table, or
650 * to the cached shadow. Tranactions always return the physical table
651 * and read operations return either the physical table or the cache
652 * depending on whether or not the cache exists.
653 */
654static CK_RV
655sdb_openDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB, const char **table)
656{
657 *sqlDB = NULL((void*)0);
658
659 PR_EnterMonitor(sdb_p->dbMon);
660
661 if (table) {
662 *table = sdb_p->table;
663 }
664
665 /* We're in a transaction, use the transaction DB */
666 if ((sdb_p->sqlXactDB) && (sdb_p->sqlXactThread == PR_GetCurrentThread())) {
667 *sqlDB = sdb_p->sqlXactDB;
668 /* only one thread can get here, safe to unlock */
669 PR_ExitMonitor(sdb_p->dbMon);
670 return CKR_OK0x00000000UL;
671 }
672
673 /*
674 * if we are just reading from the table, we may have the table
675 * cached in a temporary table (especially if it's on a shared FS).
676 * In that case we want to see updates to the table, the the granularity
677 * is on order of human scale, not computer scale.
678 */
679 if (table && sdb_p->cacheTable) {
680 PRIntervalTime now = PR_IntervalNow();
681 if ((now - sdb_p->lastUpdateTime) > sdb_p->updateInterval) {
682 sdb_updateCache(sdb_p);
683 }
684 *table = sdb_p->cacheTable;
685 }
686
687 *sqlDB = sdb_p->sqlReadDB;
688
689 /* leave holding the lock. only one thread can actually use a given
690 * database connection at once */
691
692 return CKR_OK0x00000000UL;
693}
694
695/* closing the local database currenly means unlocking the monitor */
696static CK_RV
697sdb_closeDBLocal(SDBPrivate *sdb_p, sqlite3 *sqlDB)
698{
699 if (sdb_p->sqlXactDB != sqlDB) {
700 /* if we weren't in a transaction, we got a lock */
701 PR_ExitMonitor(sdb_p->dbMon);
702 }
703 return CKR_OK0x00000000UL;
704}
705
706/*
707 * wrapper to sqlite3_open which also sets the busy_timeout
708 */
709static int
710sdb_openDB(const char *name, sqlite3 **sqlDB, int flags)
711{
712 int sqlerr;
713 int openFlags;
714
715 *sqlDB = NULL((void*)0);
716
717 if (flags & SDB_RDONLY1) {
718 openFlags = SQLITE_OPEN_READONLY0x00000001;
719 } else {
720 openFlags = SQLITE_OPEN_READWRITE0x00000002 | SQLITE_OPEN_CREATE0x00000004;
721 /* sqlite 3.34 seem to incorrectly open readwrite.
722 * when the file is readonly. Explicitly reject that issue here */
723 if ((_NSSUTIL_Access(name, PR_ACCESS_EXISTS)PR_Access((name), (PR_ACCESS_EXISTS)) == PR_SUCCESS) && (_NSSUTIL_Access(name, PR_ACCESS_WRITE_OK)PR_Access((name), (PR_ACCESS_WRITE_OK)) != PR_SUCCESS)) {
724 return SQLITE_READONLY8;
725 }
726 }
727
728 /* Requires SQLite 3.5.0 or newer. */
729 sqlerr = sqlite3_open_v2(name, sqlDB, openFlags, NULL((void*)0));
730 if (sqlerr != SQLITE_OK0) {
731 return sqlerr;
732 }
733
734 sqlerr = sqlite3_busy_timeout(*sqlDB, SDB_SQLITE_BUSY_TIMEOUT1000);
735 if (sqlerr != SQLITE_OK0) {
736 sqlite3_close(*sqlDB);
737 *sqlDB = NULL((void*)0);
738 return sqlerr;
739 }
740 return SQLITE_OK0;
741}
742
743/* Sigh, if we created a new table since we opened the database,
744 * the database handle will not see the new table, we need to close this
745 * database and reopen it. Caller must be in a transaction or holding
746 * the dbMon. sqlDB is changed on success. */
747static int
748sdb_reopenDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB)
749{
750 sqlite3 *newDB;
751 int sqlerr;
752
753 /* open a new database */
754 sqlerr = sdb_openDB(sdb_p->sqlDBName, &newDB, SDB_RDONLY1);
755 if (sqlerr != SQLITE_OK0) {
756 return sqlerr;
757 }
758
759 /* if we are in a transaction, we may not be holding the monitor.
760 * grab it before we update the transaction database. This is
761 * safe since are using monitors. */
762 PR_EnterMonitor(sdb_p->dbMon);
763 /* update our view of the database */
764 if (sdb_p->sqlReadDB == *sqlDB) {
765 sdb_p->sqlReadDB = newDB;
766 } else if (sdb_p->sqlXactDB == *sqlDB) {
767 sdb_p->sqlXactDB = newDB;
768 }
769 PR_ExitMonitor(sdb_p->dbMon);
770
771 /* close the old one */
772 sqlite3_close(*sqlDB);
773
774 *sqlDB = newDB;
775 return SQLITE_OK0;
776}
777
778struct SDBFindStr {
779 sqlite3 *sqlDB;
780 sqlite3_stmt *findstmt;
781};
782
783static const char FIND_OBJECTS_CMD[] = "SELECT ALL id FROM %s WHERE %s;";
784static const char FIND_OBJECTS_ALL_CMD[] = "SELECT ALL id FROM %s;";
785CK_RV
786sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count,
787 SDBFind **find)
788{
789 SDBPrivate *sdb_p = sdb->private;
790 sqlite3 *sqlDB = NULL((void*)0);
791 const char *table;
792 char *newStr, *findStr = NULL((void*)0);
793 sqlite3_stmt *findstmt = NULL((void*)0);
794 char *join = "";
795 int sqlerr = SQLITE_OK0;
796 CK_RV error = CKR_OK0x00000000UL;
797 unsigned int i;
798
799 LOCK_SQLITE()
800 *find = NULL((void*)0);
801 error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
802 if (error != CKR_OK0x00000000UL) {
803 goto loser;
804 }
805
806 findStr = sqlite3_mprintf("");
807 for (i = 0; findStr && i < count; i++) {
808 newStr = sqlite3_mprintf("%s%sa%x=$DATA%d", findStr, join,
809 template[i].type, i);
810 join = " AND ";
811 sqlite3_free(findStr);
812 findStr = newStr;
813 }
814
815 if (findStr == NULL((void*)0)) {
816 error = CKR_HOST_MEMORY0x00000002UL;
817 goto loser;
818 }
819
820 if (count == 0) {
821 newStr = sqlite3_mprintf(FIND_OBJECTS_ALL_CMD, table);
822 } else {
823 newStr = sqlite3_mprintf(FIND_OBJECTS_CMD, table, findStr);
824 }
825 sqlite3_free(findStr);
826 if (newStr == NULL((void*)0)) {
827 error = CKR_HOST_MEMORY0x00000002UL;
828 goto loser;
829 }
830 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &findstmt, NULL((void*)0));
831 sqlite3_free(newStr);
832 for (i = 0; sqlerr == SQLITE_OK0 && i < count; i++) {
833 const void *blobData = template[i].pValue;
834 unsigned int blobSize = template[i].ulValueLen;
835 if (blobSize == 0) {
836 blobSize = SQLITE_EXPLICIT_NULL_LEN3;
837 blobData = SQLITE_EXPLICIT_NULL;
838 }
839 sqlerr = sqlite3_bind_blob(findstmt, i + 1, blobData, blobSize,
840 SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
841 }
842 if (sqlerr == SQLITE_OK0) {
843 *find = PORT_New(SDBFind)(SDBFind *)PORT_Alloc_Util(sizeof(SDBFind));
844 if (*find == NULL((void*)0)) {
845 error = CKR_HOST_MEMORY0x00000002UL;
846 goto loser;
847 }
848 (*find)->findstmt = findstmt;
849 (*find)->sqlDB = sqlDB;
850 UNLOCK_SQLITE()
851 return CKR_OK0x00000000UL;
852 }
853 error = sdb_mapSQLError(sdb_p->type, sqlerr);
854
855loser:
856 if (findstmt) {
857 sqlite3_reset(findstmt);
858 sqlite3_finalize(findstmt);
859 }
860 if (sqlDB) {
861 sdb_closeDBLocal(sdb_p, sqlDB);
862 }
863 UNLOCK_SQLITE()
864 return error;
865}
866
867CK_RV
868sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
869 CK_ULONG arraySize, CK_ULONG *count)
870{
871 SDBPrivate *sdb_p = sdb->private;
872 sqlite3_stmt *stmt = sdbFind->findstmt;
873 int sqlerr = SQLITE_OK0;
874 int retry = 0;
875
876 *count = 0;
877
878 if (arraySize == 0) {
879 return CKR_OK0x00000000UL;
880 }
881 LOCK_SQLITE()
882
883 do {
884 sqlerr = sqlite3_step(stmt);
885 if (sqlerr == SQLITE_BUSY5) {
886 PR_Sleep(SDB_BUSY_RETRY_TIME5);
887 }
888 if (sqlerr == SQLITE_ROW100) {
889 /* only care about the id */
890 *object++ = sqlite3_column_int(stmt, 0);
891 arraySize--;
892 (*count)++;
893 }
894 } while (!sdb_done(sqlerr, &retry) && (arraySize > 0));
895
896 /* we only have some of the objects, there is probably more,
897 * set the sqlerr to an OK value so we return CKR_OK */
898 if (sqlerr == SQLITE_ROW100 && arraySize == 0) {
899 sqlerr = SQLITE_DONE101;
900 }
901 UNLOCK_SQLITE()
902
903 return sdb_mapSQLError(sdb_p->type, sqlerr);
904}
905
906CK_RV
907sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
908{
909 SDBPrivate *sdb_p = sdb->private;
910 sqlite3_stmt *stmt = sdbFind->findstmt;
911 sqlite3 *sqlDB = sdbFind->sqlDB;
912 int sqlerr = SQLITE_OK0;
913
914 LOCK_SQLITE()
915 if (stmt) {
916 sqlite3_reset(stmt);
917 sqlerr = sqlite3_finalize(stmt);
918 }
919 if (sqlDB) {
920 sdb_closeDBLocal(sdb_p, sqlDB);
921 }
922 PORT_FreePORT_Free_Util(sdbFind);
923
924 UNLOCK_SQLITE()
925 return sdb_mapSQLError(sdb_p->type, sqlerr);
926}
927
928static CK_RV
929sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
930 CK_ATTRIBUTE *template, CK_ULONG count)
931{
932 SDBPrivate *sdb_p = sdb->private;
933 sqlite3 *sqlDB = NULL((void*)0);
934 sqlite3_stmt *stmt = NULL((void*)0);
935 const char *table = NULL((void*)0);
936 int sqlerr = SQLITE_OK0;
937 CK_RV error = CKR_OK0x00000000UL;
938 int found = 0;
939 int retry = 0;
940 unsigned int i;
941
942 if (count == 0) {
943 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
944 goto loser;
945 }
946
947 /* open a new db if necessary */
948 error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
949 if (error != CKR_OK0x00000000UL) {
950 goto loser;
951 }
952
953 char *columns = NULL((void*)0);
954 for (i = 0; i < count; i++) {
955 char *newColumns;
956 if (columns) {
957 newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
958 sqlite3_free(columns);
959 columns = NULL((void*)0);
960 } else {
961 newColumns = sqlite3_mprintf("a%x", template[i].type);
962 }
963 if (!newColumns) {
964 error = CKR_HOST_MEMORY0x00000002UL;
965 goto loser;
966 }
967 columns = newColumns;
968 }
969
970 PORT_Assert(columns)((columns)?((void)0):PR_Assert("columns","sdb.c",970));
971
972 char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
973 columns, table);
974 sqlite3_free(columns);
975 columns = NULL((void*)0);
976 if (!statement) {
977 error = CKR_HOST_MEMORY0x00000002UL;
978 goto loser;
979 }
980
981 sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL((void*)0));
982 sqlite3_free(statement);
983 statement = NULL((void*)0);
984 if (sqlerr != SQLITE_OK0) {
985 goto loser;
986 }
987
988 // NB: indices in sqlite3_bind_int are 1-indexed
989 sqlerr = sqlite3_bind_int(stmt, 1, object_id);
990 if (sqlerr != SQLITE_OK0) {
991 goto loser;
992 }
993
994 do {
995 sqlerr = sqlite3_step(stmt);
996 if (sqlerr == SQLITE_BUSY5) {
997 PR_Sleep(SDB_BUSY_RETRY_TIME5);
998 }
999 if (sqlerr == SQLITE_ROW100) {
1000 PORT_Assert(!found)((!found)?((void)0):PR_Assert("!found","sdb.c",1000));
1001 for (i = 0; i < count; i++) {
1002 unsigned int blobSize;
1003 const char *blobData;
1004
1005 // NB: indices in sqlite_column_{bytes,blob} are 0-indexed
1006 blobSize = sqlite3_column_bytes(stmt, i);
1007 blobData = sqlite3_column_blob(stmt, i);
1008 if (blobData == NULL((void*)0)) {
1009 /* PKCS 11 requires that get attributes process all the
1010 * attributes in the template, marking the attributes with
1011 * issues with -1. Mark the error but continue */
1012 template[i].ulValueLen = -1;
1013 error = CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL;
1014 continue;
1015 }
1016 /* If the blob equals our explicit NULL value, then the
1017 * attribute is a NULL. */
1018 if ((blobSize == SQLITE_EXPLICIT_NULL_LEN3) &&
1019 (PORT_Memcmpmemcmp(blobData, SQLITE_EXPLICIT_NULL,
1020 SQLITE_EXPLICIT_NULL_LEN3) == 0)) {
1021 blobSize = 0;
1022 }
1023 if (template[i].pValue) {
1024 if (template[i].ulValueLen < blobSize) {
1025 /* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
1026 template[i].ulValueLen = -1;
1027 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1028 continue;
1029 }
1030 PORT_Memcpymemcpy(template[i].pValue, blobData, blobSize);
1031 }
1032 template[i].ulValueLen = blobSize;
1033 }
1034 found = 1;
1035 }
1036 } while (!sdb_done(sqlerr, &retry));
1037
1038 sqlite3_reset(stmt);
1039 sqlite3_finalize(stmt);
1040 stmt = NULL((void*)0);
1041
1042loser:
1043 /* fix up the error if necessary */
1044 if (error == CKR_OK0x00000000UL) {
1045 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1046 if (!found && error == CKR_OK0x00000000UL) {
1047 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1048 }
1049 }
1050
1051 if (stmt) {
1052 sqlite3_reset(stmt);
1053 sqlite3_finalize(stmt);
1054 }
1055
1056 /* if we had to open a new database, free it now */
1057 if (sqlDB) {
1058 sdb_closeDBLocal(sdb_p, sqlDB);
1059 }
1060 return error;
1061}
1062
1063/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */
1064inline static PRBool
1065sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr)
1066{
1067 SDBPrivate *sdb_p = sdb->private;
1068 int first = 0;
1069 int last = (int)sdb_p->numSchemaAttrs - 1;
1070 while (last >= first) {
1071 int mid = first + (last - first) / 2;
1072 if (sdb_p->schemaAttrs[mid] == attr) {
1073 return PR_TRUE1;
1074 }
1075 if (attr > sdb_p->schemaAttrs[mid]) {
1076 first = mid + 1;
1077 } else {
1078 last = mid - 1;
1079 }
1080 }
1081
1082 return PR_FALSE0;
1083}
1084
1085CK_RV
1086sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1087 CK_ATTRIBUTE *template, CK_ULONG count)
1088{
1089 CK_RV crv = CKR_OK0x00000000UL;
1090 unsigned int tmplIdx;
1091 unsigned int resIdx = 0;
1092 unsigned int validCount = 0;
1093 unsigned int i;
1094
1095 if (count == 0) {
1096 return crv;
1097 }
1098
1099 CK_ATTRIBUTE *validTemplate;
1100 PRBool invalidExists = PR_FALSE0;
1101 for (tmplIdx = 0; tmplIdx < count; tmplIdx++) {
1102 if (!sdb_attributeExists(sdb, template[tmplIdx].type)) {
1103 template[tmplIdx].ulValueLen = -1;
1104 crv = CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL;
1105 invalidExists = PR_TRUE1;
1106 break;
1107 }
1108 }
1109
1110 if (!invalidExists) {
1111 validTemplate = template;
1112 validCount = count;
1113 } else {
1114 /* Create a new template containing only the valid subset of
1115 * input |template|, and query with that. */
1116 validCount = tmplIdx;
1117 validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count);
1118 if (!validTemplate) {
1119 return CKR_HOST_MEMORY0x00000002UL;
1120 }
1121 /* Copy in what we already know is valid. */
1122 for (i = 0; i < validCount; i++) {
1123 validTemplate[i] = template[i];
1124 }
1125
1126 /* tmplIdx was left at the index of the first invalid
1127 * attribute, which has been handled. We only need to
1128 * deal with the remainder. */
1129 tmplIdx++;
1130 for (; tmplIdx < count; tmplIdx++) {
1131 if (sdb_attributeExists(sdb, template[tmplIdx].type)) {
1132 validTemplate[validCount++] = template[tmplIdx];
1133 } else {
1134 template[tmplIdx].ulValueLen = -1;
1135 }
1136 }
1137 }
1138
1139 if (validCount) {
1140 LOCK_SQLITE()
1141 CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount);
1142 UNLOCK_SQLITE()
1143
1144 /* If an invalid attribute was removed above, let
1145 * the caller know. Any other error from the actual
1146 * query should propogate. */
1147 crv = (crv2 == CKR_OK0x00000000UL) ? crv : crv2;
1148 }
1149
1150 if (invalidExists) {
1151 /* Copy out valid lengths. */
1152 tmplIdx = 0;
1153 for (resIdx = 0; resIdx < validCount; resIdx++) {
1154 for (; tmplIdx < count; tmplIdx++) {
1155 if (template[tmplIdx].type != validTemplate[resIdx].type) {
1156 continue;
1157 }
1158 template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen;
1159 tmplIdx++;
1160 break;
1161 }
1162 }
1163 free(validTemplate);
1164 }
1165
1166 return crv;
1167}
1168
1169static const char SET_ATTRIBUTE_CMD[] = "UPDATE %s SET %s WHERE id=$ID;";
1170CK_RV
1171sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1172 const CK_ATTRIBUTE *template, CK_ULONG count)
1173{
1174 SDBPrivate *sdb_p = sdb->private;
1175 sqlite3 *sqlDB = NULL((void*)0);
1176 sqlite3_stmt *stmt = NULL((void*)0);
1177 char *setStr = NULL((void*)0);
1178 char *newStr = NULL((void*)0);
1179 int sqlerr = SQLITE_OK0;
1180 int retry = 0;
1181 CK_RV error = CKR_OK0x00000000UL;
1182 unsigned int i;
1183
1184 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1185 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1186 }
1187
1188 if (count == 0) {
1189 return CKR_OK0x00000000UL;
1190 }
1191
1192 LOCK_SQLITE()
1193 setStr = sqlite3_mprintf("");
1194 for (i = 0; setStr && i < count; i++) {
1195 if (i == 0) {
1196 sqlite3_free(setStr);
1197 setStr = sqlite3_mprintf("a%x=$VALUE%d",
1198 template[i].type, i);
1199 continue;
1200 }
1201 newStr = sqlite3_mprintf("%s,a%x=$VALUE%d", setStr,
1202 template[i].type, i);
1203 sqlite3_free(setStr);
1204 setStr = newStr;
1205 }
1206 newStr = NULL((void*)0);
1207
1208 if (setStr == NULL((void*)0)) {
1209 return CKR_HOST_MEMORY0x00000002UL;
1210 }
1211 newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr);
1212 sqlite3_free(setStr);
1213 if (newStr == NULL((void*)0)) {
1214 UNLOCK_SQLITE()
1215 return CKR_HOST_MEMORY0x00000002UL;
1216 }
1217 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1218 if (error != CKR_OK0x00000000UL) {
1219 goto loser;
1220 }
1221 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1222 if (sqlerr != SQLITE_OK0)
1223 goto loser;
1224 for (i = 0; i < count; i++) {
1225 if (template[i].ulValueLen != 0) {
1226 sqlerr = sqlite3_bind_blob(stmt, i + 1, template[i].pValue,
1227 template[i].ulValueLen, SQLITE_STATIC((sqlite3_destructor_type)0));
1228 } else {
1229 sqlerr = sqlite3_bind_blob(stmt, i + 1, SQLITE_EXPLICIT_NULL,
1230 SQLITE_EXPLICIT_NULL_LEN3, SQLITE_STATIC((sqlite3_destructor_type)0));
1231 }
1232 if (sqlerr != SQLITE_OK0)
1233 goto loser;
1234 }
1235 sqlerr = sqlite3_bind_int(stmt, i + 1, object_id);
1236 if (sqlerr != SQLITE_OK0)
1237 goto loser;
1238
1239 do {
1240 sqlerr = sqlite3_step(stmt);
1241 if (sqlerr == SQLITE_BUSY5) {
1242 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1243 }
1244 } while (!sdb_done(sqlerr, &retry));
1245
1246loser:
1247 if (newStr) {
1248 sqlite3_free(newStr);
1249 }
1250 if (error == CKR_OK0x00000000UL) {
1251 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1252 }
1253
1254 if (stmt) {
1255 sqlite3_reset(stmt);
1256 sqlite3_finalize(stmt);
1257 }
1258
1259 if (sqlDB) {
1260 sdb_closeDBLocal(sdb_p, sqlDB);
1261 }
1262
1263 UNLOCK_SQLITE()
1264 return error;
1265}
1266
1267/*
1268 * check to see if a candidate object handle already exists.
1269 */
1270static PRBool
1271sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
1272{
1273 CK_RV crv;
1274 CK_ATTRIBUTE template = { CKA_LABEL0x00000003UL, NULL((void*)0), 0 };
1275
1276 crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1);
1277 if (crv == CKR_OBJECT_HANDLE_INVALID0x00000082UL) {
1278 return PR_FALSE0;
1279 }
1280 return PR_TRUE1;
1281}
1282
1283/*
1284 * if we're here, we are in a transaction, so it's safe
1285 * to examine the current state of the database
1286 */
1287static CK_OBJECT_HANDLE
1288sdb_getObjectId(SDB *sdb)
1289{
1290 CK_OBJECT_HANDLE candidate;
1291 static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE0;
1292 int count;
1293 /*
1294 * get an initial object handle to use
1295 */
1296 if (next_obj == CK_INVALID_HANDLE0) {
1297 PRTime time;
1298 time = PR_Now();
1299
1300 next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL);
1301 }
1302 candidate = next_obj++;
1303 /* detect that we've looped through all the handles... */
1304 for (count = 0; count < 0x40000000; count++, candidate = next_obj++) {
1305 /* mask off excess bits */
1306 candidate &= 0x3fffffff;
1307 /* if we hit zero, go to the next entry */
1308 if (candidate == CK_INVALID_HANDLE0) {
1309 continue;
1310 }
1311 /* make sure we aren't already using */
1312 if (!sdb_objectExists(sdb, candidate)) {
1313 /* this one is free */
1314 return candidate;
1315 }
1316 }
1317
1318 /* no handle is free, fail */
1319 return CK_INVALID_HANDLE0;
1320}
1321
1322CK_RV
1323sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object)
1324{
1325 CK_OBJECT_HANDLE id;
1326
1327 id = sdb_getObjectId(sdb);
1328 if (id == CK_INVALID_HANDLE0) {
1329 return CKR_DEVICE_MEMORY0x00000031UL; /* basically we ran out of resources */
1330 }
1331 *object = id;
1332 return CKR_OK0x00000000UL;
1333}
1334
1335static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);";
1336CK_RV
1337sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
1338 const CK_ATTRIBUTE *template, CK_ULONG count)
1339{
1340 SDBPrivate *sdb_p = sdb->private;
1341 sqlite3 *sqlDB = NULL((void*)0);
1342 sqlite3_stmt *stmt = NULL((void*)0);
1343 char *columnStr = NULL((void*)0);
1344 char *valueStr = NULL((void*)0);
1345 char *newStr = NULL((void*)0);
1346 int sqlerr = SQLITE_OK0;
1347 CK_RV error = CKR_OK0x00000000UL;
1348 CK_OBJECT_HANDLE this_object = CK_INVALID_HANDLE0;
1349 int retry = 0;
1350 unsigned int i;
1351
1352 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1353 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1354 }
1355
1356 LOCK_SQLITE()
1357 if ((*object_id != CK_INVALID_HANDLE0) &&
1358 !sdb_objectExists(sdb, *object_id)) {
1359 this_object = *object_id;
1360 } else {
1361 this_object = sdb_getObjectId(sdb);
1362 }
1363 if (this_object == CK_INVALID_HANDLE0) {
1364 UNLOCK_SQLITE();
1365 return CKR_HOST_MEMORY0x00000002UL;
1366 }
1367 columnStr = sqlite3_mprintf("");
1368 valueStr = sqlite3_mprintf("");
1369 *object_id = this_object;
1370 for (i = 0; columnStr && valueStr && i < count; i++) {
1371 newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type);
1372 sqlite3_free(columnStr);
1373 columnStr = newStr;
1374 newStr = sqlite3_mprintf("%s,$VALUE%d", valueStr, i);
1375 sqlite3_free(valueStr);
1376 valueStr = newStr;
1377 }
1378 newStr = NULL((void*)0);
1379 if ((columnStr == NULL((void*)0)) || (valueStr == NULL((void*)0))) {
1380 if (columnStr) {
1381 sqlite3_free(columnStr);
1382 }
1383 if (valueStr) {
1384 sqlite3_free(valueStr);
1385 }
1386 UNLOCK_SQLITE()
1387 return CKR_HOST_MEMORY0x00000002UL;
1388 }
1389 newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr);
1390 sqlite3_free(columnStr);
1391 sqlite3_free(valueStr);
1392 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1393 if (error != CKR_OK0x00000000UL) {
1394 goto loser;
1395 }
1396 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1397 if (sqlerr != SQLITE_OK0)
1398 goto loser;
1399 sqlerr = sqlite3_bind_int(stmt, 1, *object_id);
1400 if (sqlerr != SQLITE_OK0)
1401 goto loser;
1402 for (i = 0; i < count; i++) {
1403 if (template[i].ulValueLen) {
1404 sqlerr = sqlite3_bind_blob(stmt, i + 2, template[i].pValue,
1405 template[i].ulValueLen, SQLITE_STATIC((sqlite3_destructor_type)0));
1406 } else {
1407 sqlerr = sqlite3_bind_blob(stmt, i + 2, SQLITE_EXPLICIT_NULL,
1408 SQLITE_EXPLICIT_NULL_LEN3, SQLITE_STATIC((sqlite3_destructor_type)0));
1409 }
1410 if (sqlerr != SQLITE_OK0)
1411 goto loser;
1412 }
1413
1414 do {
1415 sqlerr = sqlite3_step(stmt);
1416 if (sqlerr == SQLITE_BUSY5) {
1417 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1418 }
1419 } while (!sdb_done(sqlerr, &retry));
1420
1421loser:
1422 if (newStr) {
1423 sqlite3_free(newStr);
1424 }
1425 if (error == CKR_OK0x00000000UL) {
1426 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1427 }
1428
1429 if (stmt) {
1430 sqlite3_reset(stmt);
1431 sqlite3_finalize(stmt);
1432 }
1433
1434 if (sqlDB) {
1435 sdb_closeDBLocal(sdb_p, sqlDB);
1436 }
1437 UNLOCK_SQLITE()
1438
1439 return error;
1440}
1441
1442/*
1443 * Generic destroy that can destroy metadata or objects
1444 */
1445static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);";
1446CK_RV
1447sdb_destroyAnyObject(SDB *sdb, const char *table,
1448 CK_OBJECT_HANDLE object_id, const char *string_id)
1449{
1450 SDBPrivate *sdb_p = sdb->private;
1451 sqlite3 *sqlDB = NULL((void*)0);
1452 sqlite3_stmt *stmt = NULL((void*)0);
1453 char *newStr = NULL((void*)0);
1454 int sqlerr = SQLITE_OK0;
1455 CK_RV error = CKR_OK0x00000000UL;
1456 int retry = 0;
1457
1458 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1459 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1460 }
1461
1462 LOCK_SQLITE()
1463 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1464 if (error != CKR_OK0x00000000UL) {
1465 goto loser;
1466 }
1467 newStr = sqlite3_mprintf(DESTROY_CMD, table);
1468 if (newStr == NULL((void*)0)) {
1469 error = CKR_HOST_MEMORY0x00000002UL;
1470 goto loser;
1471 }
1472 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1473 sqlite3_free(newStr);
1474 if (sqlerr != SQLITE_OK0)
1475 goto loser;
1476 if (string_id == NULL((void*)0)) {
1477 sqlerr = sqlite3_bind_int(stmt, 1, object_id);
1478 } else {
1479 sqlerr = sqlite3_bind_text(stmt, 1, string_id,
1480 PORT_Strlen(string_id)strlen(string_id), SQLITE_STATIC((sqlite3_destructor_type)0));
1481 }
1482 if (sqlerr != SQLITE_OK0)
1483 goto loser;
1484
1485 do {
1486 sqlerr = sqlite3_step(stmt);
1487 if (sqlerr == SQLITE_BUSY5) {
1488 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1489 }
1490 } while (!sdb_done(sqlerr, &retry));
1491
1492loser:
1493 if (error == CKR_OK0x00000000UL) {
1494 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1495 }
1496
1497 if (stmt) {
1498 sqlite3_reset(stmt);
1499 sqlite3_finalize(stmt);
1500 }
1501
1502 if (sqlDB) {
1503 sdb_closeDBLocal(sdb_p, sqlDB);
1504 }
1505
1506 UNLOCK_SQLITE()
1507 return error;
1508}
1509
1510CK_RV
1511sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
1512{
1513 SDBPrivate *sdb_p = sdb->private;
1514 return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL((void*)0));
1515}
1516
1517CK_RV
1518sdb_DestroyMetaData(SDB *sdb, const char *id)
1519{
1520 return sdb_destroyAnyObject(sdb, "metaData", 0, id);
1521}
1522
1523static const char BEGIN_CMD[] = "BEGIN IMMEDIATE TRANSACTION;";
1524
1525/*
1526 * start a transaction.
1527 *
1528 * We need to open a new database, then store that new database into
1529 * the private data structure. We open the database first, then use locks
1530 * to protect storing the data to prevent deadlocks.
1531 */
1532CK_RV
1533sdb_Begin(SDB *sdb)
1534{
1535 SDBPrivate *sdb_p = sdb->private;
1536 sqlite3 *sqlDB = NULL((void*)0);
1537 sqlite3_stmt *stmt = NULL((void*)0);
1538 int sqlerr = SQLITE_OK0;
1539 CK_RV error = CKR_OK0x00000000UL;
1540 int retry = 0;
1541
1542 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1543 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1544 }
1545
1546 LOCK_SQLITE()
1547
1548 /* get a new version that we will use for the entire transaction */
1549 sqlerr = sdb_openDB(sdb_p->sqlDBName, &sqlDB, SDB_RDWR2);
1550 if (sqlerr != SQLITE_OK0) {
1551 goto loser;
1552 }
1553
1554 sqlerr = sqlite3_prepare_v2(sqlDB, BEGIN_CMD, -1, &stmt, NULL((void*)0));
1555
1556 do {
1557 sqlerr = sqlite3_step(stmt);
1558 if (sqlerr == SQLITE_BUSY5) {
1559 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1560 }
1561 /* don't retry BEGIN transaction*/
1562 retry = 0;
1563 } while (!sdb_done(sqlerr, &retry));
1564
1565 if (stmt) {
1566 sqlite3_reset(stmt);
1567 sqlite3_finalize(stmt);
1568 }
1569
1570loser:
1571 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1572
1573 /* we are starting a new transaction,
1574 * and if we succeeded, then save this database for the rest of
1575 * our transaction */
1576 if (error == CKR_OK0x00000000UL) {
1577 /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point
1578 * sdb_p->sqlXactDB MUST be null */
1579 PR_EnterMonitor(sdb_p->dbMon);
1580 PORT_Assert(sdb_p->sqlXactDB == NULL)((sdb_p->sqlXactDB == ((void*)0))?((void)0):PR_Assert("sdb_p->sqlXactDB == NULL"
,"sdb.c",1580))
;
1581 sdb_p->sqlXactDB = sqlDB;
1582 sdb_p->sqlXactThread = PR_GetCurrentThread();
1583 PR_ExitMonitor(sdb_p->dbMon);
1584 } else {
1585 /* we failed to start our transaction,
1586 * free any databases we opened. */
1587 if (sqlDB) {
1588 sqlite3_close(sqlDB);
1589 }
1590 }
1591
1592 UNLOCK_SQLITE()
1593 return error;
1594}
1595
1596/*
1597 * Complete a transaction. Basically undo everything we did in begin.
1598 * There are 2 flavors Abort and Commit. Basically the only differerence between
1599 * these 2 are what the database will show. (no change in to former, change in
1600 * the latter).
1601 */
1602static CK_RV
1603sdb_complete(SDB *sdb, const char *cmd)
1604{
1605 SDBPrivate *sdb_p = sdb->private;
1606 sqlite3 *sqlDB = NULL((void*)0);
1607 sqlite3_stmt *stmt = NULL((void*)0);
1608 int sqlerr = SQLITE_OK0;
1609 CK_RV error = CKR_OK0x00000000UL;
1610 int retry = 0;
1611
1612 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1613 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1614 }
1615
1616 /* We must have a transation database, or we shouldn't have arrived here */
1617 PR_EnterMonitor(sdb_p->dbMon);
1618 PORT_Assert(sdb_p->sqlXactDB)((sdb_p->sqlXactDB)?((void)0):PR_Assert("sdb_p->sqlXactDB"
,"sdb.c",1618))
;
1619 if (sdb_p->sqlXactDB == NULL((void*)0)) {
1620 PR_ExitMonitor(sdb_p->dbMon);
1621 return CKR_GENERAL_ERROR0x00000005UL; /* shouldn't happen */
1622 }
1623 PORT_Assert(sdb_p->sqlXactThread == PR_GetCurrentThread())((sdb_p->sqlXactThread == PR_GetCurrentThread())?((void)0)
:PR_Assert("sdb_p->sqlXactThread == PR_GetCurrentThread()"
,"sdb.c",1623))
;
1624 if (sdb_p->sqlXactThread != PR_GetCurrentThread()) {
1625 PR_ExitMonitor(sdb_p->dbMon);
1626 return CKR_GENERAL_ERROR0x00000005UL; /* shouldn't happen */
1627 }
1628 sqlDB = sdb_p->sqlXactDB;
1629 sdb_p->sqlXactDB = NULL((void*)0); /* no one else can get to this DB,
1630 * safe to unlock */
1631 sdb_p->sqlXactThread = NULL((void*)0);
1632 PR_ExitMonitor(sdb_p->dbMon);
1633
1634 sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL((void*)0));
1635
1636 do {
1637 sqlerr = sqlite3_step(stmt);
1638 if (sqlerr == SQLITE_BUSY5) {
1639 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1640 }
1641 } while (!sdb_done(sqlerr, &retry));
1642
1643 /* Pending BEGIN TRANSACTIONS Can move forward at this point. */
1644
1645 if (stmt) {
1646 sqlite3_reset(stmt);
1647 sqlite3_finalize(stmt);
1648 }
1649
1650 /* we we have a cached DB image, update it as well */
1651 if (sdb_p->cacheTable) {
1652 PR_EnterMonitor(sdb_p->dbMon);
1653 sdb_updateCache(sdb_p);
1654 PR_ExitMonitor(sdb_p->dbMon);
1655 }
1656
1657 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1658
1659 /* We just finished a transaction.
1660 * Free the database, and remove it from the list */
1661 sqlite3_close(sqlDB);
1662
1663 return error;
1664}
1665
1666static const char COMMIT_CMD[] = "COMMIT TRANSACTION;";
1667CK_RV
1668sdb_Commit(SDB *sdb)
1669{
1670 CK_RV crv;
1671 LOCK_SQLITE()
1672 crv = sdb_complete(sdb, COMMIT_CMD);
1673 UNLOCK_SQLITE()
1674 return crv;
1675}
1676
1677static const char ROLLBACK_CMD[] = "ROLLBACK TRANSACTION;";
1678CK_RV
1679sdb_Abort(SDB *sdb)
1680{
1681 CK_RV crv;
1682 LOCK_SQLITE()
1683 crv = sdb_complete(sdb, ROLLBACK_CMD);
1684 UNLOCK_SQLITE()
1685 return crv;
1686}
1687
1688static int tableExists(sqlite3 *sqlDB, const char *tableName);
1689
1690static const char GET_PW_CMD[] = "SELECT ALL * FROM metaData WHERE id=$ID;";
1691CK_RV
1692sdb_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2)
1693{
1694 SDBPrivate *sdb_p = sdb->private;
1695 sqlite3 *sqlDB = NULL((void*)0);
1696 sqlite3_stmt *stmt = NULL((void*)0);
1697 int sqlerr = SQLITE_OK0;
1698 CK_RV error = CKR_OK0x00000000UL;
1699 int found = 0;
1700 int retry = 0;
1701
1702 LOCK_SQLITE()
1703 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1704 if (error != CKR_OK0x00000000UL) {
1705 goto loser;
1706 }
1707
1708 /* handle 'test' versions of the sqlite db */
1709 sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL((void*)0));
1710 /* Sigh, if we created a new table since we opened the database,
1711 * the database handle will not see the new table, we need to close this
1712 * database and reopen it. This is safe because we are holding the lock
1713 * still. */
1714 if (sqlerr == SQLITE_SCHEMA17) {
1715 sqlerr = sdb_reopenDBLocal(sdb_p, &sqlDB);
1716 if (sqlerr != SQLITE_OK0) {
1717 goto loser;
1718 }
1719 sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL((void*)0));
1720 }
1721 if (sqlerr != SQLITE_OK0)
1722 goto loser;
1723 sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id)strlen(id), SQLITE_STATIC((sqlite3_destructor_type)0));
1724 do {
1725 sqlerr = sqlite3_step(stmt);
1726 if (sqlerr == SQLITE_BUSY5) {
1727 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1728 }
1729 if (sqlerr == SQLITE_ROW100) {
1730 const char *blobData;
1731 unsigned int len = item1->len;
1732 item1->len = sqlite3_column_bytes(stmt, 1);
1733 if (item1->len > len) {
1734 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1735 continue;
1736 }
1737 blobData = sqlite3_column_blob(stmt, 1);
1738 PORT_Memcpymemcpy(item1->data, blobData, item1->len);
1739 if (item2) {
1740 len = item2->len;
1741 item2->len = sqlite3_column_bytes(stmt, 2);
1742 if (item2->len > len) {
1743 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1744 continue;
1745 }
1746 blobData = sqlite3_column_blob(stmt, 2);
1747 PORT_Memcpymemcpy(item2->data, blobData, item2->len);
1748 }
1749 found = 1;
1750 }
1751 } while (!sdb_done(sqlerr, &retry));
1752
1753loser:
1754 /* fix up the error if necessary */
1755 if (error == CKR_OK0x00000000UL) {
1756 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1757 if (!found && error == CKR_OK0x00000000UL) {
1758 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1759 }
1760 }
1761
1762 if (stmt) {
1763 sqlite3_reset(stmt);
1764 sqlite3_finalize(stmt);
1765 }
1766
1767 if (sqlDB) {
1768 sdb_closeDBLocal(sdb_p, sqlDB);
1769 }
1770 UNLOCK_SQLITE()
1771
1772 return error;
1773}
1774
1775static const char PW_CREATE_TABLE_CMD[] =
1776 "CREATE TABLE metaData (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, item1, item2);";
1777static const char PW_CREATE_CMD[] =
1778 "INSERT INTO metaData (id,item1,item2) VALUES($ID,$ITEM1,$ITEM2);";
1779static const char MD_CREATE_CMD[] =
1780 "INSERT INTO metaData (id,item1) VALUES($ID,$ITEM1);";
1781
1782CK_RV
1783sdb_PutMetaData(SDB *sdb, const char *id, const SECItem *item1,
1784 const SECItem *item2)
1785{
1786 SDBPrivate *sdb_p = sdb->private;
1787 sqlite3 *sqlDB = sdb_p->sqlXactDB;
1788 sqlite3_stmt *stmt = NULL((void*)0);
1789 int sqlerr = SQLITE_OK0;
1790 CK_RV error = CKR_OK0x00000000UL;
1791 int retry = 0;
1792 const char *cmd = PW_CREATE_CMD;
1793
1794 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1795 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1796 }
1797
1798 LOCK_SQLITE()
1799 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1800 if (error != CKR_OK0x00000000UL) {
1801 goto loser;
1802 }
1803
1804 if (!tableExists(sqlDB, "metaData")) {
1805 sqlerr = sqlite3_exec(sqlDB, PW_CREATE_TABLE_CMD, NULL((void*)0), 0, NULL((void*)0));
1806 if (sqlerr != SQLITE_OK0)
1807 goto loser;
1808 }
1809 if (item2 == NULL((void*)0)) {
1810 cmd = MD_CREATE_CMD;
1811 }
1812 sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL((void*)0));
1813 if (sqlerr != SQLITE_OK0)
1814 goto loser;
1815 sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id)strlen(id), SQLITE_STATIC((sqlite3_destructor_type)0));
1816 if (sqlerr != SQLITE_OK0)
1817 goto loser;
1818 sqlerr = sqlite3_bind_blob(stmt, 2, item1->data, item1->len, SQLITE_STATIC((sqlite3_destructor_type)0));
1819 if (sqlerr != SQLITE_OK0)
1820 goto loser;
1821 if (item2) {
1822 sqlerr = sqlite3_bind_blob(stmt, 3, item2->data,
1823 item2->len, SQLITE_STATIC((sqlite3_destructor_type)0));
1824 if (sqlerr != SQLITE_OK0)
1825 goto loser;
1826 }
1827
1828 do {
1829 sqlerr = sqlite3_step(stmt);
1830 if (sqlerr == SQLITE_BUSY5) {
1831 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1832 }
1833 } while (!sdb_done(sqlerr, &retry));
1834
1835loser:
1836 /* fix up the error if necessary */
1837 if (error == CKR_OK0x00000000UL) {
1838 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1839 }
1840
1841 if (stmt) {
1842 sqlite3_reset(stmt);
1843 sqlite3_finalize(stmt);
1844 }
1845
1846 if (sqlDB) {
1847 sdb_closeDBLocal(sdb_p, sqlDB);
1848 }
1849 UNLOCK_SQLITE()
1850
1851 return error;
1852}
1853
1854static const char RESET_CMD[] = "DELETE FROM %s;";
1855CK_RV
1856sdb_Reset(SDB *sdb)
1857{
1858 SDBPrivate *sdb_p = sdb->private;
1859 sqlite3 *sqlDB = NULL((void*)0);
1860 char *newStr;
1861 int sqlerr = SQLITE_OK0;
1862 CK_RV error = CKR_OK0x00000000UL;
1863
1864 /* only Key databases can be reset */
1865 if (sdb_p->type != SDB_KEY) {
1866 return CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1867 }
1868
1869 LOCK_SQLITE()
1870 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1871 if (error != CKR_OK0x00000000UL) {
1872 goto loser;
1873 }
1874
1875 if (tableExists(sqlDB, sdb_p->table)) {
1876 /* delete the contents of the key table */
1877 newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
1878 if (newStr == NULL((void*)0)) {
1879 error = CKR_HOST_MEMORY0x00000002UL;
1880 goto loser;
1881 }
1882 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
1883 sqlite3_free(newStr);
1884
1885 if (sqlerr != SQLITE_OK0)
1886 goto loser;
1887 }
1888
1889 /* delete the password entry table */
1890 sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;",
1891 NULL((void*)0), 0, NULL((void*)0));
1892
1893loser:
1894 /* fix up the error if necessary */
1895 if (error == CKR_OK0x00000000UL) {
1896 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1897 }
1898
1899 if (sqlDB) {
1900 sdb_closeDBLocal(sdb_p, sqlDB);
1901 }
1902
1903 UNLOCK_SQLITE()
1904 return error;
1905}
1906
1907CK_RV
1908sdb_Close(SDB *sdb)
1909{
1910 SDBPrivate *sdb_p = sdb->private;
1911 int sqlerr = SQLITE_OK0;
1912 sdbDataType type = sdb_p->type;
1913
1914 sqlerr = sqlite3_close(sdb_p->sqlReadDB);
1915 PORT_FreePORT_Free_Util(sdb_p->sqlDBName);
1916 if (sdb_p->cacheTable) {
1917 sqlite3_free(sdb_p->cacheTable);
1918 }
1919 if (sdb_p->dbMon) {
1920 PR_DestroyMonitor(sdb_p->dbMon);
1921 }
1922 free(sdb_p->schemaAttrs);
1923 free(sdb_p);
1924 free(sdb);
1925 return sdb_mapSQLError(type, sqlerr);
1926}
1927
1928/*
1929 * functions to support open
1930 */
1931
1932static const char CHECK_TABLE_CMD[] = "SELECT ALL * FROM %s LIMIT 0;";
1933
1934/* return 1 if sqlDB contains table 'tableName */
1935static int
1936tableExists(sqlite3 *sqlDB, const char *tableName)
1937{
1938 char *cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
1939 int sqlerr = SQLITE_OK0;
1940
1941 if (cmd == NULL((void*)0)) {
1942 return 0;
1943 }
1944
1945 sqlerr = sqlite3_exec(sqlDB, cmd, NULL((void*)0), 0, 0);
1946 sqlite3_free(cmd);
1947
1948 return (sqlerr == SQLITE_OK0) ? 1 : 0;
1949}
1950
1951void
1952sdb_SetForkState(PRBool forked)
1953{
1954 /* XXXright now this is a no-op. The global fork state in the softokn3
1955 * shared library is already taken care of at the PKCS#11 level.
1956 * If and when we add fork state to the sqlite shared library and extern
1957 * interface, we will need to set it and reset it from here */
1958}
1959
1960static int
1961sdb_attributeComparator(const void *a, const void *b)
1962{
1963 if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) {
1964 return -1;
1965 }
1966 if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) {
1967 return 1;
1968 }
1969 return 0;
1970}
1971
1972static const char ADD_COLUMN_CMD[] = "ALTER TABLE %s ADD COLUMN %s";
1973static CK_RV
1974sdb_add_column(sqlite3 *sqlDB, const char *table, sdbDataType type,
1975 const char *typeString)
1976{
1977 char *newStr = sqlite3_mprintf(ADD_COLUMN_CMD, table, typeString);
1978 int sqlerr;
1979
1980 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
1981 sqlite3_free(newStr);
1982 if (sqlerr != SQLITE_OK0) {
1983 return sdb_mapSQLError(type, sqlerr);
1984 }
1985 return CKR_OK0x00000000UL;
1986}
1987
1988static const char COLUMN_QUERY_CMD[] =
1989 "SELECT * FROM %s";
1990/*
1991 * if our current database does not have all the attributes in the columns,
1992 * we need to add those columns or attempts to add objects with those
1993 * attributes will fail. We only need this on R/W databases because we only
1994 * add objects to R/W databases.
1995 */
1996static CK_RV
1997sdb_update_column(sqlite3 *sqlDB, const char *table, sdbDataType type)
1998{
1999 char *newStr = sqlite3_mprintf(COLUMN_QUERY_CMD, table);
2000 sqlite3_stmt *stmt;
2001 int columnCount;
2002 int sqlerr;
2003 CK_RV error;
2004
2005 if (!newStr) {
2006 return CKR_HOST_MEMORY0x00000002UL;
2007 }
2008
2009 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
2010 sqlite3_free(newStr);
2011 if (sqlerr != SQLITE_OK0) {
2012 return sdb_mapSQLError(type, sqlerr);
2013 }
2014
2015 columnCount = sqlite3_column_count(stmt);
2016 /* columns include the first column, which is id, which is not
2017 * and attribute. check to make sure we have at least as many attributes
2018 * as there are id in out list. This assumes we never add some
2019 * attributes in some NSS version and not others, which is generally
2020 * true. */
2021 if (columnCount >= sftkdb_known_attributes_size + 1) {
2022 sqlite3_finalize(stmt);
2023 return CKR_OK0x00000000UL;
2024 }
2025 /* we have more attributes than in the database, so we know things
2026 * are missing, find what was missing */
2027 for (size_t i = 0; i < sftkdb_known_attributes_size; i++) {
2028 char *typeString = sqlite3_mprintf("a%lx", sftkdb_known_attributes[i]);
2029 PRBool found = PR_FALSE0;
2030 /* this one index is important, we skip the first column (id), since
2031 * it will never match, starting at zero isn't a bug,
2032 * just inefficient */
2033 for (int j = 1; j < columnCount; j++) {
2034 const char *columnName = sqlite3_column_name(stmt, j);
2035 if (columnName == NULL((void*)0)) {
2036 sqlite3_free(typeString);
2037 sqlite3_finalize(stmt);
2038 /* if we couldnt' get the colmun name, it's only because
2039 * we couldn't get the memory */
2040 return CKR_HOST_MEMORY0x00000002UL;
2041 }
2042 if (PORT_Strcmpstrcmp(typeString, columnName) == 0) {
2043 /* we found this one, no need to add it */
2044 found = PR_TRUE1;
2045 break;
2046 }
2047 }
2048 if (found) {
2049 sqlite3_free(typeString);
2050 continue;
2051 }
2052 /* we didn't find the attribute, so now add it */
2053 error = sdb_add_column(sqlDB, table, type, typeString);
2054 if (error != CKR_OK0x00000000UL) {
2055 sqlite3_free(typeString);
2056 sqlite3_finalize(stmt);
2057 return error;
2058 }
2059 sqlite3_free(typeString);
2060 }
2061 sqlite3_finalize(stmt);
2062 return CKR_OK0x00000000UL;
2063}
2064
2065/*
2066 * initialize a single database
2067 */
2068static const char INIT_CMD[] =
2069 "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)";
2070
2071CK_RV
2072sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
2073 int *newInit, int inFlags, PRUint32 accessOps, SDB **pSdb)
2074{
2075 char *initStr = NULL((void*)0);
2076 char *newStr;
2077 char *queryStr = NULL((void*)0);
2078 int inTransaction = 0;
2079 SDB *sdb = NULL((void*)0);
2080 SDBPrivate *sdb_p = NULL((void*)0);
2081 sqlite3 *sqlDB = NULL((void*)0);
2082 int sqlerr = SQLITE_OK0;
2083 CK_RV error = CKR_OK0x00000000UL;
2084 char *cacheTable = NULL((void*)0);
2085 PRIntervalTime now = 0;
2086 char *env;
2087 PRBool enableCache = PR_FALSE0;
2088 PRBool checkFSType = PR_FALSE0;
2089 PRBool measureSpeed = PR_FALSE0;
2090 PRBool create;
2091 int flags = inFlags & 0x7;
2092
2093 *pSdb = NULL((void*)0);
2094 *inUpdate = 0;
2095
2096 /* sqlite3 doesn't have a flag to specify that we want to
2097 * open the database read only. If the db doesn't exist,
2098 * sqlite3 will always create it.
2099 */
2100 LOCK_SQLITE();
2101 create = (_NSSUTIL_Access(dbname, PR_ACCESS_EXISTS)PR_Access((dbname), (PR_ACCESS_EXISTS)) != PR_SUCCESS);
2102 if ((flags == SDB_RDONLY1) && create) {
2103 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2104 goto loser;
2105 }
2106 sqlerr = sdb_openDB(dbname, &sqlDB, flags);
2107 if (sqlerr != SQLITE_OK0) {
2108 error = sdb_mapSQLError(type, sqlerr);
2109 goto loser;
2110 }
2111
2112 /*
2113 * SQL created the file, but it doesn't set appropriate modes for
2114 * a database.
2115 *
2116 * NO NSPR call for chmod? :(
2117 */
2118 if (create && sdb_chmod(dbname, 0600)chmod((dbname), (0600)) != 0) {
2119 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2120 goto loser;
2121 }
2122
2123 if (flags != SDB_RDONLY1) {
2124 sqlerr = sqlite3_exec(sqlDB, BEGIN_CMD, NULL((void*)0), 0, NULL((void*)0));
2125 if (sqlerr != SQLITE_OK0) {
2126 error = sdb_mapSQLError(type, sqlerr);
2127 goto loser;
2128 }
2129 inTransaction = 1;
2130 }
2131 if (!tableExists(sqlDB, table)) {
2132 *newInit = 1;
2133 if (flags != SDB_CREATE4) {
2134 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2135 goto loser;
2136 }
2137 initStr = sqlite3_mprintf("");
2138 for (size_t i = 0; initStr && i < sftkdb_known_attributes_size; i++) {
2139 newStr = sqlite3_mprintf("%s, a%lx", initStr,
2140 sftkdb_known_attributes[i]);
2141 sqlite3_free(initStr);
2142 initStr = newStr;
2143 }
2144 if (initStr == NULL((void*)0)) {
2145 error = CKR_HOST_MEMORY0x00000002UL;
2146 goto loser;
2147 }
2148
2149 newStr = sqlite3_mprintf(INIT_CMD, table, initStr);
2150 sqlite3_free(initStr);
2151 if (newStr == NULL((void*)0)) {
2152 error = CKR_HOST_MEMORY0x00000002UL;
2153 goto loser;
2154 }
2155 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2156 sqlite3_free(newStr);
2157 if (sqlerr != SQLITE_OK0) {
2158 error = sdb_mapSQLError(type, sqlerr);
2159 goto loser;
2160 }
2161
2162 newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, table);
2163 if (newStr == NULL((void*)0)) {
2164 error = CKR_HOST_MEMORY0x00000002UL;
2165 goto loser;
2166 }
2167 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2168 sqlite3_free(newStr);
2169 if (sqlerr != SQLITE_OK0) {
2170 error = sdb_mapSQLError(type, sqlerr);
2171 goto loser;
2172 }
2173
2174 newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, table);
2175 if (newStr == NULL((void*)0)) {
2176 error = CKR_HOST_MEMORY0x00000002UL;
2177 goto loser;
2178 }
2179 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2180 sqlite3_free(newStr);
2181 if (sqlerr != SQLITE_OK0) {
2182 error = sdb_mapSQLError(type, sqlerr);
2183 goto loser;
2184 }
2185
2186 newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, table);
2187 if (newStr == NULL((void*)0)) {
2188 error = CKR_HOST_MEMORY0x00000002UL;
2189 goto loser;
2190 }
2191 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2192 sqlite3_free(newStr);
2193 if (sqlerr != SQLITE_OK0) {
2194 error = sdb_mapSQLError(type, sqlerr);
2195 goto loser;
2196 }
2197
2198 newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, table);
2199 if (newStr == NULL((void*)0)) {
2200 error = CKR_HOST_MEMORY0x00000002UL;
2201 goto loser;
2202 }
2203 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2204 sqlite3_free(newStr);
2205 if (sqlerr != SQLITE_OK0) {
2206 error = sdb_mapSQLError(type, sqlerr);
2207 goto loser;
2208 }
2209 } else if (flags != SDB_RDONLY1) {
2210 /* check to see if we need to update the scheme, only need to
2211 * do this if we open r/w, since that's the only case where
2212 * it's a problem if the attribute colmumn are missing */
2213 error = sdb_update_column(sqlDB, table, type);
2214 if (error != CKR_OK0x00000000UL) {
2215 goto loser;
2216 }
2217 }
2218
2219 /*
2220 * detect the case where we have created the database, but have
2221 * not yet updated it.
2222 *
2223 * We only check the Key database because only the key database has
2224 * a metaData table. The metaData table is created when a password
2225 * is set, or in the case of update, when a password is supplied.
2226 * If no key database exists, then the update would have happened immediately
2227 * on noticing that the cert database didn't exist (see newInit set above).
2228 */
2229 if (type == SDB_KEY && !tableExists(sqlDB, "metaData")) {
2230 *newInit = 1;
2231 }
2232
2233 /* access to network filesystems are significantly slower than local ones
2234 * for database operations. In those cases we need to create a cached copy
2235 * of the database in a temporary location on the local disk. SQLITE
2236 * already provides a way to create a temporary table and initialize it,
2237 * so we use it for the cache (see sdb_buildCache for how it's done).*/
2238
2239 /*
2240 * we decide whether or not to use the cache based on the following input.
2241 *
2242 * NSS_SDB_USE_CACHE environment variable is set to anything other than
2243 * "yes" or "no" (for instance, "auto"): NSS will measure the performance
2244 * of access to the temp database versus the access to the user's
2245 * passed-in database location. If the temp database location is
2246 * "significantly" faster we will use the cache.
2247 *
2248 * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no":
2249 * cache will not be used.
2250 *
2251 * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will
2252 * always be used.
2253 *
2254 * It is expected that most applications will not need this feature, and
2255 * thus it is disabled by default.
2256 */
2257
2258 env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
2259
2260 /* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default,
2261 * which is the expected behavior for NSS_SDB_USE_CACHE="no".
2262 * We don't need to check for "no" here. */
2263 if (!env) {
2264 /* By default, with no variable set, we avoid expensive measuring for
2265 * most FS types. We start with inexpensive FS type checking, and
2266 * might perform measuring for some types. */
2267 checkFSType = PR_TRUE1;
2268 } else if (PORT_StrcasecmpPL_strcasecmp(env, "yes") == 0) {
2269 enableCache = PR_TRUE1;
2270 } else if (PORT_StrcasecmpPL_strcasecmp(env, "no") != 0) { /* not "no" => "auto" */
2271 measureSpeed = PR_TRUE1;
2272 }
2273
2274 if (checkFSType) {
2275#if defined(LINUX1) && !defined(ANDROID)
2276 struct statfs statfs_s;
2277 if (statfs(dbname, &statfs_s) == 0) {
2278 switch (statfs_s.f_type) {
2279 case SMB_SUPER_MAGIC0x517B:
2280 case 0xff534d42: /* CIFS_MAGIC_NUMBER */
2281 case NFS_SUPER_MAGIC0x6969:
2282 /* We assume these are slow. */
2283 enableCache = PR_TRUE1;
2284 break;
2285 case CODA_SUPER_MAGIC0x73757245:
2286 case 0x65735546: /* FUSE_SUPER_MAGIC */
2287 case NCP_SUPER_MAGIC0x564c:
2288 /* It's uncertain if this FS is fast or slow.
2289 * It seems reasonable to perform slow measuring for users
2290 * with questionable FS speed. */
2291 measureSpeed = PR_TRUE1;
2292 break;
2293 case AFS_SUPER_MAGIC0x5346414F: /* Already implements caching. */
2294 default:
2295 break;
2296 }
2297 }
2298#endif
2299 }
2300
2301 if (measureSpeed) {
2302 char *tempDir = NULL((void*)0);
2303 PRUint32 tempOps = 0;
2304 /*
2305 * Use PR_Access to determine how expensive it
2306 * is to check for the existance of a local file compared to the same
2307 * check in the temp directory. If the temp directory is faster, cache
2308 * the database there. */
2309 tempDir = sdb_getTempDir(sqlDB);
2310 if (tempDir) {
2311 tempOps = sdb_measureAccess(tempDir);
2312 PORT_FreePORT_Free_Util(tempDir);
2313
2314 /* There is a cost to continually copying the database.
2315 * Account for that cost with the arbitrary factor of 10 */
2316 enableCache = (PRBool)(tempOps > accessOps * 10);
2317 }
2318 }
2319
2320 if (enableCache) {
2321 /* try to set the temp store to memory.*/
2322 sqlite3_exec(sqlDB, "PRAGMA temp_store=MEMORY", NULL((void*)0), 0, NULL((void*)0));
2323 /* Failure to set the temp store to memory is not fatal,
2324 * ignore the error */
2325
2326 cacheTable = sqlite3_mprintf("%sCache", table);
2327 if (cacheTable == NULL((void*)0)) {
2328 error = CKR_HOST_MEMORY0x00000002UL;
2329 goto loser;
2330 }
2331 /* build the cache table */
2332 error = sdb_buildCache(sqlDB, type, cacheTable, table);
2333 if (error != CKR_OK0x00000000UL) {
2334 goto loser;
2335 }
2336 /* initialize the last cache build time */
2337 now = PR_IntervalNow();
2338 }
2339
2340 sdb = (SDB *)malloc(sizeof(SDB));
2341 if (!sdb) {
2342 error = CKR_HOST_MEMORY0x00000002UL;
2343 goto loser;
2344 }
2345 sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate));
2346 if (!sdb_p) {
2347 error = CKR_HOST_MEMORY0x00000002UL;
2348 goto loser;
2349 }
2350
2351 /* Cache the attributes that are held in the table, so we can later check
2352 * that queried attributes actually exist. We don't assume the schema
2353 * to be exactly |sftkdb_known_attributes|, as it may change over time. */
2354 sdb_p->schemaAttrs = NULL((void*)0);
2355 if (!PORT_Strcmpstrcmp("nssPublic", table) ||
2356 !PORT_Strcmpstrcmp("nssPrivate", table)) {
2357 sqlite3_stmt *stmt = NULL((void*)0);
2358 int retry = 0;
2359 unsigned int backedAttrs = 0;
2360
2361 /* Can't bind parameters to a PRAGMA. */
2362 queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table);
2363 if (queryStr == NULL((void*)0)) {
2364 error = CKR_HOST_MEMORY0x00000002UL;
2365 goto loser;
2366 }
2367 sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL((void*)0));
2368 sqlite3_free(queryStr);
2369 queryStr = NULL((void*)0);
2370 if (sqlerr != SQLITE_OK0) {
2371 goto loser;
2372 }
2373 unsigned int schemaAttrsCapacity = sftkdb_known_attributes_size;
2374 sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2375 if (!sdb_p->schemaAttrs) {
2376 error = CKR_HOST_MEMORY0x00000002UL;
2377 goto loser;
2378 }
2379 do {
2380 sqlerr = sqlite3_step(stmt);
2381 if (sqlerr == SQLITE_BUSY5) {
2382 PR_Sleep(SDB_BUSY_RETRY_TIME5);
2383 }
2384 if (sqlerr == SQLITE_ROW100) {
2385 if (backedAttrs == schemaAttrsCapacity) {
2386 schemaAttrsCapacity += sftkdb_known_attributes_size;
2387 sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs,
2388 schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2389 if (!sdb_p->schemaAttrs) {
2390 error = CKR_HOST_MEMORY0x00000002UL;
2391 goto loser;
2392 }
2393 }
2394 /* Record the ULONG attribute value. */
2395 char *val = (char *)sqlite3_column_text(stmt, 1);
2396 if (val && val[0] == 'a') {
2397 CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL((void*)0), 16);
2398 sdb_p->schemaAttrs[backedAttrs++] = attr;
2399 }
2400 }
2401 } while (!sdb_done(sqlerr, &retry));
2402
2403 if (sqlerr != SQLITE_DONE101) {
2404 goto loser;
2405 }
2406 sqlerr = sqlite3_reset(stmt);
2407 if (sqlerr != SQLITE_OK0) {
2408 goto loser;
2409 }
2410 sqlerr = sqlite3_finalize(stmt);
2411 if (sqlerr != SQLITE_OK0) {
2412 goto loser;
2413 }
2414
2415 sdb_p->numSchemaAttrs = backedAttrs;
2416
2417 /* Sort these once so we can shortcut invalid attribute searches. */
2418 qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs,
2419 sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator);
2420 }
2421
2422 /* invariant fields */
2423 sdb_p->sqlDBName = PORT_StrdupPORT_Strdup_Util(dbname);
2424 sdb_p->type = type;
2425 sdb_p->table = table;
2426 sdb_p->cacheTable = cacheTable;
2427 sdb_p->lastUpdateTime = now;
2428 /* set the cache delay time. This is how long we will wait before we
2429 * decide the existing cache is stale. Currently set to 10 sec */
2430 sdb_p->updateInterval = PR_SecondsToInterval(10);
2431 sdb_p->dbMon = PR_NewMonitor();
2432 /* these fields are protected by the lock */
2433 sdb_p->sqlXactDB = NULL((void*)0);
2434 sdb_p->sqlXactThread = NULL((void*)0);
2435 sdb->private = sdb_p;
2436 sdb->version = 1;
2437 sdb->sdb_flags = inFlags | SDB_HAS_META8;
2438 sdb->app_private = NULL((void*)0);
2439 sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
2440 sdb->sdb_FindObjects = sdb_FindObjects;
2441 sdb->sdb_FindObjectsFinal = sdb_FindObjectsFinal;
2442 sdb->sdb_GetAttributeValue = sdb_GetAttributeValue;
2443 sdb->sdb_SetAttributeValue = sdb_SetAttributeValue;
2444 sdb->sdb_CreateObject = sdb_CreateObject;
2445 sdb->sdb_DestroyObject = sdb_DestroyObject;
2446 sdb->sdb_GetMetaData = sdb_GetMetaData;
2447 sdb->sdb_PutMetaData = sdb_PutMetaData;
2448 sdb->sdb_DestroyMetaData = sdb_DestroyMetaData;
2449 sdb->sdb_Begin = sdb_Begin;
2450 sdb->sdb_Commit = sdb_Commit;
2451 sdb->sdb_Abort = sdb_Abort;
2452 sdb->sdb_Reset = sdb_Reset;
2453 sdb->sdb_Close = sdb_Close;
2454 sdb->sdb_SetForkState = sdb_SetForkState;
2455 sdb->sdb_GetNewObjectID = sdb_GetNewObjectID;
2456
2457 if (inTransaction) {
2458 sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL((void*)0), 0, NULL((void*)0));
2459 if (sqlerr != SQLITE_OK0) {
2460 error = sdb_mapSQLError(sdb_p->type, sqlerr);
2461 goto loser;
2462 }
2463 inTransaction = 0;
2464 }
2465
2466 sdb_p->sqlReadDB = sqlDB;
2467
2468 *pSdb = sdb;
2469 UNLOCK_SQLITE();
2470 return CKR_OK0x00000000UL;
2471
2472loser:
2473 /* lots of stuff to do */
2474 if (inTransaction) {
2475 sqlite3_exec(sqlDB, ROLLBACK_CMD, NULL((void*)0), 0, NULL((void*)0));
2476 }
2477 if (sdb) {
2478 free(sdb);
2479 }
2480 if (sdb_p) {
2481 if (sdb_p->schemaAttrs) {
2482 free(sdb_p->schemaAttrs);
2483 }
2484 free(sdb_p);
2485 }
2486 if (sqlDB) {
2487 sqlite3_close(sqlDB);
2488 }
2489 UNLOCK_SQLITE();
2490 return error;
2491}
2492
2493/* sdbopen */
2494CK_RV
2495s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
2496 int cert_version, int key_version, int flags,
2497 SDB **certdb, SDB **keydb, int *newInit)
2498{
2499 char *cert = sdb_BuildFileName(directory, certPrefix,
2500 "cert", cert_version);
2501 char *key = sdb_BuildFileName(directory, keyPrefix,
2502 "key", key_version);
2503 CK_RV error = CKR_OK0x00000000UL;
2504 int inUpdate;
2505 PRUint32 accessOps;
2506
2507 if (certdb)
2508 *certdb = NULL((void*)0);
2509 if (keydb)
2510 *keydb = NULL((void*)0);
2511 *newInit = 0;
2512
2513#ifdef SQLITE_UNSAFE_THREADS
2514 if (sqlite_lock == NULL((void*)0)) {
2515 sqlite_lock = PR_NewLock();
2516 if (sqlite_lock == NULL((void*)0)) {
2517 error = CKR_HOST_MEMORY0x00000002UL;
2518 goto loser;
2519 }
2520 }
2521#endif
2522
2523 /* how long does it take to test for a non-existant file in our working
2524 * directory? Allows us to test if we may be on a network file system */
2525 accessOps = 1;
2526 {
2527 char *env;
2528 env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
2529 /* If the environment variable is undefined or set to yes or no,
2530 * sdb_init() will ignore the value of accessOps, and we can skip the
2531 * measuring.*/
2532 if (env && PORT_StrcasecmpPL_strcasecmp(env, "no") != 0 &&
2533 PORT_StrcasecmpPL_strcasecmp(env, "yes") != 0) {
2534 accessOps = sdb_measureAccess(directory);
2535 }
2536 }
2537
2538 /*
2539 * open the cert data base
2540 */
2541 if (certdb) {
2542 /* initialize Certificate database */
2543 error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate,
2544 newInit, flags, accessOps, certdb);
2545 if (error != CKR_OK0x00000000UL) {
2546 goto loser;
2547 }
2548 }
2549
2550 /*
2551 * open the key data base:
2552 * NOTE:if we want to implement a single database, we open
2553 * the same database file as the certificate here.
2554 *
2555 * cert an key db's have different tables, so they will not
2556 * conflict.
2557 */
2558 if (keydb) {
2559 /* initialize the Key database */
2560 error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate,
2561 newInit, flags, accessOps, keydb);
2562 if (error != CKR_OK0x00000000UL) {
2563 goto loser;
2564 }
2565 }
2566
2567loser:
2568 if (cert) {
2569 sqlite3_free(cert);
2570 }
2571 if (key) {
2572 sqlite3_free(key);
2573 }
2574
2575 if (error != CKR_OK0x00000000UL) {
2576 /* currently redundant, but could be necessary if more code is added
2577 * just before loser */
2578 if (keydb && *keydb) {
2579 sdb_Close(*keydb);
2580 }
2581 if (certdb && *certdb) {
2582 sdb_Close(*certdb);
2583 }
2584 }
2585
2586 return error;
2587}
2588
2589CK_RV
2590s_shutdown()
2591{
2592#ifdef SQLITE_UNSAFE_THREADS
2593 if (sqlite_lock) {
2594 PR_DestroyLock(sqlite_lock);
2595 sqlite_lock = NULL((void*)0);
2596 }
2597#endif
2598 return CKR_OK0x00000000UL;
2599}