Coverage Report

Created: 2025-07-01 06:25

/src/nss/lib/softoken/sdb.c
Line
Count
Source (jump to first uncovered line)
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_UNIX)
38
#include <unistd.h>
39
#endif
40
#if defined(LINUX) && !defined(ANDROID)
41
#include <linux/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
 */
53
static PRLock *sqlite_lock = NULL;
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
62
typedef 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
0
#define SDB_SQLITE_BUSY_TIMEOUT 1000 /* milliseconds */
89
0
#define SDB_BUSY_RETRY_TIME 5        /* 'ticks', varies by platforms */
90
0
#define SDB_MAX_BUSY_RETRIES 30
91
92
/*
93
 * known attributes
94
 */
95
static const CK_ATTRIBUTE_TYPE known_attributes[] = {
96
    CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
97
    CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
98
    CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
99
    CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
100
    CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
101
    CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
102
    CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
103
    CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
104
    CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
105
    CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
106
    CKA_PUBLIC_KEY_INFO, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
107
    CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
108
    CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
109
    CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
110
    CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
111
    CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_HW_FEATURE_TYPE,
112
    CKA_RESET_ON_INIT, CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y,
113
    CKA_RESOLUTION, CKA_CHAR_ROWS, CKA_CHAR_COLUMNS, CKA_COLOR,
114
    CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, CKA_ENCODING_METHODS, CKA_MIME_TYPES,
115
    CKA_MECHANISM_TYPE, CKA_REQUIRED_CMS_ATTRIBUTES,
116
    CKA_DEFAULT_CMS_ATTRIBUTES, CKA_SUPPORTED_CMS_ATTRIBUTES,
117
    CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE, CKA_NSS_TRUST, CKA_NSS_URL,
118
    CKA_NSS_EMAIL, CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP,
119
    CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES,
120
    CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED,
121
    CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC,
122
    CKA_NSS_OVERRIDE_EXTENSIONS, CKA_NSS_SERVER_DISTRUST_AFTER,
123
    CKA_NSS_EMAIL_DISTRUST_AFTER, CKA_TRUST_DIGITAL_SIGNATURE,
124
    CKA_TRUST_NON_REPUDIATION, CKA_TRUST_KEY_ENCIPHERMENT,
125
    CKA_TRUST_DATA_ENCIPHERMENT, CKA_TRUST_KEY_AGREEMENT,
126
    CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, CKA_TRUST_SERVER_AUTH,
127
    CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION,
128
    CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER,
129
    CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH,
130
    CKA_CERT_MD5_HASH, CKA_NSS_DB
131
};
132
133
static const int known_attributes_size = PR_ARRAY_SIZE(known_attributes);
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
148
struct 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
167
typedef 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
 */
176
const unsigned char SQLITE_EXPLICIT_NULL[] = { 0xa5, 0x0, 0x5a };
177
0
#define SQLITE_EXPLICIT_NULL_LEN 3
178
179
/*
180
 * determine when we've completed our tasks
181
 */
182
static int
183
sdb_done(int err, int *count)
184
0
{
185
    /* allow as many rows as the database wants to give */
186
0
    if (err == SQLITE_ROW) {
187
0
        *count = 0;
188
0
        return 0;
189
0
    }
190
0
    if (err != SQLITE_BUSY) {
191
0
        return 1;
192
0
    }
193
    /* err == SQLITE_BUSY, Dont' retry forever in this case */
194
0
    if (++(*count) >= SDB_MAX_BUSY_RETRIES) {
195
0
        return 1;
196
0
    }
197
0
    return 0;
198
0
}
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
206
static int
207
sdb_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_Free(filenameWide);
221
222
    return result;
223
}
224
#else
225
0
#define sdb_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)
233
static char *
234
sdb_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;
248
    len = strlen(path);
249
    if (len == 0)
250
        return NULL;
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_Strdup(path);
255
}
256
#elif defined(XP_UNIX)
257
static char *
258
sdb_getFallbackTempDir(void)
259
0
{
260
0
    const char *azDirs[] = {
261
0
        NULL,
262
0
        NULL,
263
0
        "/var/tmp",
264
0
        "/usr/tmp",
265
0
        "/tmp",
266
        NULL /* List terminator */
267
0
    };
268
0
    unsigned int i;
269
0
    struct stat buf;
270
0
    const char *zDir = NULL;
271
272
0
    azDirs[0] = sqlite3_temp_directory;
273
0
    azDirs[1] = PR_GetEnvSecure("TMPDIR");
274
275
0
    for (i = 0; i < PR_ARRAY_SIZE(azDirs); i++) {
276
0
        zDir = azDirs[i];
277
0
        if (zDir == NULL)
278
0
            continue;
279
0
        if (stat(zDir, &buf))
280
0
            continue;
281
0
        if (!S_ISDIR(buf.st_mode))
282
0
            continue;
283
0
        if (access(zDir, 07))
284
0
            continue;
285
0
        break;
286
0
    }
287
288
0
    if (zDir == NULL)
289
0
        return NULL;
290
0
    return PORT_Strdup(zDir);
291
0
}
292
#else
293
#error "sdb_getFallbackTempDir not implemented"
294
#endif
295
296
#ifndef SQLITE_FCNTL_TEMPFILENAME
297
/* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */
298
#define SQLITE_FCNTL_TEMPFILENAME 16
299
#endif
300
301
static char *
302
sdb_getTempDir(sqlite3 *sqlDB)
303
0
{
304
0
    int sqlrv;
305
0
    char *result = NULL;
306
0
    char *tempName = NULL;
307
0
    char *foundSeparator = NULL;
308
309
    /* Obtain temporary filename in sqlite's directory for temporary tables */
310
0
    sqlrv = sqlite3_file_control(sqlDB, 0, SQLITE_FCNTL_TEMPFILENAME,
311
0
                                 (void *)&tempName);
312
0
    if (sqlrv == SQLITE_NOTFOUND) {
313
        /* SQLITE_FCNTL_TEMPFILENAME not implemented because we are using
314
         * an older SQLite. */
315
0
        return sdb_getFallbackTempDir();
316
0
    }
317
0
    if (sqlrv != SQLITE_OK) {
318
0
        return NULL;
319
0
    }
320
321
    /* We'll extract the temporary directory from tempName */
322
0
    foundSeparator = PORT_Strrchr(tempName, PR_GetDirectorySeparator());
323
0
    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
0
        ++foundSeparator;
334
0
        *foundSeparator = 0;
335
336
        /* Now we copy the directory name for our caller */
337
0
        result = PORT_Strdup(tempName);
338
0
    }
339
340
0
    sqlite3_free(tempName);
341
0
    return result;
342
0
}
343
344
/*
345
 * Map SQL_LITE errors to PKCS #11 errors as best we can.
346
 */
347
static CK_RV
348
sdb_mapSQLError(sdbDataType type, int sqlerr)
349
0
{
350
0
    switch (sqlerr) {
351
        /* good matches */
352
0
        case SQLITE_OK:
353
0
        case SQLITE_DONE:
354
0
            return CKR_OK;
355
0
        case SQLITE_NOMEM:
356
0
            return CKR_HOST_MEMORY;
357
0
        case SQLITE_READONLY:
358
0
            return CKR_TOKEN_WRITE_PROTECTED;
359
        /* close matches */
360
0
        case SQLITE_AUTH:
361
0
        case SQLITE_PERM:
362
        /*return CKR_USER_NOT_LOGGED_IN; */
363
0
        case SQLITE_CANTOPEN:
364
0
        case SQLITE_NOTFOUND:
365
            /* NSS distiguishes between failure to open the cert and the key db */
366
0
            return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED : CKR_NSS_KEYDB_FAILED;
367
0
        case SQLITE_IOERR:
368
0
            return CKR_DEVICE_ERROR;
369
0
        default:
370
0
            break;
371
0
    }
372
0
    return CKR_GENERAL_ERROR;
373
0
}
374
375
/*
376
 * build up database name from a directory, prefix, name, version and flags.
377
 */
378
static char *
379
sdb_BuildFileName(const char *directory,
380
                  const char *prefix, const char *type,
381
                  int version)
382
0
{
383
0
    char *dbname = NULL;
384
    /* build the full dbname */
385
0
    dbname = sqlite3_mprintf("%s%c%s%s%d.db", directory,
386
0
                             (int)(unsigned char)PR_GetDirectorySeparator(),
387
0
                             prefix, type, version);
388
0
    return dbname;
389
0
}
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
 */
395
static PRUint32
396
sdb_measureAccess(const char *directory)
397
0
{
398
0
    PRUint32 i;
399
0
    PRIntervalTime time;
400
0
    PRIntervalTime delta;
401
0
    PRIntervalTime duration = PR_MillisecondsToInterval(33);
402
0
    const char *doesntExistName = "_dOeSnotExist_.db";
403
0
    char *temp, *tempStartOfFilename;
404
0
    size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
405
0
#ifdef SDB_MEASURE_USE_TEMP_DIR
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
0
    const char template[] = "dbTemp.XXXXXX";
416
0
    tmpdirLength = sizeof(template);
417
0
#endif
418
    /* no directory, just return one */
419
0
    if (directory == NULL) {
420
0
        return 1;
421
0
    }
422
423
    /* our calculation assumes time is a 4 bytes == 32 bit integer */
424
0
    PORT_Assert(sizeof(time) == 4);
425
426
0
    directoryLength = strlen(directory);
427
428
0
    maxTempLen = directoryLength + 1       /* dirname + / */
429
0
                 + tmpdirLength            /* tmpdirname includes / */
430
0
                 + strlen(doesntExistName) /* filename base */
431
0
                 + 11                      /* max chars for 32 bit int plus potential sign */
432
0
                 + 1;                      /* zero terminator */
433
434
0
    temp = PORT_ZAlloc(maxTempLen);
435
0
    if (!temp) {
436
0
        return 1;
437
0
    }
438
439
    /* We'll copy directory into temp just once, then ensure it ends
440
     * with the directory separator. */
441
442
0
    strcpy(temp, directory);
443
0
    if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
444
0
        temp[directoryLength++] = PR_GetDirectorySeparator();
445
0
    }
446
447
0
#ifdef SDB_MEASURE_USE_TEMP_DIR
448
    /* add the template for a temporary subdir, and create it */
449
0
    strcat(temp, template);
450
0
    if (!mkdtemp(temp)) {
451
0
        PORT_Free(temp);
452
0
        return 1;
453
0
    }
454
    /* and terminate that tmp subdir with a / */
455
0
    strcat(temp, "/");
456
0
#endif
457
458
    /* Remember the position after the last separator, and calculate the
459
     * number of remaining bytes. */
460
0
    tempStartOfFilename = temp + directoryLength + tmpdirLength;
461
0
    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
0
    time = PR_IntervalNow();
467
0
    for (i = 0; i < 10000u; i++) {
468
0
        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
0
        PR_snprintf(tempStartOfFilename, maxFileNameLen,
476
0
                    ".%lu%s", (PRUint32)(time + i), doesntExistName);
477
0
        PR_Access(temp, PR_ACCESS_EXISTS);
478
0
        next = PR_IntervalNow();
479
0
        delta = next - time;
480
0
        if (delta >= duration)
481
0
            break;
482
0
    }
483
484
0
#ifdef SDB_MEASURE_USE_TEMP_DIR
485
    /* turn temp back into our tmpdir path by removing doesntExistName, and
486
     * remove the tmp dir */
487
0
    *tempStartOfFilename = '\0';
488
0
    (void)rmdir(temp);
489
0
#endif
490
0
    PORT_Free(temp);
491
492
    /* always return 1 or greater */
493
0
    return i ? i : 1u;
494
0
}
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
 */
504
static const char DROP_CACHE_CMD[] = "DROP TABLE %s";
505
static const char CREATE_CACHE_CMD[] =
506
    "CREATE TEMPORARY TABLE %s AS SELECT * FROM %s";
507
static const char CREATE_ISSUER_INDEX_CMD[] =
508
    "CREATE INDEX issuer ON %s (a81)";
509
static const char CREATE_SUBJECT_INDEX_CMD[] =
510
    "CREATE INDEX subject ON %s (a101)";
511
static const char CREATE_LABEL_INDEX_CMD[] = "CREATE INDEX label ON %s (a3)";
512
static const char CREATE_ID_INDEX_CMD[] = "CREATE INDEX ckaid ON %s (a102)";
513
514
static CK_RV
515
sdb_buildCache(sqlite3 *sqlDB, sdbDataType type,
516
               const char *cacheTable, const char *table)
517
0
{
518
0
    char *newStr;
519
0
    int sqlerr = SQLITE_OK;
520
521
0
    newStr = sqlite3_mprintf(CREATE_CACHE_CMD, cacheTable, table);
522
0
    if (newStr == NULL) {
523
0
        return CKR_HOST_MEMORY;
524
0
    }
525
0
    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
526
0
    sqlite3_free(newStr);
527
0
    if (sqlerr != SQLITE_OK) {
528
0
        return sdb_mapSQLError(type, sqlerr);
529
0
    }
530
    /* failure to create the indexes is not an issue */
531
0
    newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, cacheTable);
532
0
    if (newStr == NULL) {
533
0
        return CKR_OK;
534
0
    }
535
0
    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
536
0
    sqlite3_free(newStr);
537
0
    newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, cacheTable);
538
0
    if (newStr == NULL) {
539
0
        return CKR_OK;
540
0
    }
541
0
    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
542
0
    sqlite3_free(newStr);
543
0
    newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, cacheTable);
544
0
    if (newStr == NULL) {
545
0
        return CKR_OK;
546
0
    }
547
0
    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
548
0
    sqlite3_free(newStr);
549
0
    newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, cacheTable);
550
0
    if (newStr == NULL) {
551
0
        return CKR_OK;
552
0
    }
553
0
    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
554
0
    sqlite3_free(newStr);
555
0
    return CKR_OK;
556
0
}
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
 */
562
static CK_RV
563
sdb_updateCache(SDBPrivate *sdb_p)
564
0
{
565
0
    int sqlerr = SQLITE_OK;
566
0
    CK_RV error = CKR_OK;
567
0
    char *newStr;
568
569
    /* drop the old table */
570
0
    newStr = sqlite3_mprintf(DROP_CACHE_CMD, sdb_p->cacheTable);
571
0
    if (newStr == NULL) {
572
0
        return CKR_HOST_MEMORY;
573
0
    }
574
0
    sqlerr = sqlite3_exec(sdb_p->sqlReadDB, newStr, NULL, 0, NULL);
575
0
    sqlite3_free(newStr);
576
0
    if ((sqlerr != SQLITE_OK) && (sqlerr != SQLITE_ERROR)) {
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
0
        return sdb_mapSQLError(sdb_p->type, sqlerr);
581
0
    }
582
583
    /* set up the new table */
584
0
    error = sdb_buildCache(sdb_p->sqlReadDB, sdb_p->type,
585
0
                           sdb_p->cacheTable, sdb_p->table);
586
0
    if (error == CKR_OK) {
587
        /* we have a new cache! */
588
0
        sdb_p->lastUpdateTime = PR_IntervalNow();
589
0
    }
590
0
    return error;
591
0
}
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
 */
626
static CK_RV
627
sdb_openDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB, const char **table)
628
0
{
629
0
    *sqlDB = NULL;
630
631
0
    PR_EnterMonitor(sdb_p->dbMon);
632
633
0
    if (table) {
634
0
        *table = sdb_p->table;
635
0
    }
636
637
    /* We're in a transaction, use the transaction DB */
638
0
    if ((sdb_p->sqlXactDB) && (sdb_p->sqlXactThread == PR_GetCurrentThread())) {
639
0
        *sqlDB = sdb_p->sqlXactDB;
640
        /* only one thread can get here, safe to unlock */
641
0
        PR_ExitMonitor(sdb_p->dbMon);
642
0
        return CKR_OK;
643
0
    }
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
0
    if (table && sdb_p->cacheTable) {
652
0
        PRIntervalTime now = PR_IntervalNow();
653
0
        if ((now - sdb_p->lastUpdateTime) > sdb_p->updateInterval) {
654
0
            sdb_updateCache(sdb_p);
655
0
        }
656
0
        *table = sdb_p->cacheTable;
657
0
    }
658
659
0
    *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
0
    return CKR_OK;
665
0
}
666
667
/* closing the local database currenly means unlocking the monitor */
668
static CK_RV
669
sdb_closeDBLocal(SDBPrivate *sdb_p, sqlite3 *sqlDB)
670
0
{
671
0
    if (sdb_p->sqlXactDB != sqlDB) {
672
        /* if we weren't in a transaction, we got a lock */
673
0
        PR_ExitMonitor(sdb_p->dbMon);
674
0
    }
675
0
    return CKR_OK;
676
0
}
677
678
/*
679
 * wrapper to sqlite3_open which also sets the busy_timeout
680
 */
681
static int
682
sdb_openDB(const char *name, sqlite3 **sqlDB, int flags)
683
0
{
684
0
    int sqlerr;
685
0
    int openFlags;
686
687
0
    *sqlDB = NULL;
688
689
0
    if (flags & SDB_RDONLY) {
690
0
        openFlags = SQLITE_OPEN_READONLY;
691
0
    } else {
692
0
        openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
693
        /* sqlite 3.34 seem to incorrectly open readwrite.
694
         * when the file is readonly. Explicitly reject that issue here */
695
0
        if ((_NSSUTIL_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) && (_NSSUTIL_Access(name, PR_ACCESS_WRITE_OK) != PR_SUCCESS)) {
696
0
            return SQLITE_READONLY;
697
0
        }
698
0
    }
699
700
    /* Requires SQLite 3.5.0 or newer. */
701
0
    sqlerr = sqlite3_open_v2(name, sqlDB, openFlags, NULL);
702
0
    if (sqlerr != SQLITE_OK) {
703
0
        return sqlerr;
704
0
    }
705
706
0
    sqlerr = sqlite3_busy_timeout(*sqlDB, SDB_SQLITE_BUSY_TIMEOUT);
707
0
    if (sqlerr != SQLITE_OK) {
708
0
        sqlite3_close(*sqlDB);
709
0
        *sqlDB = NULL;
710
0
        return sqlerr;
711
0
    }
712
0
    return SQLITE_OK;
713
0
}
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. */
719
static int
720
sdb_reopenDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB)
721
0
{
722
0
    sqlite3 *newDB;
723
0
    int sqlerr;
724
725
    /* open a new database */
726
0
    sqlerr = sdb_openDB(sdb_p->sqlDBName, &newDB, SDB_RDONLY);
727
0
    if (sqlerr != SQLITE_OK) {
728
0
        return sqlerr;
729
0
    }
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
0
    PR_EnterMonitor(sdb_p->dbMon);
735
    /* update our view of the database */
736
0
    if (sdb_p->sqlReadDB == *sqlDB) {
737
0
        sdb_p->sqlReadDB = newDB;
738
0
    } else if (sdb_p->sqlXactDB == *sqlDB) {
739
0
        sdb_p->sqlXactDB = newDB;
740
0
    }
741
0
    PR_ExitMonitor(sdb_p->dbMon);
742
743
    /* close the old one */
744
0
    sqlite3_close(*sqlDB);
745
746
0
    *sqlDB = newDB;
747
0
    return SQLITE_OK;
748
0
}
749
750
struct SDBFindStr {
751
    sqlite3 *sqlDB;
752
    sqlite3_stmt *findstmt;
753
};
754
755
static const char FIND_OBJECTS_CMD[] = "SELECT ALL id FROM %s WHERE %s;";
756
static const char FIND_OBJECTS_ALL_CMD[] = "SELECT ALL id FROM %s;";
757
CK_RV
758
sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count,
759
                    SDBFind **find)
760
0
{
761
0
    SDBPrivate *sdb_p = sdb->private;
762
0
    sqlite3 *sqlDB = NULL;
763
0
    const char *table;
764
0
    char *newStr, *findStr = NULL;
765
0
    sqlite3_stmt *findstmt = NULL;
766
0
    char *join = "";
767
0
    int sqlerr = SQLITE_OK;
768
0
    CK_RV error = CKR_OK;
769
0
    unsigned int i;
770
771
0
    LOCK_SQLITE()
772
0
    *find = NULL;
773
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
774
0
    if (error != CKR_OK) {
775
0
        goto loser;
776
0
    }
777
778
0
    findStr = sqlite3_mprintf("");
779
0
    for (i = 0; findStr && i < count; i++) {
780
0
        newStr = sqlite3_mprintf("%s%sa%x=$DATA%d", findStr, join,
781
0
                                 template[i].type, i);
782
0
        join = " AND ";
783
0
        sqlite3_free(findStr);
784
0
        findStr = newStr;
785
0
    }
786
787
0
    if (findStr == NULL) {
788
0
        error = CKR_HOST_MEMORY;
789
0
        goto loser;
790
0
    }
791
792
0
    if (count == 0) {
793
0
        newStr = sqlite3_mprintf(FIND_OBJECTS_ALL_CMD, table);
794
0
    } else {
795
0
        newStr = sqlite3_mprintf(FIND_OBJECTS_CMD, table, findStr);
796
0
    }
797
0
    sqlite3_free(findStr);
798
0
    if (newStr == NULL) {
799
0
        error = CKR_HOST_MEMORY;
800
0
        goto loser;
801
0
    }
802
0
    sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &findstmt, NULL);
803
0
    sqlite3_free(newStr);
804
0
    for (i = 0; sqlerr == SQLITE_OK && i < count; i++) {
805
0
        const void *blobData = template[i].pValue;
806
0
        unsigned int blobSize = template[i].ulValueLen;
807
0
        if (blobSize == 0) {
808
0
            blobSize = SQLITE_EXPLICIT_NULL_LEN;
809
0
            blobData = SQLITE_EXPLICIT_NULL;
810
0
        }
811
0
        sqlerr = sqlite3_bind_blob(findstmt, i + 1, blobData, blobSize,
812
0
                                   SQLITE_TRANSIENT);
813
0
    }
814
0
    if (sqlerr == SQLITE_OK) {
815
0
        *find = PORT_New(SDBFind);
816
0
        if (*find == NULL) {
817
0
            error = CKR_HOST_MEMORY;
818
0
            goto loser;
819
0
        }
820
0
        (*find)->findstmt = findstmt;
821
0
        (*find)->sqlDB = sqlDB;
822
0
        UNLOCK_SQLITE()
823
0
        return CKR_OK;
824
0
    }
825
0
    error = sdb_mapSQLError(sdb_p->type, sqlerr);
826
827
0
loser:
828
0
    if (findstmt) {
829
0
        sqlite3_reset(findstmt);
830
0
        sqlite3_finalize(findstmt);
831
0
    }
832
0
    if (sqlDB) {
833
0
        sdb_closeDBLocal(sdb_p, sqlDB);
834
0
    }
835
0
    UNLOCK_SQLITE()
836
0
    return error;
837
0
}
838
839
CK_RV
840
sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
841
                CK_ULONG arraySize, CK_ULONG *count)
842
0
{
843
0
    SDBPrivate *sdb_p = sdb->private;
844
0
    sqlite3_stmt *stmt = sdbFind->findstmt;
845
0
    int sqlerr = SQLITE_OK;
846
0
    int retry = 0;
847
848
0
    *count = 0;
849
850
0
    if (arraySize == 0) {
851
0
        return CKR_OK;
852
0
    }
853
0
    LOCK_SQLITE()
854
855
0
    do {
856
0
        sqlerr = sqlite3_step(stmt);
857
0
        if (sqlerr == SQLITE_BUSY) {
858
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
859
0
        }
860
0
        if (sqlerr == SQLITE_ROW) {
861
            /* only care about the id */
862
0
            *object++ = sqlite3_column_int(stmt, 0);
863
0
            arraySize--;
864
0
            (*count)++;
865
0
        }
866
0
    } 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
0
    if (sqlerr == SQLITE_ROW && arraySize == 0) {
871
0
        sqlerr = SQLITE_DONE;
872
0
    }
873
0
    UNLOCK_SQLITE()
874
875
0
    return sdb_mapSQLError(sdb_p->type, sqlerr);
876
0
}
877
878
CK_RV
879
sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
880
0
{
881
0
    SDBPrivate *sdb_p = sdb->private;
882
0
    sqlite3_stmt *stmt = sdbFind->findstmt;
883
0
    sqlite3 *sqlDB = sdbFind->sqlDB;
884
0
    int sqlerr = SQLITE_OK;
885
886
0
    LOCK_SQLITE()
887
0
    if (stmt) {
888
0
        sqlite3_reset(stmt);
889
0
        sqlerr = sqlite3_finalize(stmt);
890
0
    }
891
0
    if (sqlDB) {
892
0
        sdb_closeDBLocal(sdb_p, sqlDB);
893
0
    }
894
0
    PORT_Free(sdbFind);
895
896
0
    UNLOCK_SQLITE()
897
0
    return sdb_mapSQLError(sdb_p->type, sqlerr);
898
0
}
899
900
static CK_RV
901
sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
902
                                 CK_ATTRIBUTE *template, CK_ULONG count)
903
0
{
904
0
    SDBPrivate *sdb_p = sdb->private;
905
0
    sqlite3 *sqlDB = NULL;
906
0
    sqlite3_stmt *stmt = NULL;
907
0
    const char *table = NULL;
908
0
    int sqlerr = SQLITE_OK;
909
0
    CK_RV error = CKR_OK;
910
0
    int found = 0;
911
0
    int retry = 0;
912
0
    unsigned int i;
913
914
0
    if (count == 0) {
915
0
        error = CKR_OBJECT_HANDLE_INVALID;
916
0
        goto loser;
917
0
    }
918
919
    /* open a new db if necessary */
920
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
921
0
    if (error != CKR_OK) {
922
0
        goto loser;
923
0
    }
924
925
0
    char *columns = NULL;
926
0
    for (i = 0; i < count; i++) {
927
0
        char *newColumns;
928
0
        if (columns) {
929
0
            newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
930
0
            sqlite3_free(columns);
931
0
            columns = NULL;
932
0
        } else {
933
0
            newColumns = sqlite3_mprintf("a%x", template[i].type);
934
0
        }
935
0
        if (!newColumns) {
936
0
            error = CKR_HOST_MEMORY;
937
0
            goto loser;
938
0
        }
939
0
        columns = newColumns;
940
0
    }
941
942
0
    PORT_Assert(columns);
943
944
0
    char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
945
0
                                      columns, table);
946
0
    sqlite3_free(columns);
947
0
    columns = NULL;
948
0
    if (!statement) {
949
0
        error = CKR_HOST_MEMORY;
950
0
        goto loser;
951
0
    }
952
953
0
    sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL);
954
0
    sqlite3_free(statement);
955
0
    statement = NULL;
956
0
    if (sqlerr != SQLITE_OK) {
957
0
        goto loser;
958
0
    }
959
960
    // NB: indices in sqlite3_bind_int are 1-indexed
961
0
    sqlerr = sqlite3_bind_int(stmt, 1, object_id);
962
0
    if (sqlerr != SQLITE_OK) {
963
0
        goto loser;
964
0
    }
965
966
0
    do {
967
0
        sqlerr = sqlite3_step(stmt);
968
0
        if (sqlerr == SQLITE_BUSY) {
969
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
970
0
        }
971
0
        if (sqlerr == SQLITE_ROW) {
972
0
            PORT_Assert(!found);
973
0
            for (i = 0; i < count; i++) {
974
0
                unsigned int blobSize;
975
0
                const char *blobData;
976
977
                // NB: indices in sqlite_column_{bytes,blob} are 0-indexed
978
0
                blobSize = sqlite3_column_bytes(stmt, i);
979
0
                blobData = sqlite3_column_blob(stmt, i);
980
0
                if (blobData == NULL) {
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
0
                    template[i].ulValueLen = -1;
985
0
                    error = CKR_ATTRIBUTE_TYPE_INVALID;
986
0
                    continue;
987
0
                }
988
                /* If the blob equals our explicit NULL value, then the
989
                 * attribute is a NULL. */
990
0
                if ((blobSize == SQLITE_EXPLICIT_NULL_LEN) &&
991
0
                    (PORT_Memcmp(blobData, SQLITE_EXPLICIT_NULL,
992
0
                                 SQLITE_EXPLICIT_NULL_LEN) == 0)) {
993
0
                    blobSize = 0;
994
0
                }
995
0
                if (template[i].pValue) {
996
0
                    if (template[i].ulValueLen < blobSize) {
997
                        /* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
998
0
                        template[i].ulValueLen = -1;
999
0
                        error = CKR_BUFFER_TOO_SMALL;
1000
0
                        continue;
1001
0
                    }
1002
0
                    PORT_Memcpy(template[i].pValue, blobData, blobSize);
1003
0
                }
1004
0
                template[i].ulValueLen = blobSize;
1005
0
            }
1006
0
            found = 1;
1007
0
        }
1008
0
    } while (!sdb_done(sqlerr, &retry));
1009
1010
0
    sqlite3_reset(stmt);
1011
0
    sqlite3_finalize(stmt);
1012
0
    stmt = NULL;
1013
1014
0
loser:
1015
    /* fix up the error if necessary */
1016
0
    if (error == CKR_OK) {
1017
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1018
0
        if (!found && error == CKR_OK) {
1019
0
            error = CKR_OBJECT_HANDLE_INVALID;
1020
0
        }
1021
0
    }
1022
1023
0
    if (stmt) {
1024
0
        sqlite3_reset(stmt);
1025
0
        sqlite3_finalize(stmt);
1026
0
    }
1027
1028
    /* if we had to open a new database, free it now */
1029
0
    if (sqlDB) {
1030
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1031
0
    }
1032
0
    return error;
1033
0
}
1034
1035
/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */
1036
inline static PRBool
1037
sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr)
1038
0
{
1039
0
    SDBPrivate *sdb_p = sdb->private;
1040
0
    int first = 0;
1041
0
    int last = (int)sdb_p->numSchemaAttrs - 1;
1042
0
    while (last >= first) {
1043
0
        int mid = first + (last - first) / 2;
1044
0
        if (sdb_p->schemaAttrs[mid] == attr) {
1045
0
            return PR_TRUE;
1046
0
        }
1047
0
        if (attr > sdb_p->schemaAttrs[mid]) {
1048
0
            first = mid + 1;
1049
0
        } else {
1050
0
            last = mid - 1;
1051
0
        }
1052
0
    }
1053
1054
0
    return PR_FALSE;
1055
0
}
1056
1057
CK_RV
1058
sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1059
                      CK_ATTRIBUTE *template, CK_ULONG count)
1060
0
{
1061
0
    CK_RV crv = CKR_OK;
1062
0
    unsigned int tmplIdx;
1063
0
    unsigned int resIdx = 0;
1064
0
    unsigned int validCount = 0;
1065
0
    unsigned int i;
1066
1067
0
    if (count == 0) {
1068
0
        return crv;
1069
0
    }
1070
1071
0
    CK_ATTRIBUTE *validTemplate;
1072
0
    PRBool invalidExists = PR_FALSE;
1073
0
    for (tmplIdx = 0; tmplIdx < count; tmplIdx++) {
1074
0
        if (!sdb_attributeExists(sdb, template[tmplIdx].type)) {
1075
0
            template[tmplIdx].ulValueLen = -1;
1076
0
            crv = CKR_ATTRIBUTE_TYPE_INVALID;
1077
0
            invalidExists = PR_TRUE;
1078
0
            break;
1079
0
        }
1080
0
    }
1081
1082
0
    if (!invalidExists) {
1083
0
        validTemplate = template;
1084
0
        validCount = count;
1085
0
    } else {
1086
        /* Create a new template containing only the valid subset of
1087
         * input |template|, and query with that. */
1088
0
        validCount = tmplIdx;
1089
0
        validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count);
1090
0
        if (!validTemplate) {
1091
0
            return CKR_HOST_MEMORY;
1092
0
        }
1093
        /* Copy in what we already know is valid. */
1094
0
        for (i = 0; i < validCount; i++) {
1095
0
            validTemplate[i] = template[i];
1096
0
        }
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
0
        tmplIdx++;
1102
0
        for (; tmplIdx < count; tmplIdx++) {
1103
0
            if (sdb_attributeExists(sdb, template[tmplIdx].type)) {
1104
0
                validTemplate[validCount++] = template[tmplIdx];
1105
0
            } else {
1106
0
                template[tmplIdx].ulValueLen = -1;
1107
0
            }
1108
0
        }
1109
0
    }
1110
1111
0
    if (validCount) {
1112
0
        LOCK_SQLITE()
1113
0
        CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount);
1114
0
        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
0
        crv = (crv2 == CKR_OK) ? crv : crv2;
1120
0
    }
1121
1122
0
    if (invalidExists) {
1123
        /* Copy out valid lengths. */
1124
0
        tmplIdx = 0;
1125
0
        for (resIdx = 0; resIdx < validCount; resIdx++) {
1126
0
            for (; tmplIdx < count; tmplIdx++) {
1127
0
                if (template[tmplIdx].type != validTemplate[resIdx].type) {
1128
0
                    continue;
1129
0
                }
1130
0
                template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen;
1131
0
                tmplIdx++;
1132
0
                break;
1133
0
            }
1134
0
        }
1135
0
        free(validTemplate);
1136
0
    }
1137
1138
0
    return crv;
1139
0
}
1140
1141
static const char SET_ATTRIBUTE_CMD[] = "UPDATE %s SET %s WHERE id=$ID;";
1142
CK_RV
1143
sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1144
                      const CK_ATTRIBUTE *template, CK_ULONG count)
1145
0
{
1146
0
    SDBPrivate *sdb_p = sdb->private;
1147
0
    sqlite3 *sqlDB = NULL;
1148
0
    sqlite3_stmt *stmt = NULL;
1149
0
    char *setStr = NULL;
1150
0
    char *newStr = NULL;
1151
0
    int sqlerr = SQLITE_OK;
1152
0
    int retry = 0;
1153
0
    CK_RV error = CKR_OK;
1154
0
    unsigned int i;
1155
1156
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1157
0
        return CKR_TOKEN_WRITE_PROTECTED;
1158
0
    }
1159
1160
0
    if (count == 0) {
1161
0
        return CKR_OK;
1162
0
    }
1163
1164
0
    LOCK_SQLITE()
1165
0
    setStr = sqlite3_mprintf("");
1166
0
    for (i = 0; setStr && i < count; i++) {
1167
0
        if (i == 0) {
1168
0
            sqlite3_free(setStr);
1169
0
            setStr = sqlite3_mprintf("a%x=$VALUE%d",
1170
0
                                     template[i].type, i);
1171
0
            continue;
1172
0
        }
1173
0
        newStr = sqlite3_mprintf("%s,a%x=$VALUE%d", setStr,
1174
0
                                 template[i].type, i);
1175
0
        sqlite3_free(setStr);
1176
0
        setStr = newStr;
1177
0
    }
1178
0
    newStr = NULL;
1179
1180
0
    if (setStr == NULL) {
1181
0
        return CKR_HOST_MEMORY;
1182
0
    }
1183
0
    newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr);
1184
0
    sqlite3_free(setStr);
1185
0
    if (newStr == NULL) {
1186
0
        UNLOCK_SQLITE()
1187
0
        return CKR_HOST_MEMORY;
1188
0
    }
1189
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1190
0
    if (error != CKR_OK) {
1191
0
        goto loser;
1192
0
    }
1193
0
    sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
1194
0
    if (sqlerr != SQLITE_OK)
1195
0
        goto loser;
1196
0
    for (i = 0; i < count; i++) {
1197
0
        if (template[i].ulValueLen != 0) {
1198
0
            sqlerr = sqlite3_bind_blob(stmt, i + 1, template[i].pValue,
1199
0
                                       template[i].ulValueLen, SQLITE_STATIC);
1200
0
        } else {
1201
0
            sqlerr = sqlite3_bind_blob(stmt, i + 1, SQLITE_EXPLICIT_NULL,
1202
0
                                       SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC);
1203
0
        }
1204
0
        if (sqlerr != SQLITE_OK)
1205
0
            goto loser;
1206
0
    }
1207
0
    sqlerr = sqlite3_bind_int(stmt, i + 1, object_id);
1208
0
    if (sqlerr != SQLITE_OK)
1209
0
        goto loser;
1210
1211
0
    do {
1212
0
        sqlerr = sqlite3_step(stmt);
1213
0
        if (sqlerr == SQLITE_BUSY) {
1214
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1215
0
        }
1216
0
    } while (!sdb_done(sqlerr, &retry));
1217
1218
0
loser:
1219
0
    if (newStr) {
1220
0
        sqlite3_free(newStr);
1221
0
    }
1222
0
    if (error == CKR_OK) {
1223
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1224
0
    }
1225
1226
0
    if (stmt) {
1227
0
        sqlite3_reset(stmt);
1228
0
        sqlite3_finalize(stmt);
1229
0
    }
1230
1231
0
    if (sqlDB) {
1232
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1233
0
    }
1234
1235
0
    UNLOCK_SQLITE()
1236
0
    return error;
1237
0
}
1238
1239
/*
1240
 * check to see if a candidate object handle already exists.
1241
 */
1242
static PRBool
1243
sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
1244
0
{
1245
0
    CK_RV crv;
1246
0
    CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 };
1247
1248
0
    crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1);
1249
0
    if (crv == CKR_OBJECT_HANDLE_INVALID) {
1250
0
        return PR_FALSE;
1251
0
    }
1252
0
    return PR_TRUE;
1253
0
}
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
 */
1259
static CK_OBJECT_HANDLE
1260
sdb_getObjectId(SDB *sdb)
1261
0
{
1262
0
    CK_OBJECT_HANDLE candidate;
1263
0
    static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE;
1264
0
    int count;
1265
    /*
1266
     * get an initial object handle to use
1267
     */
1268
0
    if (next_obj == CK_INVALID_HANDLE) {
1269
0
        PRTime time;
1270
0
        time = PR_Now();
1271
1272
0
        next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL);
1273
0
    }
1274
0
    candidate = next_obj++;
1275
    /* detect that we've looped through all the handles... */
1276
0
    for (count = 0; count < 0x40000000; count++, candidate = next_obj++) {
1277
        /* mask off excess bits */
1278
0
        candidate &= 0x3fffffff;
1279
        /* if we hit zero, go to the next entry */
1280
0
        if (candidate == CK_INVALID_HANDLE) {
1281
0
            continue;
1282
0
        }
1283
        /* make sure we aren't already using */
1284
0
        if (!sdb_objectExists(sdb, candidate)) {
1285
            /* this one is free */
1286
0
            return candidate;
1287
0
        }
1288
0
    }
1289
1290
    /* no handle is free, fail */
1291
0
    return CK_INVALID_HANDLE;
1292
0
}
1293
1294
CK_RV
1295
sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object)
1296
0
{
1297
0
    CK_OBJECT_HANDLE id;
1298
1299
0
    id = sdb_getObjectId(sdb);
1300
0
    if (id == CK_INVALID_HANDLE) {
1301
0
        return CKR_DEVICE_MEMORY; /* basically we ran out of resources */
1302
0
    }
1303
0
    *object = id;
1304
0
    return CKR_OK;
1305
0
}
1306
1307
static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);";
1308
CK_RV
1309
sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
1310
                 const CK_ATTRIBUTE *template, CK_ULONG count)
1311
0
{
1312
0
    SDBPrivate *sdb_p = sdb->private;
1313
0
    sqlite3 *sqlDB = NULL;
1314
0
    sqlite3_stmt *stmt = NULL;
1315
0
    char *columnStr = NULL;
1316
0
    char *valueStr = NULL;
1317
0
    char *newStr = NULL;
1318
0
    int sqlerr = SQLITE_OK;
1319
0
    CK_RV error = CKR_OK;
1320
0
    CK_OBJECT_HANDLE this_object = CK_INVALID_HANDLE;
1321
0
    int retry = 0;
1322
0
    unsigned int i;
1323
1324
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1325
0
        return CKR_TOKEN_WRITE_PROTECTED;
1326
0
    }
1327
1328
0
    LOCK_SQLITE()
1329
0
    if ((*object_id != CK_INVALID_HANDLE) &&
1330
0
        !sdb_objectExists(sdb, *object_id)) {
1331
0
        this_object = *object_id;
1332
0
    } else {
1333
0
        this_object = sdb_getObjectId(sdb);
1334
0
    }
1335
0
    if (this_object == CK_INVALID_HANDLE) {
1336
0
        UNLOCK_SQLITE();
1337
0
        return CKR_HOST_MEMORY;
1338
0
    }
1339
0
    columnStr = sqlite3_mprintf("");
1340
0
    valueStr = sqlite3_mprintf("");
1341
0
    *object_id = this_object;
1342
0
    for (i = 0; columnStr && valueStr && i < count; i++) {
1343
0
        newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type);
1344
0
        sqlite3_free(columnStr);
1345
0
        columnStr = newStr;
1346
0
        newStr = sqlite3_mprintf("%s,$VALUE%d", valueStr, i);
1347
0
        sqlite3_free(valueStr);
1348
0
        valueStr = newStr;
1349
0
    }
1350
0
    newStr = NULL;
1351
0
    if ((columnStr == NULL) || (valueStr == NULL)) {
1352
0
        if (columnStr) {
1353
0
            sqlite3_free(columnStr);
1354
0
        }
1355
0
        if (valueStr) {
1356
0
            sqlite3_free(valueStr);
1357
0
        }
1358
0
        UNLOCK_SQLITE()
1359
0
        return CKR_HOST_MEMORY;
1360
0
    }
1361
0
    newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr);
1362
0
    sqlite3_free(columnStr);
1363
0
    sqlite3_free(valueStr);
1364
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1365
0
    if (error != CKR_OK) {
1366
0
        goto loser;
1367
0
    }
1368
0
    sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
1369
0
    if (sqlerr != SQLITE_OK)
1370
0
        goto loser;
1371
0
    sqlerr = sqlite3_bind_int(stmt, 1, *object_id);
1372
0
    if (sqlerr != SQLITE_OK)
1373
0
        goto loser;
1374
0
    for (i = 0; i < count; i++) {
1375
0
        if (template[i].ulValueLen) {
1376
0
            sqlerr = sqlite3_bind_blob(stmt, i + 2, template[i].pValue,
1377
0
                                       template[i].ulValueLen, SQLITE_STATIC);
1378
0
        } else {
1379
0
            sqlerr = sqlite3_bind_blob(stmt, i + 2, SQLITE_EXPLICIT_NULL,
1380
0
                                       SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC);
1381
0
        }
1382
0
        if (sqlerr != SQLITE_OK)
1383
0
            goto loser;
1384
0
    }
1385
1386
0
    do {
1387
0
        sqlerr = sqlite3_step(stmt);
1388
0
        if (sqlerr == SQLITE_BUSY) {
1389
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1390
0
        }
1391
0
    } while (!sdb_done(sqlerr, &retry));
1392
1393
0
loser:
1394
0
    if (newStr) {
1395
0
        sqlite3_free(newStr);
1396
0
    }
1397
0
    if (error == CKR_OK) {
1398
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1399
0
    }
1400
1401
0
    if (stmt) {
1402
0
        sqlite3_reset(stmt);
1403
0
        sqlite3_finalize(stmt);
1404
0
    }
1405
1406
0
    if (sqlDB) {
1407
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1408
0
    }
1409
0
    UNLOCK_SQLITE()
1410
1411
0
    return error;
1412
0
}
1413
1414
/*
1415
 *  Generic destroy that can destroy metadata or objects
1416
 */
1417
static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);";
1418
CK_RV
1419
sdb_destroyAnyObject(SDB *sdb, const char *table,
1420
                     CK_OBJECT_HANDLE object_id, const char *string_id)
1421
0
{
1422
0
    SDBPrivate *sdb_p = sdb->private;
1423
0
    sqlite3 *sqlDB = NULL;
1424
0
    sqlite3_stmt *stmt = NULL;
1425
0
    char *newStr = NULL;
1426
0
    int sqlerr = SQLITE_OK;
1427
0
    CK_RV error = CKR_OK;
1428
0
    int retry = 0;
1429
1430
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1431
0
        return CKR_TOKEN_WRITE_PROTECTED;
1432
0
    }
1433
1434
0
    LOCK_SQLITE()
1435
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1436
0
    if (error != CKR_OK) {
1437
0
        goto loser;
1438
0
    }
1439
0
    newStr = sqlite3_mprintf(DESTROY_CMD, table);
1440
0
    if (newStr == NULL) {
1441
0
        error = CKR_HOST_MEMORY;
1442
0
        goto loser;
1443
0
    }
1444
0
    sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
1445
0
    sqlite3_free(newStr);
1446
0
    if (sqlerr != SQLITE_OK)
1447
0
        goto loser;
1448
0
    if (string_id == NULL) {
1449
0
        sqlerr = sqlite3_bind_int(stmt, 1, object_id);
1450
0
    } else {
1451
0
        sqlerr = sqlite3_bind_text(stmt, 1, string_id,
1452
0
                                   PORT_Strlen(string_id), SQLITE_STATIC);
1453
0
    }
1454
0
    if (sqlerr != SQLITE_OK)
1455
0
        goto loser;
1456
1457
0
    do {
1458
0
        sqlerr = sqlite3_step(stmt);
1459
0
        if (sqlerr == SQLITE_BUSY) {
1460
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1461
0
        }
1462
0
    } while (!sdb_done(sqlerr, &retry));
1463
1464
0
loser:
1465
0
    if (error == CKR_OK) {
1466
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1467
0
    }
1468
1469
0
    if (stmt) {
1470
0
        sqlite3_reset(stmt);
1471
0
        sqlite3_finalize(stmt);
1472
0
    }
1473
1474
0
    if (sqlDB) {
1475
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1476
0
    }
1477
1478
0
    UNLOCK_SQLITE()
1479
0
    return error;
1480
0
}
1481
1482
CK_RV
1483
sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
1484
0
{
1485
0
    SDBPrivate *sdb_p = sdb->private;
1486
0
    return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL);
1487
0
}
1488
1489
CK_RV
1490
sdb_DestroyMetaData(SDB *sdb, const char *id)
1491
0
{
1492
0
    return sdb_destroyAnyObject(sdb, "metaData", 0, id);
1493
0
}
1494
1495
static 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
 */
1504
CK_RV
1505
sdb_Begin(SDB *sdb)
1506
0
{
1507
0
    SDBPrivate *sdb_p = sdb->private;
1508
0
    sqlite3 *sqlDB = NULL;
1509
0
    sqlite3_stmt *stmt = NULL;
1510
0
    int sqlerr = SQLITE_OK;
1511
0
    CK_RV error = CKR_OK;
1512
0
    int retry = 0;
1513
1514
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1515
0
        return CKR_TOKEN_WRITE_PROTECTED;
1516
0
    }
1517
1518
0
    LOCK_SQLITE()
1519
1520
    /* get a new version that we will use for the entire transaction */
1521
0
    sqlerr = sdb_openDB(sdb_p->sqlDBName, &sqlDB, SDB_RDWR);
1522
0
    if (sqlerr != SQLITE_OK) {
1523
0
        goto loser;
1524
0
    }
1525
1526
0
    sqlerr = sqlite3_prepare_v2(sqlDB, BEGIN_CMD, -1, &stmt, NULL);
1527
1528
0
    do {
1529
0
        sqlerr = sqlite3_step(stmt);
1530
0
        if (sqlerr == SQLITE_BUSY) {
1531
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1532
0
        }
1533
        /* don't retry BEGIN transaction*/
1534
0
        retry = 0;
1535
0
    } while (!sdb_done(sqlerr, &retry));
1536
1537
0
    if (stmt) {
1538
0
        sqlite3_reset(stmt);
1539
0
        sqlite3_finalize(stmt);
1540
0
    }
1541
1542
0
loser:
1543
0
    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
0
    if (error == CKR_OK) {
1549
        /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point
1550
         * sdb_p->sqlXactDB MUST be null */
1551
0
        PR_EnterMonitor(sdb_p->dbMon);
1552
0
        PORT_Assert(sdb_p->sqlXactDB == NULL);
1553
0
        sdb_p->sqlXactDB = sqlDB;
1554
0
        sdb_p->sqlXactThread = PR_GetCurrentThread();
1555
0
        PR_ExitMonitor(sdb_p->dbMon);
1556
0
    } else {
1557
        /* we failed to start our transaction,
1558
         * free any databases we opened. */
1559
0
        if (sqlDB) {
1560
0
            sqlite3_close(sqlDB);
1561
0
        }
1562
0
    }
1563
1564
0
    UNLOCK_SQLITE()
1565
0
    return error;
1566
0
}
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
 */
1574
static CK_RV
1575
sdb_complete(SDB *sdb, const char *cmd)
1576
0
{
1577
0
    SDBPrivate *sdb_p = sdb->private;
1578
0
    sqlite3 *sqlDB = NULL;
1579
0
    sqlite3_stmt *stmt = NULL;
1580
0
    int sqlerr = SQLITE_OK;
1581
0
    CK_RV error = CKR_OK;
1582
0
    int retry = 0;
1583
1584
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1585
0
        return CKR_TOKEN_WRITE_PROTECTED;
1586
0
    }
1587
1588
    /* We must have a transation database, or we shouldn't have arrived here */
1589
0
    PR_EnterMonitor(sdb_p->dbMon);
1590
0
    PORT_Assert(sdb_p->sqlXactDB);
1591
0
    if (sdb_p->sqlXactDB == NULL) {
1592
0
        PR_ExitMonitor(sdb_p->dbMon);
1593
0
        return CKR_GENERAL_ERROR; /* shouldn't happen */
1594
0
    }
1595
0
    PORT_Assert(sdb_p->sqlXactThread == PR_GetCurrentThread());
1596
0
    if (sdb_p->sqlXactThread != PR_GetCurrentThread()) {
1597
0
        PR_ExitMonitor(sdb_p->dbMon);
1598
0
        return CKR_GENERAL_ERROR; /* shouldn't happen */
1599
0
    }
1600
0
    sqlDB = sdb_p->sqlXactDB;
1601
0
    sdb_p->sqlXactDB = NULL; /* no one else can get to this DB,
1602
                              * safe to unlock */
1603
0
    sdb_p->sqlXactThread = NULL;
1604
0
    PR_ExitMonitor(sdb_p->dbMon);
1605
1606
0
    sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL);
1607
1608
0
    do {
1609
0
        sqlerr = sqlite3_step(stmt);
1610
0
        if (sqlerr == SQLITE_BUSY) {
1611
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1612
0
        }
1613
0
    } while (!sdb_done(sqlerr, &retry));
1614
1615
    /* Pending BEGIN TRANSACTIONS Can move forward at this point. */
1616
1617
0
    if (stmt) {
1618
0
        sqlite3_reset(stmt);
1619
0
        sqlite3_finalize(stmt);
1620
0
    }
1621
1622
    /* we we have a cached DB image, update it as well */
1623
0
    if (sdb_p->cacheTable) {
1624
0
        PR_EnterMonitor(sdb_p->dbMon);
1625
0
        sdb_updateCache(sdb_p);
1626
0
        PR_ExitMonitor(sdb_p->dbMon);
1627
0
    }
1628
1629
0
    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
0
    sqlite3_close(sqlDB);
1634
1635
0
    return error;
1636
0
}
1637
1638
static const char COMMIT_CMD[] = "COMMIT TRANSACTION;";
1639
CK_RV
1640
sdb_Commit(SDB *sdb)
1641
0
{
1642
0
    CK_RV crv;
1643
0
    LOCK_SQLITE()
1644
0
    crv = sdb_complete(sdb, COMMIT_CMD);
1645
0
    UNLOCK_SQLITE()
1646
0
    return crv;
1647
0
}
1648
1649
static const char ROLLBACK_CMD[] = "ROLLBACK TRANSACTION;";
1650
CK_RV
1651
sdb_Abort(SDB *sdb)
1652
0
{
1653
0
    CK_RV crv;
1654
0
    LOCK_SQLITE()
1655
0
    crv = sdb_complete(sdb, ROLLBACK_CMD);
1656
0
    UNLOCK_SQLITE()
1657
0
    return crv;
1658
0
}
1659
1660
static int tableExists(sqlite3 *sqlDB, const char *tableName);
1661
1662
static const char GET_PW_CMD[] = "SELECT ALL * FROM metaData WHERE id=$ID;";
1663
CK_RV
1664
sdb_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2)
1665
0
{
1666
0
    SDBPrivate *sdb_p = sdb->private;
1667
0
    sqlite3 *sqlDB = NULL;
1668
0
    sqlite3_stmt *stmt = NULL;
1669
0
    int sqlerr = SQLITE_OK;
1670
0
    CK_RV error = CKR_OK;
1671
0
    int found = 0;
1672
0
    int retry = 0;
1673
1674
0
    LOCK_SQLITE()
1675
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1676
0
    if (error != CKR_OK) {
1677
0
        goto loser;
1678
0
    }
1679
1680
    /* handle 'test' versions of the sqlite db */
1681
0
    sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL);
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
0
    if (sqlerr == SQLITE_SCHEMA) {
1687
0
        sqlerr = sdb_reopenDBLocal(sdb_p, &sqlDB);
1688
0
        if (sqlerr != SQLITE_OK) {
1689
0
            goto loser;
1690
0
        }
1691
0
        sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL);
1692
0
    }
1693
0
    if (sqlerr != SQLITE_OK)
1694
0
        goto loser;
1695
0
    sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id), SQLITE_STATIC);
1696
0
    do {
1697
0
        sqlerr = sqlite3_step(stmt);
1698
0
        if (sqlerr == SQLITE_BUSY) {
1699
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1700
0
        }
1701
0
        if (sqlerr == SQLITE_ROW) {
1702
0
            const char *blobData;
1703
0
            unsigned int len = item1->len;
1704
0
            item1->len = sqlite3_column_bytes(stmt, 1);
1705
0
            if (item1->len > len) {
1706
0
                error = CKR_BUFFER_TOO_SMALL;
1707
0
                continue;
1708
0
            }
1709
0
            blobData = sqlite3_column_blob(stmt, 1);
1710
0
            PORT_Memcpy(item1->data, blobData, item1->len);
1711
0
            if (item2) {
1712
0
                len = item2->len;
1713
0
                item2->len = sqlite3_column_bytes(stmt, 2);
1714
0
                if (item2->len > len) {
1715
0
                    error = CKR_BUFFER_TOO_SMALL;
1716
0
                    continue;
1717
0
                }
1718
0
                blobData = sqlite3_column_blob(stmt, 2);
1719
0
                PORT_Memcpy(item2->data, blobData, item2->len);
1720
0
            }
1721
0
            found = 1;
1722
0
        }
1723
0
    } while (!sdb_done(sqlerr, &retry));
1724
1725
0
loser:
1726
    /* fix up the error if necessary */
1727
0
    if (error == CKR_OK) {
1728
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1729
0
        if (!found && error == CKR_OK) {
1730
0
            error = CKR_OBJECT_HANDLE_INVALID;
1731
0
        }
1732
0
    }
1733
1734
0
    if (stmt) {
1735
0
        sqlite3_reset(stmt);
1736
0
        sqlite3_finalize(stmt);
1737
0
    }
1738
1739
0
    if (sqlDB) {
1740
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1741
0
    }
1742
0
    UNLOCK_SQLITE()
1743
1744
0
    return error;
1745
0
}
1746
1747
static const char PW_CREATE_TABLE_CMD[] =
1748
    "CREATE TABLE metaData (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, item1, item2);";
1749
static const char PW_CREATE_CMD[] =
1750
    "INSERT INTO metaData (id,item1,item2) VALUES($ID,$ITEM1,$ITEM2);";
1751
static const char MD_CREATE_CMD[] =
1752
    "INSERT INTO metaData (id,item1) VALUES($ID,$ITEM1);";
1753
1754
CK_RV
1755
sdb_PutMetaData(SDB *sdb, const char *id, const SECItem *item1,
1756
                const SECItem *item2)
1757
0
{
1758
0
    SDBPrivate *sdb_p = sdb->private;
1759
0
    sqlite3 *sqlDB = sdb_p->sqlXactDB;
1760
0
    sqlite3_stmt *stmt = NULL;
1761
0
    int sqlerr = SQLITE_OK;
1762
0
    CK_RV error = CKR_OK;
1763
0
    int retry = 0;
1764
0
    const char *cmd = PW_CREATE_CMD;
1765
1766
0
    if ((sdb->sdb_flags & SDB_RDONLY) != 0) {
1767
0
        return CKR_TOKEN_WRITE_PROTECTED;
1768
0
    }
1769
1770
0
    LOCK_SQLITE()
1771
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1772
0
    if (error != CKR_OK) {
1773
0
        goto loser;
1774
0
    }
1775
1776
0
    if (!tableExists(sqlDB, "metaData")) {
1777
0
        sqlerr = sqlite3_exec(sqlDB, PW_CREATE_TABLE_CMD, NULL, 0, NULL);
1778
0
        if (sqlerr != SQLITE_OK)
1779
0
            goto loser;
1780
0
    }
1781
0
    if (item2 == NULL) {
1782
0
        cmd = MD_CREATE_CMD;
1783
0
    }
1784
0
    sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL);
1785
0
    if (sqlerr != SQLITE_OK)
1786
0
        goto loser;
1787
0
    sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id), SQLITE_STATIC);
1788
0
    if (sqlerr != SQLITE_OK)
1789
0
        goto loser;
1790
0
    sqlerr = sqlite3_bind_blob(stmt, 2, item1->data, item1->len, SQLITE_STATIC);
1791
0
    if (sqlerr != SQLITE_OK)
1792
0
        goto loser;
1793
0
    if (item2) {
1794
0
        sqlerr = sqlite3_bind_blob(stmt, 3, item2->data,
1795
0
                                   item2->len, SQLITE_STATIC);
1796
0
        if (sqlerr != SQLITE_OK)
1797
0
            goto loser;
1798
0
    }
1799
1800
0
    do {
1801
0
        sqlerr = sqlite3_step(stmt);
1802
0
        if (sqlerr == SQLITE_BUSY) {
1803
0
            PR_Sleep(SDB_BUSY_RETRY_TIME);
1804
0
        }
1805
0
    } while (!sdb_done(sqlerr, &retry));
1806
1807
0
loser:
1808
    /* fix up the error if necessary */
1809
0
    if (error == CKR_OK) {
1810
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1811
0
    }
1812
1813
0
    if (stmt) {
1814
0
        sqlite3_reset(stmt);
1815
0
        sqlite3_finalize(stmt);
1816
0
    }
1817
1818
0
    if (sqlDB) {
1819
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1820
0
    }
1821
0
    UNLOCK_SQLITE()
1822
1823
0
    return error;
1824
0
}
1825
1826
static const char RESET_CMD[] = "DELETE FROM %s;";
1827
CK_RV
1828
sdb_Reset(SDB *sdb)
1829
0
{
1830
0
    SDBPrivate *sdb_p = sdb->private;
1831
0
    sqlite3 *sqlDB = NULL;
1832
0
    char *newStr;
1833
0
    int sqlerr = SQLITE_OK;
1834
0
    CK_RV error = CKR_OK;
1835
1836
    /* only Key databases can be reset */
1837
0
    if (sdb_p->type != SDB_KEY) {
1838
0
        return CKR_OBJECT_HANDLE_INVALID;
1839
0
    }
1840
1841
0
    LOCK_SQLITE()
1842
0
    error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
1843
0
    if (error != CKR_OK) {
1844
0
        goto loser;
1845
0
    }
1846
1847
0
    if (tableExists(sqlDB, sdb_p->table)) {
1848
        /* delete the contents of the key table */
1849
0
        newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
1850
0
        if (newStr == NULL) {
1851
0
            error = CKR_HOST_MEMORY;
1852
0
            goto loser;
1853
0
        }
1854
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
1855
0
        sqlite3_free(newStr);
1856
1857
0
        if (sqlerr != SQLITE_OK)
1858
0
            goto loser;
1859
0
    }
1860
1861
    /* delete the password entry table */
1862
0
    sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;",
1863
0
                          NULL, 0, NULL);
1864
1865
0
loser:
1866
    /* fix up the error if necessary */
1867
0
    if (error == CKR_OK) {
1868
0
        error = sdb_mapSQLError(sdb_p->type, sqlerr);
1869
0
    }
1870
1871
0
    if (sqlDB) {
1872
0
        sdb_closeDBLocal(sdb_p, sqlDB);
1873
0
    }
1874
1875
0
    UNLOCK_SQLITE()
1876
0
    return error;
1877
0
}
1878
1879
CK_RV
1880
sdb_Close(SDB *sdb)
1881
0
{
1882
0
    SDBPrivate *sdb_p = sdb->private;
1883
0
    int sqlerr = SQLITE_OK;
1884
0
    sdbDataType type = sdb_p->type;
1885
1886
0
    sqlerr = sqlite3_close(sdb_p->sqlReadDB);
1887
0
    PORT_Free(sdb_p->sqlDBName);
1888
0
    if (sdb_p->cacheTable) {
1889
0
        sqlite3_free(sdb_p->cacheTable);
1890
0
    }
1891
0
    if (sdb_p->dbMon) {
1892
0
        PR_DestroyMonitor(sdb_p->dbMon);
1893
0
    }
1894
0
    free(sdb_p->schemaAttrs);
1895
0
    free(sdb_p);
1896
0
    free(sdb);
1897
0
    return sdb_mapSQLError(type, sqlerr);
1898
0
}
1899
1900
/*
1901
 * functions to support open
1902
 */
1903
1904
static const char CHECK_TABLE_CMD[] = "SELECT ALL * FROM %s LIMIT 0;";
1905
1906
/* return 1 if sqlDB contains table 'tableName */
1907
static int
1908
tableExists(sqlite3 *sqlDB, const char *tableName)
1909
0
{
1910
0
    char *cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
1911
0
    int sqlerr = SQLITE_OK;
1912
1913
0
    if (cmd == NULL) {
1914
0
        return 0;
1915
0
    }
1916
1917
0
    sqlerr = sqlite3_exec(sqlDB, cmd, NULL, 0, 0);
1918
0
    sqlite3_free(cmd);
1919
1920
0
    return (sqlerr == SQLITE_OK) ? 1 : 0;
1921
0
}
1922
1923
void
1924
sdb_SetForkState(PRBool forked)
1925
0
{
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
0
}
1931
1932
static int
1933
sdb_attributeComparator(const void *a, const void *b)
1934
0
{
1935
0
    if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) {
1936
0
        return -1;
1937
0
    }
1938
0
    if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) {
1939
0
        return 1;
1940
0
    }
1941
0
    return 0;
1942
0
}
1943
1944
/*
1945
 * initialize a single database
1946
 */
1947
static const char INIT_CMD[] =
1948
    "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)";
1949
1950
CK_RV
1951
sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
1952
         int *newInit, int inFlags, PRUint32 accessOps, SDB **pSdb)
1953
0
{
1954
0
    int i;
1955
0
    char *initStr = NULL;
1956
0
    char *newStr;
1957
0
    char *queryStr = NULL;
1958
0
    int inTransaction = 0;
1959
0
    SDB *sdb = NULL;
1960
0
    SDBPrivate *sdb_p = NULL;
1961
0
    sqlite3 *sqlDB = NULL;
1962
0
    int sqlerr = SQLITE_OK;
1963
0
    CK_RV error = CKR_OK;
1964
0
    char *cacheTable = NULL;
1965
0
    PRIntervalTime now = 0;
1966
0
    char *env;
1967
0
    PRBool enableCache = PR_FALSE;
1968
0
    PRBool checkFSType = PR_FALSE;
1969
0
    PRBool measureSpeed = PR_FALSE;
1970
0
    PRBool create;
1971
0
    int flags = inFlags & 0x7;
1972
1973
0
    *pSdb = NULL;
1974
0
    *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
0
    LOCK_SQLITE();
1981
0
    create = (_NSSUTIL_Access(dbname, PR_ACCESS_EXISTS) != PR_SUCCESS);
1982
0
    if ((flags == SDB_RDONLY) && create) {
1983
0
        error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
1984
0
        goto loser;
1985
0
    }
1986
0
    sqlerr = sdb_openDB(dbname, &sqlDB, flags);
1987
0
    if (sqlerr != SQLITE_OK) {
1988
0
        error = sdb_mapSQLError(type, sqlerr);
1989
0
        goto loser;
1990
0
    }
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
0
    if (create && sdb_chmod(dbname, 0600) != 0) {
1999
0
        error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
2000
0
        goto loser;
2001
0
    }
2002
2003
0
    if (flags != SDB_RDONLY) {
2004
0
        sqlerr = sqlite3_exec(sqlDB, BEGIN_CMD, NULL, 0, NULL);
2005
0
        if (sqlerr != SQLITE_OK) {
2006
0
            error = sdb_mapSQLError(type, sqlerr);
2007
0
            goto loser;
2008
0
        }
2009
0
        inTransaction = 1;
2010
0
    }
2011
0
    if (!tableExists(sqlDB, table)) {
2012
0
        *newInit = 1;
2013
0
        if (flags != SDB_CREATE) {
2014
0
            error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
2015
0
            goto loser;
2016
0
        }
2017
0
        initStr = sqlite3_mprintf("");
2018
0
        for (i = 0; initStr && i < known_attributes_size; i++) {
2019
0
            newStr = sqlite3_mprintf("%s, a%x", initStr, known_attributes[i]);
2020
0
            sqlite3_free(initStr);
2021
0
            initStr = newStr;
2022
0
        }
2023
0
        if (initStr == NULL) {
2024
0
            error = CKR_HOST_MEMORY;
2025
0
            goto loser;
2026
0
        }
2027
2028
0
        newStr = sqlite3_mprintf(INIT_CMD, table, initStr);
2029
0
        sqlite3_free(initStr);
2030
0
        if (newStr == NULL) {
2031
0
            error = CKR_HOST_MEMORY;
2032
0
            goto loser;
2033
0
        }
2034
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
2035
0
        sqlite3_free(newStr);
2036
0
        if (sqlerr != SQLITE_OK) {
2037
0
            error = sdb_mapSQLError(type, sqlerr);
2038
0
            goto loser;
2039
0
        }
2040
2041
0
        newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, table);
2042
0
        if (newStr == NULL) {
2043
0
            error = CKR_HOST_MEMORY;
2044
0
            goto loser;
2045
0
        }
2046
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
2047
0
        sqlite3_free(newStr);
2048
0
        if (sqlerr != SQLITE_OK) {
2049
0
            error = sdb_mapSQLError(type, sqlerr);
2050
0
            goto loser;
2051
0
        }
2052
2053
0
        newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, table);
2054
0
        if (newStr == NULL) {
2055
0
            error = CKR_HOST_MEMORY;
2056
0
            goto loser;
2057
0
        }
2058
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
2059
0
        sqlite3_free(newStr);
2060
0
        if (sqlerr != SQLITE_OK) {
2061
0
            error = sdb_mapSQLError(type, sqlerr);
2062
0
            goto loser;
2063
0
        }
2064
2065
0
        newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, table);
2066
0
        if (newStr == NULL) {
2067
0
            error = CKR_HOST_MEMORY;
2068
0
            goto loser;
2069
0
        }
2070
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
2071
0
        sqlite3_free(newStr);
2072
0
        if (sqlerr != SQLITE_OK) {
2073
0
            error = sdb_mapSQLError(type, sqlerr);
2074
0
            goto loser;
2075
0
        }
2076
2077
0
        newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, table);
2078
0
        if (newStr == NULL) {
2079
0
            error = CKR_HOST_MEMORY;
2080
0
            goto loser;
2081
0
        }
2082
0
        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
2083
0
        sqlite3_free(newStr);
2084
0
        if (sqlerr != SQLITE_OK) {
2085
0
            error = sdb_mapSQLError(type, sqlerr);
2086
0
            goto loser;
2087
0
        }
2088
0
    }
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
0
    if (type == SDB_KEY && !tableExists(sqlDB, "metaData")) {
2100
0
        *newInit = 1;
2101
0
    }
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
0
    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
0
    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
0
        checkFSType = PR_TRUE;
2138
0
    } else if (PORT_Strcasecmp(env, "yes") == 0) {
2139
0
        enableCache = PR_TRUE;
2140
0
    } else if (PORT_Strcasecmp(env, "no") != 0) { /* not "no" => "auto" */
2141
0
        measureSpeed = PR_TRUE;
2142
0
    }
2143
2144
0
    if (checkFSType) {
2145
0
#if defined(LINUX) && !defined(ANDROID)
2146
0
        struct statfs statfs_s;
2147
0
        if (statfs(dbname, &statfs_s) == 0) {
2148
0
            switch (statfs_s.f_type) {
2149
0
                case SMB_SUPER_MAGIC:
2150
0
                case 0xff534d42: /* CIFS_MAGIC_NUMBER */
2151
0
                case NFS_SUPER_MAGIC:
2152
                    /* We assume these are slow. */
2153
0
                    enableCache = PR_TRUE;
2154
0
                    break;
2155
0
                case CODA_SUPER_MAGIC:
2156
0
                case 0x65735546: /* FUSE_SUPER_MAGIC */
2157
0
                case NCP_SUPER_MAGIC:
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
0
                    measureSpeed = PR_TRUE;
2162
0
                    break;
2163
0
                case AFS_SUPER_MAGIC: /* Already implements caching. */
2164
0
                default:
2165
0
                    break;
2166
0
            }
2167
0
        }
2168
0
#endif
2169
0
    }
2170
2171
0
    if (measureSpeed) {
2172
0
        char *tempDir = NULL;
2173
0
        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
0
        tempDir = sdb_getTempDir(sqlDB);
2180
0
        if (tempDir) {
2181
0
            tempOps = sdb_measureAccess(tempDir);
2182
0
            PORT_Free(tempDir);
2183
2184
            /* There is a cost to continually copying the database.
2185
             * Account for that cost  with the arbitrary factor of 10 */
2186
0
            enableCache = (PRBool)(tempOps > accessOps * 10);
2187
0
        }
2188
0
    }
2189
2190
0
    if (enableCache) {
2191
        /* try to set the temp store to memory.*/
2192
0
        sqlite3_exec(sqlDB, "PRAGMA temp_store=MEMORY", NULL, 0, NULL);
2193
        /* Failure to set the temp store to memory is not fatal,
2194
         * ignore the error */
2195
2196
0
        cacheTable = sqlite3_mprintf("%sCache", table);
2197
0
        if (cacheTable == NULL) {
2198
0
            error = CKR_HOST_MEMORY;
2199
0
            goto loser;
2200
0
        }
2201
        /* build the cache table */
2202
0
        error = sdb_buildCache(sqlDB, type, cacheTable, table);
2203
0
        if (error != CKR_OK) {
2204
0
            goto loser;
2205
0
        }
2206
        /* initialize the last cache build time */
2207
0
        now = PR_IntervalNow();
2208
0
    }
2209
2210
0
    sdb = (SDB *)malloc(sizeof(SDB));
2211
0
    if (!sdb) {
2212
0
        error = CKR_HOST_MEMORY;
2213
0
        goto loser;
2214
0
    }
2215
0
    sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate));
2216
0
    if (!sdb_p) {
2217
0
        error = CKR_HOST_MEMORY;
2218
0
        goto loser;
2219
0
    }
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
0
    sdb_p->schemaAttrs = NULL;
2225
0
    if (!PORT_Strcmp("nssPublic", table) ||
2226
0
        !PORT_Strcmp("nssPrivate", table)) {
2227
0
        sqlite3_stmt *stmt = NULL;
2228
0
        int retry = 0;
2229
0
        unsigned int backedAttrs = 0;
2230
2231
        /* Can't bind parameters to a PRAGMA. */
2232
0
        queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table);
2233
0
        if (queryStr == NULL) {
2234
0
            error = CKR_HOST_MEMORY;
2235
0
            goto loser;
2236
0
        }
2237
0
        sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL);
2238
0
        sqlite3_free(queryStr);
2239
0
        queryStr = NULL;
2240
0
        if (sqlerr != SQLITE_OK) {
2241
0
            goto loser;
2242
0
        }
2243
0
        unsigned int schemaAttrsCapacity = known_attributes_size;
2244
0
        sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2245
0
        if (!sdb_p->schemaAttrs) {
2246
0
            error = CKR_HOST_MEMORY;
2247
0
            goto loser;
2248
0
        }
2249
0
        do {
2250
0
            sqlerr = sqlite3_step(stmt);
2251
0
            if (sqlerr == SQLITE_BUSY) {
2252
0
                PR_Sleep(SDB_BUSY_RETRY_TIME);
2253
0
            }
2254
0
            if (sqlerr == SQLITE_ROW) {
2255
0
                if (backedAttrs == schemaAttrsCapacity) {
2256
0
                    schemaAttrsCapacity += known_attributes_size;
2257
0
                    sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs,
2258
0
                                                 schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2259
0
                    if (!sdb_p->schemaAttrs) {
2260
0
                        error = CKR_HOST_MEMORY;
2261
0
                        goto loser;
2262
0
                    }
2263
0
                }
2264
                /* Record the ULONG attribute value. */
2265
0
                char *val = (char *)sqlite3_column_text(stmt, 1);
2266
0
                if (val && val[0] == 'a') {
2267
0
                    CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL, 16);
2268
0
                    sdb_p->schemaAttrs[backedAttrs++] = attr;
2269
0
                }
2270
0
            }
2271
0
        } while (!sdb_done(sqlerr, &retry));
2272
2273
0
        if (sqlerr != SQLITE_DONE) {
2274
0
            goto loser;
2275
0
        }
2276
0
        sqlerr = sqlite3_reset(stmt);
2277
0
        if (sqlerr != SQLITE_OK) {
2278
0
            goto loser;
2279
0
        }
2280
0
        sqlerr = sqlite3_finalize(stmt);
2281
0
        if (sqlerr != SQLITE_OK) {
2282
0
            goto loser;
2283
0
        }
2284
2285
0
        sdb_p->numSchemaAttrs = backedAttrs;
2286
2287
        /* Sort these once so we can shortcut invalid attribute searches. */
2288
0
        qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs,
2289
0
              sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator);
2290
0
    }
2291
2292
    /* invariant fields */
2293
0
    sdb_p->sqlDBName = PORT_Strdup(dbname);
2294
0
    sdb_p->type = type;
2295
0
    sdb_p->table = table;
2296
0
    sdb_p->cacheTable = cacheTable;
2297
0
    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
0
    sdb_p->updateInterval = PR_SecondsToInterval(10);
2301
0
    sdb_p->dbMon = PR_NewMonitor();
2302
    /* these fields are protected by the lock */
2303
0
    sdb_p->sqlXactDB = NULL;
2304
0
    sdb_p->sqlXactThread = NULL;
2305
0
    sdb->private = sdb_p;
2306
0
    sdb->version = 1;
2307
0
    sdb->sdb_flags = inFlags | SDB_HAS_META;
2308
0
    sdb->app_private = NULL;
2309
0
    sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
2310
0
    sdb->sdb_FindObjects = sdb_FindObjects;
2311
0
    sdb->sdb_FindObjectsFinal = sdb_FindObjectsFinal;
2312
0
    sdb->sdb_GetAttributeValue = sdb_GetAttributeValue;
2313
0
    sdb->sdb_SetAttributeValue = sdb_SetAttributeValue;
2314
0
    sdb->sdb_CreateObject = sdb_CreateObject;
2315
0
    sdb->sdb_DestroyObject = sdb_DestroyObject;
2316
0
    sdb->sdb_GetMetaData = sdb_GetMetaData;
2317
0
    sdb->sdb_PutMetaData = sdb_PutMetaData;
2318
0
    sdb->sdb_DestroyMetaData = sdb_DestroyMetaData;
2319
0
    sdb->sdb_Begin = sdb_Begin;
2320
0
    sdb->sdb_Commit = sdb_Commit;
2321
0
    sdb->sdb_Abort = sdb_Abort;
2322
0
    sdb->sdb_Reset = sdb_Reset;
2323
0
    sdb->sdb_Close = sdb_Close;
2324
0
    sdb->sdb_SetForkState = sdb_SetForkState;
2325
0
    sdb->sdb_GetNewObjectID = sdb_GetNewObjectID;
2326
2327
0
    if (inTransaction) {
2328
0
        sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL, 0, NULL);
2329
0
        if (sqlerr != SQLITE_OK) {
2330
0
            error = sdb_mapSQLError(sdb_p->type, sqlerr);
2331
0
            goto loser;
2332
0
        }
2333
0
        inTransaction = 0;
2334
0
    }
2335
2336
0
    sdb_p->sqlReadDB = sqlDB;
2337
2338
0
    *pSdb = sdb;
2339
0
    UNLOCK_SQLITE();
2340
0
    return CKR_OK;
2341
2342
0
loser:
2343
    /* lots of stuff to do */
2344
0
    if (inTransaction) {
2345
0
        sqlite3_exec(sqlDB, ROLLBACK_CMD, NULL, 0, NULL);
2346
0
    }
2347
0
    if (sdb) {
2348
0
        free(sdb);
2349
0
    }
2350
0
    if (sdb_p) {
2351
0
        if (sdb_p->schemaAttrs) {
2352
0
            free(sdb_p->schemaAttrs);
2353
0
        }
2354
0
        free(sdb_p);
2355
0
    }
2356
0
    if (sqlDB) {
2357
0
        sqlite3_close(sqlDB);
2358
0
    }
2359
0
    UNLOCK_SQLITE();
2360
0
    return error;
2361
0
}
2362
2363
/* sdbopen */
2364
CK_RV
2365
s_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
0
{
2369
0
    char *cert = sdb_BuildFileName(directory, certPrefix,
2370
0
                                   "cert", cert_version);
2371
0
    char *key = sdb_BuildFileName(directory, keyPrefix,
2372
0
                                  "key", key_version);
2373
0
    CK_RV error = CKR_OK;
2374
0
    int inUpdate;
2375
0
    PRUint32 accessOps;
2376
2377
0
    if (certdb)
2378
0
        *certdb = NULL;
2379
0
    if (keydb)
2380
0
        *keydb = NULL;
2381
0
    *newInit = 0;
2382
2383
#ifdef SQLITE_UNSAFE_THREADS
2384
    if (sqlite_lock == NULL) {
2385
        sqlite_lock = PR_NewLock();
2386
        if (sqlite_lock == NULL) {
2387
            error = CKR_HOST_MEMORY;
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
0
    accessOps = 1;
2396
0
    {
2397
0
        char *env;
2398
0
        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
0
        if (env && PORT_Strcasecmp(env, "no") != 0 &&
2403
0
            PORT_Strcasecmp(env, "yes") != 0) {
2404
0
            accessOps = sdb_measureAccess(directory);
2405
0
        }
2406
0
    }
2407
2408
    /*
2409
     * open the cert data base
2410
     */
2411
0
    if (certdb) {
2412
        /* initialize Certificate database */
2413
0
        error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate,
2414
0
                         newInit, flags, accessOps, certdb);
2415
0
        if (error != CKR_OK) {
2416
0
            goto loser;
2417
0
        }
2418
0
    }
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
0
    if (keydb) {
2429
        /* initialize the Key database */
2430
0
        error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate,
2431
0
                         newInit, flags, accessOps, keydb);
2432
0
        if (error != CKR_OK) {
2433
0
            goto loser;
2434
0
        }
2435
0
    }
2436
2437
0
loser:
2438
0
    if (cert) {
2439
0
        sqlite3_free(cert);
2440
0
    }
2441
0
    if (key) {
2442
0
        sqlite3_free(key);
2443
0
    }
2444
2445
0
    if (error != CKR_OK) {
2446
        /* currently redundant, but could be necessary if more code is added
2447
         * just before loser */
2448
0
        if (keydb && *keydb) {
2449
0
            sdb_Close(*keydb);
2450
0
        }
2451
0
        if (certdb && *certdb) {
2452
0
            sdb_Close(*certdb);
2453
0
        }
2454
0
    }
2455
2456
0
    return error;
2457
0
}
2458
2459
CK_RV
2460
s_shutdown()
2461
0
{
2462
#ifdef SQLITE_UNSAFE_THREADS
2463
    if (sqlite_lock) {
2464
        PR_DestroyLock(sqlite_lock);
2465
        sqlite_lock = NULL;
2466
    }
2467
#endif
2468
0
    return CKR_OK;
2469
0
}