tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sdb.c (81575B)


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