Coverage Report

Created: 2025-07-11 07:05

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