tor-browser

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

pk11db.c (22541B)


      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 *  The following code handles the storage of PKCS 11 modules used by the
      6 * NSS. This file is written to abstract away how the modules are
      7 * stored so we can deside that later.
      8 */
      9 
     10 #include "lgdb.h"
     11 #include "mcom_db.h"
     12 #include "secerr.h"
     13 #include "utilpars.h"
     14 
     15 #define FREE_CLEAR(p) \
     16    if (p) {          \
     17        PORT_Free(p); \
     18        p = NULL;     \
     19    }
     20 
     21 /* Construct a database key for a given module */
     22 static SECStatus
     23 lgdb_MakeKey(DBT *key, char *module)
     24 {
     25    int len = 0;
     26    char *commonName;
     27 
     28    commonName = NSSUTIL_ArgGetParamValue("name", module);
     29    if (commonName == NULL) {
     30        commonName = NSSUTIL_ArgGetParamValue("library", module);
     31    }
     32    if (commonName == NULL)
     33        return SECFailure;
     34    len = PORT_Strlen(commonName);
     35    key->data = commonName;
     36    key->size = len;
     37    return SECSuccess;
     38 }
     39 
     40 /* free out constructed database key */
     41 static void
     42 lgdb_FreeKey(DBT *key)
     43 {
     44    if (key->data) {
     45        PORT_Free(key->data);
     46    }
     47    key->data = NULL;
     48    key->size = 0;
     49 }
     50 
     51 typedef struct lgdbDataStr lgdbData;
     52 typedef struct lgdbSlotDataStr lgdbSlotData;
     53 struct lgdbDataStr {
     54    unsigned char major;
     55    unsigned char minor;
     56    unsigned char nameStart[2];
     57    unsigned char slotOffset[2];
     58    unsigned char internal;
     59    unsigned char fips;
     60    unsigned char ssl[8];
     61    unsigned char trustOrder[4];
     62    unsigned char cipherOrder[4];
     63    unsigned char reserved1;
     64    unsigned char isModuleDB;
     65    unsigned char isModuleDBOnly;
     66    unsigned char isCritical;
     67    unsigned char reserved[4];
     68    unsigned char names[6]; /* enough space for the length fields */
     69 };
     70 
     71 struct lgdbSlotDataStr {
     72    unsigned char slotID[4];
     73    unsigned char defaultFlags[4];
     74    unsigned char timeout[4];
     75    unsigned char askpw;
     76    unsigned char hasRootCerts;
     77    unsigned char reserved[18]; /* this makes it a round 32 bytes */
     78 };
     79 
     80 #define LGDB_DB_VERSION_MAJOR 0
     81 #define LGDB_DB_VERSION_MINOR 6
     82 #define LGDB_DB_EXT1_VERSION_MAJOR 0
     83 #define LGDB_DB_EXT1_VERSION_MINOR 6
     84 #define LGDB_DB_NOUI_VERSION_MAJOR 0
     85 #define LGDB_DB_NOUI_VERSION_MINOR 4
     86 
     87 #define LGDB_PUTSHORT(dest, src)             \
     88    (dest)[1] = (unsigned char)((src)&0xff); \
     89    (dest)[0] = (unsigned char)(((src) >> 8) & 0xff);
     90 #define LGDB_PUTLONG(dest, src)                        \
     91    (dest)[3] = (unsigned char)((src)&0xff);           \
     92    (dest)[2] = (unsigned char)(((src) >> 8) & 0xff);  \
     93    (dest)[1] = (unsigned char)(((src) >> 16) & 0xff); \
     94    (dest)[0] = (unsigned char)(((src) >> 24) & 0xff);
     95 #define LGDB_GETSHORT(src) \
     96    ((unsigned short)(((src)[0] << 8) | (src)[1]))
     97 #define LGDB_GETLONG(src)                              \
     98    ((unsigned long)(((unsigned long)(src)[0] << 24) | \
     99                     ((unsigned long)(src)[1] << 16) | \
    100                     ((unsigned long)(src)[2] << 8) |  \
    101                     (unsigned long)(src)[3]))
    102 
    103 /*
    104 * build a data base entry from a module
    105 */
    106 static SECStatus
    107 lgdb_EncodeData(DBT *data, char *module)
    108 {
    109    lgdbData *encoded = NULL;
    110    lgdbSlotData *slot;
    111    unsigned char *dataPtr, *offsetPtr;
    112    unsigned short len, len2 = 0, len3 = 0;
    113    int count = 0;
    114    unsigned short offset;
    115    int dataLen, i;
    116    unsigned long order;
    117    unsigned long ssl[2];
    118    char *commonName = NULL, *dllName = NULL, *param = NULL, *nss = NULL;
    119    char *slotParams, *ciphers;
    120    struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
    121    SECStatus rv = SECFailure;
    122 
    123    rv = NSSUTIL_ArgParseModuleSpec(module, &dllName, &commonName, &param, &nss);
    124    if (rv != SECSuccess)
    125        return rv;
    126    rv = SECFailure;
    127 
    128    if (commonName == NULL) {
    129        /* set error */
    130        goto loser;
    131    }
    132 
    133    len = PORT_Strlen(commonName);
    134    if (dllName) {
    135        len2 = PORT_Strlen(dllName);
    136    }
    137    if (param) {
    138        len3 = PORT_Strlen(param);
    139    }
    140 
    141    slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss);
    142    slotInfo = NSSUTIL_ArgParseSlotInfo(NULL, slotParams, &count);
    143    if (slotParams)
    144        PORT_Free(slotParams);
    145 
    146    if (count && slotInfo == NULL) {
    147        /* set error */
    148        goto loser;
    149    }
    150 
    151    dataLen = sizeof(lgdbData) + len + len2 + len3 + sizeof(unsigned short) +
    152              count * sizeof(lgdbSlotData);
    153 
    154    data->data = (unsigned char *)PORT_ZAlloc(dataLen);
    155    encoded = (lgdbData *)data->data;
    156    dataPtr = (unsigned char *)data->data;
    157    data->size = dataLen;
    158 
    159    if (encoded == NULL) {
    160        /* set error */
    161        goto loser;
    162    }
    163 
    164    encoded->major = LGDB_DB_VERSION_MAJOR;
    165    encoded->minor = LGDB_DB_VERSION_MINOR;
    166    encoded->internal = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "internal", nss) ? 1 : 0);
    167    encoded->fips = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "FIPS", nss) ? 1 : 0);
    168    encoded->isModuleDB = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDB", nss) ? 1 : 0);
    169    encoded->isModuleDBOnly = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDBOnly", nss) ? 1 : 0);
    170    encoded->isCritical = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "critical", nss) ? 1 : 0);
    171 
    172    order = NSSUTIL_ArgReadLong("trustOrder", nss,
    173                                NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
    174    LGDB_PUTLONG(encoded->trustOrder, order);
    175    order = NSSUTIL_ArgReadLong("cipherOrder", nss,
    176                                NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
    177    LGDB_PUTLONG(encoded->cipherOrder, order);
    178 
    179    ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss);
    180    NSSUTIL_ArgParseCipherFlags(&ssl[0], ciphers);
    181    LGDB_PUTLONG(encoded->ssl, ssl[0]);
    182    LGDB_PUTLONG(&encoded->ssl[4], ssl[1]);
    183    if (ciphers)
    184        PORT_Free(ciphers);
    185 
    186    offset = (unsigned short)offsetof(lgdbData, names);
    187    LGDB_PUTSHORT(encoded->nameStart, offset);
    188    offset = offset + len + len2 + len3 + 3 * sizeof(unsigned short);
    189    LGDB_PUTSHORT(encoded->slotOffset, offset);
    190 
    191    LGDB_PUTSHORT(&dataPtr[offset], ((unsigned short)count));
    192    slot = (lgdbSlotData *)(dataPtr + offset + sizeof(unsigned short));
    193 
    194    offsetPtr = encoded->names;
    195    LGDB_PUTSHORT(encoded->names, len);
    196    offsetPtr += sizeof(unsigned short);
    197    PORT_Memcpy(offsetPtr, commonName, len);
    198    offsetPtr += len;
    199 
    200    LGDB_PUTSHORT(offsetPtr, len2);
    201    offsetPtr += sizeof(unsigned short);
    202    if (len2) {
    203        PORT_Memcpy(offsetPtr, dllName, len2);
    204    }
    205    offsetPtr += len2;
    206 
    207    LGDB_PUTSHORT(offsetPtr, len3);
    208    offsetPtr += sizeof(unsigned short);
    209    if (len3) {
    210        PORT_Memcpy(offsetPtr, param, len3);
    211    }
    212    offsetPtr += len3;
    213 
    214    if (count) {
    215        for (i = 0; i < count; i++) {
    216            LGDB_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
    217            LGDB_PUTLONG(slot[i].defaultFlags,
    218                         slotInfo[i].defaultFlags);
    219            LGDB_PUTLONG(slot[i].timeout, slotInfo[i].timeout);
    220            slot[i].askpw = slotInfo[i].askpw;
    221            slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
    222            PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
    223        }
    224    }
    225    rv = SECSuccess;
    226 
    227 loser:
    228    if (commonName)
    229        PORT_Free(commonName);
    230    if (dllName)
    231        PORT_Free(dllName);
    232    if (param)
    233        PORT_Free(param);
    234    if (slotInfo)
    235        PORT_Free(slotInfo);
    236    if (nss)
    237        PORT_Free(nss);
    238    return rv;
    239 }
    240 
    241 static void
    242 lgdb_FreeData(DBT *data)
    243 {
    244    if (data->data) {
    245        PORT_Free(data->data);
    246    }
    247 }
    248 
    249 static void
    250 lgdb_FreeSlotStrings(char **slotStrings, int count)
    251 {
    252    int i;
    253 
    254    for (i = 0; i < count; i++) {
    255        if (slotStrings[i]) {
    256            PR_smprintf_free(slotStrings[i]);
    257            slotStrings[i] = NULL;
    258        }
    259    }
    260 }
    261 
    262 /*
    263 * build a module from the data base entry.
    264 */
    265 static char *
    266 lgdb_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
    267 {
    268    lgdbData *encoded;
    269    lgdbSlotData *slots;
    270    PLArenaPool *arena;
    271    char *commonName = NULL;
    272    char *dllName = NULL;
    273    char *parameters = NULL;
    274    char *nss;
    275    char *moduleSpec;
    276    char **slotStrings = NULL;
    277    unsigned char *names;
    278    unsigned long slotCount;
    279    unsigned long ssl0 = 0;
    280    unsigned long ssl1 = 0;
    281    unsigned long slotID;
    282    unsigned long defaultFlags;
    283    unsigned long timeout;
    284    unsigned long trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER;
    285    unsigned long cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER;
    286    unsigned short len;
    287    unsigned short namesOffset = 0;   /* start of the names block */
    288    unsigned long namesRunningOffset; /* offset to name we are
    289                                       * currently processing */
    290    unsigned short slotOffset;
    291    PRBool isOldVersion = PR_FALSE;
    292    PRBool internal;
    293    PRBool isFIPS;
    294    PRBool isModuleDB = PR_FALSE;
    295    PRBool isModuleDBOnly = PR_FALSE;
    296    PRBool extended = PR_FALSE;
    297    int i;
    298 
    299    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    300    if (arena == NULL)
    301        return NULL;
    302 
    303 #define CHECK_SIZE(x)                                 \
    304    if ((unsigned int)data->size < (unsigned int)(x)) \
    305    goto db_loser
    306 
    307    /* -------------------------------------------------------------
    308    ** Process the buffer header, which is the lgdbData struct.
    309    ** It may be an old or new version.  Check the length for each.
    310    */
    311 
    312    CHECK_SIZE(offsetof(lgdbData, trustOrder[0]));
    313 
    314    encoded = (lgdbData *)data->data;
    315 
    316    internal = (encoded->internal != 0) ? PR_TRUE : PR_FALSE;
    317    isFIPS = (encoded->fips != 0) ? PR_TRUE : PR_FALSE;
    318 
    319    if (retInternal)
    320        *retInternal = internal;
    321    if (internal) {
    322        parameters = PORT_ArenaStrdup(arena, defParams);
    323        if (parameters == NULL)
    324            goto loser;
    325    }
    326    if (internal && (encoded->major == LGDB_DB_NOUI_VERSION_MAJOR) &&
    327        (encoded->minor <= LGDB_DB_NOUI_VERSION_MINOR)) {
    328        isOldVersion = PR_TRUE;
    329    }
    330    if ((encoded->major == LGDB_DB_EXT1_VERSION_MAJOR) &&
    331        (encoded->minor >= LGDB_DB_EXT1_VERSION_MINOR)) {
    332        CHECK_SIZE(sizeof(lgdbData));
    333        trustOrder = LGDB_GETLONG(encoded->trustOrder);
    334        cipherOrder = LGDB_GETLONG(encoded->cipherOrder);
    335        isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE : PR_FALSE;
    336        isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE : PR_FALSE;
    337        extended = PR_TRUE;
    338    }
    339    if (internal && !extended) {
    340        trustOrder = 0;
    341        cipherOrder = 100;
    342    }
    343    /* decode SSL cipher enable flags */
    344    ssl0 = LGDB_GETLONG(encoded->ssl);
    345    ssl1 = LGDB_GETLONG(encoded->ssl + 4);
    346 
    347    slotOffset = LGDB_GETSHORT(encoded->slotOffset);
    348    namesOffset = LGDB_GETSHORT(encoded->nameStart);
    349 
    350    /*--------------------------------------------------------------
    351    ** Now process the variable length set of names.
    352    ** The names have this structure:
    353    ** struct {
    354    **     BYTE  commonNameLen[ 2 ];
    355    **     BYTE  commonName   [ commonNameLen ];
    356    **     BTTE  libNameLen   [ 2 ];
    357    **     BYTE  libName      [ libNameLen ];
    358    ** If it is "extended" it also has these members:
    359    **     BYTE  initStringLen[ 2 ];
    360    **     BYTE  initString   [ initStringLen ];
    361    ** }
    362    */
    363 
    364    namesRunningOffset = namesOffset;
    365    /* copy the module's common name */
    366    CHECK_SIZE(namesRunningOffset + 2);
    367    names = (unsigned char *)data->data;
    368    len = LGDB_GETSHORT(names + namesRunningOffset);
    369 
    370    CHECK_SIZE(namesRunningOffset + 2 + len);
    371    commonName = (char *)PORT_ArenaAlloc(arena, len + 1);
    372    if (commonName == NULL)
    373        goto loser;
    374    PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
    375    commonName[len] = 0;
    376    namesRunningOffset += len + 2;
    377 
    378    /* copy the module's shared library file name. */
    379    CHECK_SIZE(namesRunningOffset + 2);
    380    len = LGDB_GETSHORT(names + namesRunningOffset);
    381    if (len) {
    382        CHECK_SIZE(namesRunningOffset + 2 + len);
    383        dllName = (char *)PORT_ArenaAlloc(arena, len + 1);
    384        if (dllName == NULL)
    385            goto loser;
    386        PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
    387        dllName[len] = 0;
    388    }
    389    namesRunningOffset += len + 2;
    390 
    391    /* copy the module's initialization string, if present. */
    392    if (!internal && extended) {
    393        CHECK_SIZE(namesRunningOffset + 2);
    394        len = LGDB_GETSHORT(names + namesRunningOffset);
    395        if (len) {
    396            CHECK_SIZE(namesRunningOffset + 2 + len);
    397            parameters = (char *)PORT_ArenaAlloc(arena, len + 1);
    398            if (parameters == NULL)
    399                goto loser;
    400            PORT_Memcpy(parameters, names + namesRunningOffset + 2, len);
    401            parameters[len] = 0;
    402        }
    403        namesRunningOffset += len + 2;
    404    }
    405 
    406    /*
    407     * Consistency check: Make sure the slot and names blocks don't
    408     * overlap. These blocks can occur in any order, so this check is made
    409     * in 2 parts. First we check the case where the slot block starts
    410     * after the name block. Later, when we have the slot block length,
    411     * we check the case where slot block starts before the name block.
    412     * NOTE: in most cases any overlap will likely be detected by invalid
    413     * data read from the blocks, but it's better to find out sooner
    414     * than later.
    415     */
    416    if (slotOffset >= namesOffset) { /* slot block starts after name block */
    417        if (slotOffset < namesRunningOffset) {
    418            goto db_loser;
    419        }
    420    }
    421 
    422    /* ------------------------------------------------------------------
    423    ** Part 3, process the slot table.
    424    ** This part has this structure:
    425    ** struct {
    426    **     BYTE slotCount [ 2 ];
    427    **     lgdbSlotData [ slotCount ];
    428    ** {
    429    */
    430 
    431    CHECK_SIZE(slotOffset + 2);
    432    slotCount = LGDB_GETSHORT((unsigned char *)data->data + slotOffset);
    433 
    434    /*
    435     * Consistency check: Part 2. We now have the slot block length, we can
    436     * check the case where the slotblock procedes the name block.
    437     */
    438    if (slotOffset < namesOffset) { /* slot block starts before name block */
    439        if (namesOffset < slotOffset + 2 + slotCount * sizeof(lgdbSlotData)) {
    440            goto db_loser;
    441        }
    442    }
    443 
    444    CHECK_SIZE((slotOffset + 2 + slotCount * sizeof(lgdbSlotData)));
    445    slots = (lgdbSlotData *)((unsigned char *)data->data + slotOffset + 2);
    446 
    447    /*  slotCount; */
    448    slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
    449    if (slotStrings == NULL)
    450        goto loser;
    451    for (i = 0; i < (int)slotCount; i++, slots++) {
    452        PRBool hasRootCerts = PR_FALSE;
    453        PRBool hasRootTrust = PR_FALSE;
    454        slotID = LGDB_GETLONG(slots->slotID);
    455        defaultFlags = LGDB_GETLONG(slots->defaultFlags);
    456        timeout = LGDB_GETLONG(slots->timeout);
    457        hasRootCerts = slots->hasRootCerts;
    458        if (isOldVersion && internal && (slotID != 2)) {
    459            unsigned long internalFlags =
    460                NSSUTIL_ArgParseSlotFlags("slotFlags",
    461                                          NSSUTIL_DEFAULT_SFTKN_FLAGS);
    462            defaultFlags |= internalFlags;
    463        }
    464        if (hasRootCerts && !extended) {
    465            trustOrder = 100;
    466        }
    467 
    468        slotStrings[i] = NSSUTIL_MkSlotString(slotID, defaultFlags, timeout,
    469                                              (unsigned char)slots->askpw,
    470                                              hasRootCerts, hasRootTrust);
    471        if (slotStrings[i] == NULL) {
    472            lgdb_FreeSlotStrings(slotStrings, i);
    473            goto loser;
    474        }
    475    }
    476 
    477    nss = NSSUTIL_MkNSSString(slotStrings, slotCount, internal, isFIPS,
    478                              isModuleDB, isModuleDBOnly, internal, trustOrder,
    479                              cipherOrder, ssl0, ssl1);
    480    lgdb_FreeSlotStrings(slotStrings, slotCount);
    481    /* it's permissible (and normal) for nss to be NULL. it simply means
    482     * there are no NSS specific parameters in the database */
    483    moduleSpec = NSSUTIL_MkModuleSpec(dllName, commonName, parameters, nss);
    484    PR_smprintf_free(nss);
    485    PORT_FreeArena(arena, PR_TRUE);
    486    return moduleSpec;
    487 
    488 db_loser:
    489    PORT_SetError(SEC_ERROR_BAD_DATABASE);
    490 loser:
    491    PORT_FreeArena(arena, PR_TRUE);
    492    return NULL;
    493 }
    494 
    495 static DB *
    496 lgdb_OpenDB(const char *appName, const char *filename, const char *dbName,
    497            PRBool readOnly, PRBool update)
    498 {
    499    DB *pkcs11db = NULL;
    500 
    501    if (appName) {
    502        char *secname = PORT_Strdup(filename);
    503        int len = strlen(secname);
    504        int status = RDB_FAIL;
    505 
    506        if (len >= 3 && PORT_Strcmp(&secname[len - 3], ".db") == 0) {
    507            secname[len - 3] = 0;
    508        }
    509        pkcs11db =
    510            rdbopen(appName, "", secname, readOnly ? NO_RDONLY : NO_RDWR, NULL);
    511        if (update && !pkcs11db) {
    512            DB *updatedb;
    513 
    514            pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
    515            if (!pkcs11db) {
    516                if (status == RDB_RETRY) {
    517                    pkcs11db = rdbopen(appName, "", secname,
    518                                       readOnly ? NO_RDONLY : NO_RDWR, NULL);
    519                }
    520                PORT_Free(secname);
    521                return pkcs11db;
    522            }
    523            updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
    524            if (updatedb) {
    525                db_Copy(pkcs11db, updatedb);
    526                (*updatedb->close)(updatedb);
    527            } else {
    528                (*pkcs11db->close)(pkcs11db);
    529                PORT_Free(secname);
    530                return NULL;
    531            }
    532        }
    533        PORT_Free(secname);
    534        return pkcs11db;
    535    }
    536 
    537    /* I'm sure we should do more checks here sometime... */
    538    pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
    539 
    540    /* didn't exist? create it */
    541    if (pkcs11db == NULL) {
    542        if (readOnly)
    543            return NULL;
    544 
    545        pkcs11db = dbopen(dbName, NO_CREATE, 0600, DB_HASH, 0);
    546        if (pkcs11db)
    547            (*pkcs11db->sync)(pkcs11db, 0);
    548    }
    549    return pkcs11db;
    550 }
    551 
    552 static void
    553 lgdb_CloseDB(DB *pkcs11db)
    554 {
    555    (*pkcs11db->close)(pkcs11db);
    556 }
    557 
    558 SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
    559                             const char *dbname, char *module, PRBool rw);
    560 
    561 #define LGDB_STEP 10
    562 /*
    563 * Read all the existing modules in
    564 */
    565 char **
    566 legacy_ReadSecmodDB(const char *appName, const char *filename,
    567                    const char *dbname, char *params, PRBool rw)
    568 {
    569    DBT key, data;
    570    int ret;
    571    DB *pkcs11db = NULL;
    572    char **moduleList = NULL, **newModuleList = NULL;
    573    int moduleCount = 1;
    574    int useCount = LGDB_STEP;
    575 
    576    moduleList = (char **)PORT_ZAlloc(useCount * sizeof(char **));
    577    if (moduleList == NULL)
    578        return NULL;
    579 
    580    pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_TRUE, rw);
    581    if (pkcs11db == NULL)
    582        goto done;
    583 
    584    /* read and parse the file or data base */
    585    ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
    586    if (ret)
    587        goto done;
    588 
    589    do {
    590        char *moduleString;
    591        PRBool internal = PR_FALSE;
    592        if ((moduleCount + 1) >= useCount) {
    593            useCount += LGDB_STEP;
    594            newModuleList =
    595                (char **)PORT_Realloc(moduleList, useCount * sizeof(char *));
    596            if (newModuleList == NULL)
    597                goto done;
    598            moduleList = newModuleList;
    599            PORT_Memset(&moduleList[moduleCount + 1], 0,
    600                        sizeof(char *) * LGDB_STEP);
    601        }
    602        moduleString = lgdb_DecodeData(params, &data, &internal);
    603        if (internal) {
    604            moduleList[0] = moduleString;
    605        } else {
    606            moduleList[moduleCount] = moduleString;
    607            moduleCount++;
    608        }
    609    } while ((*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
    610 
    611 done:
    612    if (!moduleList[0]) {
    613        char *newparams = NSSUTIL_Quote(params, '"');
    614        if (newparams) {
    615            moduleList[0] = PR_smprintf(
    616                NSSUTIL_DEFAULT_INTERNAL_INIT1 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT2 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT3,
    617                newparams, NSSUTIL_DEFAULT_SFTKN_FLAGS);
    618            PORT_Free(newparams);
    619        }
    620    }
    621    /* deal with trust cert db here */
    622 
    623    if (pkcs11db) {
    624        lgdb_CloseDB(pkcs11db);
    625    } else if (moduleList[0] && rw) {
    626        legacy_AddSecmodDB(appName, filename, dbname, moduleList[0], rw);
    627    }
    628    if (!moduleList[0]) {
    629        PORT_Free(moduleList);
    630        moduleList = NULL;
    631    }
    632    return moduleList;
    633 }
    634 
    635 SECStatus
    636 legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
    637                           const char *dbname, char **moduleSpecList, PRBool rw)
    638 {
    639    if (moduleSpecList) {
    640        char **index;
    641        for (index = moduleSpecList; *index; index++) {
    642            PR_smprintf_free(*index);
    643        }
    644        PORT_Free(moduleSpecList);
    645    }
    646    return SECSuccess;
    647 }
    648 
    649 /*
    650 * Delete a module from the Data Base
    651 */
    652 SECStatus
    653 legacy_DeleteSecmodDB(const char *appName, const char *filename,
    654                      const char *dbname, char *args, PRBool rw)
    655 {
    656    DBT key;
    657    SECStatus rv = SECFailure;
    658    DB *pkcs11db = NULL;
    659    int ret;
    660 
    661    if (!rw)
    662        return SECFailure;
    663 
    664    /* make sure we have a db handle */
    665    pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE);
    666    if (pkcs11db == NULL) {
    667        return SECFailure;
    668    }
    669 
    670    rv = lgdb_MakeKey(&key, args);
    671    if (rv != SECSuccess)
    672        goto done;
    673    rv = SECFailure;
    674    ret = (*pkcs11db->del)(pkcs11db, &key, 0);
    675    lgdb_FreeKey(&key);
    676    if (ret != 0)
    677        goto done;
    678 
    679    ret = (*pkcs11db->sync)(pkcs11db, 0);
    680    if (ret == 0)
    681        rv = SECSuccess;
    682 
    683 done:
    684    lgdb_CloseDB(pkcs11db);
    685    return rv;
    686 }
    687 
    688 /*
    689 * Add a module to the Data base
    690 */
    691 SECStatus
    692 legacy_AddSecmodDB(const char *appName, const char *filename,
    693                   const char *dbname, char *module, PRBool rw)
    694 {
    695    DBT key, data;
    696    SECStatus rv = SECFailure;
    697    DB *pkcs11db = NULL;
    698    int ret;
    699 
    700    if (!rw)
    701        return SECFailure;
    702 
    703    /* make sure we have a db handle */
    704    pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE);
    705    if (pkcs11db == NULL) {
    706        return SECFailure;
    707    }
    708 
    709    rv = lgdb_MakeKey(&key, module);
    710    if (rv != SECSuccess)
    711        goto done;
    712    rv = lgdb_EncodeData(&data, module);
    713    if (rv != SECSuccess) {
    714        lgdb_FreeKey(&key);
    715        goto done;
    716    }
    717    rv = SECFailure;
    718    ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
    719    lgdb_FreeKey(&key);
    720    lgdb_FreeData(&data);
    721    if (ret != 0)
    722        goto done;
    723 
    724    ret = (*pkcs11db->sync)(pkcs11db, 0);
    725    if (ret == 0)
    726        rv = SECSuccess;
    727 
    728 done:
    729    lgdb_CloseDB(pkcs11db);
    730    return rv;
    731 }