Bug Summary

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