summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/softoken/legacydb/pk11db.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/lib/softoken/legacydb/pk11db.c
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/lib/softoken/legacydb/pk11db.c')
-rw-r--r--security/nss/lib/softoken/legacydb/pk11db.c731
1 files changed, 731 insertions, 0 deletions
diff --git a/security/nss/lib/softoken/legacydb/pk11db.c b/security/nss/lib/softoken/legacydb/pk11db.c
new file mode 100644
index 0000000000..a7421c83d3
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/pk11db.c
@@ -0,0 +1,731 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. This file is written to abstract away how the modules are
+ * stored so we can deside that later.
+ */
+
+#include "lgdb.h"
+#include "mcom_db.h"
+#include "secerr.h"
+#include "utilpars.h"
+
+#define FREE_CLEAR(p) \
+ if (p) { \
+ PORT_Free(p); \
+ p = NULL; \
+ }
+
+/* Construct a database key for a given module */
+static SECStatus
+lgdb_MakeKey(DBT *key, char *module)
+{
+ int len = 0;
+ char *commonName;
+
+ commonName = NSSUTIL_ArgGetParamValue("name", module);
+ if (commonName == NULL) {
+ commonName = NSSUTIL_ArgGetParamValue("library", module);
+ }
+ if (commonName == NULL)
+ return SECFailure;
+ len = PORT_Strlen(commonName);
+ key->data = commonName;
+ key->size = len;
+ return SECSuccess;
+}
+
+/* free out constructed database key */
+static void
+lgdb_FreeKey(DBT *key)
+{
+ if (key->data) {
+ PORT_Free(key->data);
+ }
+ key->data = NULL;
+ key->size = 0;
+}
+
+typedef struct lgdbDataStr lgdbData;
+typedef struct lgdbSlotDataStr lgdbSlotData;
+struct lgdbDataStr {
+ unsigned char major;
+ unsigned char minor;
+ unsigned char nameStart[2];
+ unsigned char slotOffset[2];
+ unsigned char internal;
+ unsigned char fips;
+ unsigned char ssl[8];
+ unsigned char trustOrder[4];
+ unsigned char cipherOrder[4];
+ unsigned char reserved1;
+ unsigned char isModuleDB;
+ unsigned char isModuleDBOnly;
+ unsigned char isCritical;
+ unsigned char reserved[4];
+ unsigned char names[6]; /* enough space for the length fields */
+};
+
+struct lgdbSlotDataStr {
+ unsigned char slotID[4];
+ unsigned char defaultFlags[4];
+ unsigned char timeout[4];
+ unsigned char askpw;
+ unsigned char hasRootCerts;
+ unsigned char reserved[18]; /* this makes it a round 32 bytes */
+};
+
+#define LGDB_DB_VERSION_MAJOR 0
+#define LGDB_DB_VERSION_MINOR 6
+#define LGDB_DB_EXT1_VERSION_MAJOR 0
+#define LGDB_DB_EXT1_VERSION_MINOR 6
+#define LGDB_DB_NOUI_VERSION_MAJOR 0
+#define LGDB_DB_NOUI_VERSION_MINOR 4
+
+#define LGDB_PUTSHORT(dest, src) \
+ (dest)[1] = (unsigned char)((src)&0xff); \
+ (dest)[0] = (unsigned char)(((src) >> 8) & 0xff);
+#define LGDB_PUTLONG(dest, src) \
+ (dest)[3] = (unsigned char)((src)&0xff); \
+ (dest)[2] = (unsigned char)(((src) >> 8) & 0xff); \
+ (dest)[1] = (unsigned char)(((src) >> 16) & 0xff); \
+ (dest)[0] = (unsigned char)(((src) >> 24) & 0xff);
+#define LGDB_GETSHORT(src) \
+ ((unsigned short)(((src)[0] << 8) | (src)[1]))
+#define LGDB_GETLONG(src) \
+ ((unsigned long)(((unsigned long)(src)[0] << 24) | \
+ ((unsigned long)(src)[1] << 16) | \
+ ((unsigned long)(src)[2] << 8) | \
+ (unsigned long)(src)[3]))
+
+/*
+ * build a data base entry from a module
+ */
+static SECStatus
+lgdb_EncodeData(DBT *data, char *module)
+{
+ lgdbData *encoded = NULL;
+ lgdbSlotData *slot;
+ unsigned char *dataPtr, *offsetPtr;
+ unsigned short len, len2 = 0, len3 = 0;
+ int count = 0;
+ unsigned short offset;
+ int dataLen, i;
+ unsigned long order;
+ unsigned long ssl[2];
+ char *commonName = NULL, *dllName = NULL, *param = NULL, *nss = NULL;
+ char *slotParams, *ciphers;
+ struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
+ SECStatus rv = SECFailure;
+
+ rv = NSSUTIL_ArgParseModuleSpec(module, &dllName, &commonName, &param, &nss);
+ if (rv != SECSuccess)
+ return rv;
+ rv = SECFailure;
+
+ if (commonName == NULL) {
+ /* set error */
+ goto loser;
+ }
+
+ len = PORT_Strlen(commonName);
+ if (dllName) {
+ len2 = PORT_Strlen(dllName);
+ }
+ if (param) {
+ len3 = PORT_Strlen(param);
+ }
+
+ slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss);
+ slotInfo = NSSUTIL_ArgParseSlotInfo(NULL, slotParams, &count);
+ if (slotParams)
+ PORT_Free(slotParams);
+
+ if (count && slotInfo == NULL) {
+ /* set error */
+ goto loser;
+ }
+
+ dataLen = sizeof(lgdbData) + len + len2 + len3 + sizeof(unsigned short) +
+ count * sizeof(lgdbSlotData);
+
+ data->data = (unsigned char *)PORT_ZAlloc(dataLen);
+ encoded = (lgdbData *)data->data;
+ dataPtr = (unsigned char *)data->data;
+ data->size = dataLen;
+
+ if (encoded == NULL) {
+ /* set error */
+ goto loser;
+ }
+
+ encoded->major = LGDB_DB_VERSION_MAJOR;
+ encoded->minor = LGDB_DB_VERSION_MINOR;
+ encoded->internal = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "internal", nss) ? 1 : 0);
+ encoded->fips = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "FIPS", nss) ? 1 : 0);
+ encoded->isModuleDB = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDB", nss) ? 1 : 0);
+ encoded->isModuleDBOnly = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDBOnly", nss) ? 1 : 0);
+ encoded->isCritical = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "critical", nss) ? 1 : 0);
+
+ order = NSSUTIL_ArgReadLong("trustOrder", nss,
+ NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
+ LGDB_PUTLONG(encoded->trustOrder, order);
+ order = NSSUTIL_ArgReadLong("cipherOrder", nss,
+ NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
+ LGDB_PUTLONG(encoded->cipherOrder, order);
+
+ ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss);
+ NSSUTIL_ArgParseCipherFlags(&ssl[0], ciphers);
+ LGDB_PUTLONG(encoded->ssl, ssl[0]);
+ LGDB_PUTLONG(&encoded->ssl[4], ssl[1]);
+ if (ciphers)
+ PORT_Free(ciphers);
+
+ offset = (unsigned short)offsetof(lgdbData, names);
+ LGDB_PUTSHORT(encoded->nameStart, offset);
+ offset = offset + len + len2 + len3 + 3 * sizeof(unsigned short);
+ LGDB_PUTSHORT(encoded->slotOffset, offset);
+
+ LGDB_PUTSHORT(&dataPtr[offset], ((unsigned short)count));
+ slot = (lgdbSlotData *)(dataPtr + offset + sizeof(unsigned short));
+
+ offsetPtr = encoded->names;
+ LGDB_PUTSHORT(encoded->names, len);
+ offsetPtr += sizeof(unsigned short);
+ PORT_Memcpy(offsetPtr, commonName, len);
+ offsetPtr += len;
+
+ LGDB_PUTSHORT(offsetPtr, len2);
+ offsetPtr += sizeof(unsigned short);
+ if (len2) {
+ PORT_Memcpy(offsetPtr, dllName, len2);
+ }
+ offsetPtr += len2;
+
+ LGDB_PUTSHORT(offsetPtr, len3);
+ offsetPtr += sizeof(unsigned short);
+ if (len3) {
+ PORT_Memcpy(offsetPtr, param, len3);
+ }
+ offsetPtr += len3;
+
+ if (count) {
+ for (i = 0; i < count; i++) {
+ LGDB_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
+ LGDB_PUTLONG(slot[i].defaultFlags,
+ slotInfo[i].defaultFlags);
+ LGDB_PUTLONG(slot[i].timeout, slotInfo[i].timeout);
+ slot[i].askpw = slotInfo[i].askpw;
+ slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
+ PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
+ }
+ }
+ rv = SECSuccess;
+
+loser:
+ if (commonName)
+ PORT_Free(commonName);
+ if (dllName)
+ PORT_Free(dllName);
+ if (param)
+ PORT_Free(param);
+ if (slotInfo)
+ PORT_Free(slotInfo);
+ if (nss)
+ PORT_Free(nss);
+ return rv;
+}
+
+static void
+lgdb_FreeData(DBT *data)
+{
+ if (data->data) {
+ PORT_Free(data->data);
+ }
+}
+
+static void
+lgdb_FreeSlotStrings(char **slotStrings, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (slotStrings[i]) {
+ PR_smprintf_free(slotStrings[i]);
+ slotStrings[i] = NULL;
+ }
+ }
+}
+
+/*
+ * build a module from the data base entry.
+ */
+static char *
+lgdb_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
+{
+ lgdbData *encoded;
+ lgdbSlotData *slots;
+ PLArenaPool *arena;
+ char *commonName = NULL;
+ char *dllName = NULL;
+ char *parameters = NULL;
+ char *nss;
+ char *moduleSpec;
+ char **slotStrings = NULL;
+ unsigned char *names;
+ unsigned long slotCount;
+ unsigned long ssl0 = 0;
+ unsigned long ssl1 = 0;
+ unsigned long slotID;
+ unsigned long defaultFlags;
+ unsigned long timeout;
+ unsigned long trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER;
+ unsigned long cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER;
+ unsigned short len;
+ unsigned short namesOffset = 0; /* start of the names block */
+ unsigned long namesRunningOffset; /* offset to name we are
+ * currently processing */
+ unsigned short slotOffset;
+ PRBool isOldVersion = PR_FALSE;
+ PRBool internal;
+ PRBool isFIPS;
+ PRBool isModuleDB = PR_FALSE;
+ PRBool isModuleDBOnly = PR_FALSE;
+ PRBool extended = PR_FALSE;
+ int i;
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ return NULL;
+
+#define CHECK_SIZE(x) \
+ if ((unsigned int)data->size < (unsigned int)(x)) \
+ goto db_loser
+
+ /* -------------------------------------------------------------
+ ** Process the buffer header, which is the lgdbData struct.
+ ** It may be an old or new version. Check the length for each.
+ */
+
+ CHECK_SIZE(offsetof(lgdbData, trustOrder[0]));
+
+ encoded = (lgdbData *)data->data;
+
+ internal = (encoded->internal != 0) ? PR_TRUE : PR_FALSE;
+ isFIPS = (encoded->fips != 0) ? PR_TRUE : PR_FALSE;
+
+ if (retInternal)
+ *retInternal = internal;
+ if (internal) {
+ parameters = PORT_ArenaStrdup(arena, defParams);
+ if (parameters == NULL)
+ goto loser;
+ }
+ if (internal && (encoded->major == LGDB_DB_NOUI_VERSION_MAJOR) &&
+ (encoded->minor <= LGDB_DB_NOUI_VERSION_MINOR)) {
+ isOldVersion = PR_TRUE;
+ }
+ if ((encoded->major == LGDB_DB_EXT1_VERSION_MAJOR) &&
+ (encoded->minor >= LGDB_DB_EXT1_VERSION_MINOR)) {
+ CHECK_SIZE(sizeof(lgdbData));
+ trustOrder = LGDB_GETLONG(encoded->trustOrder);
+ cipherOrder = LGDB_GETLONG(encoded->cipherOrder);
+ isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE : PR_FALSE;
+ isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE : PR_FALSE;
+ extended = PR_TRUE;
+ }
+ if (internal && !extended) {
+ trustOrder = 0;
+ cipherOrder = 100;
+ }
+ /* decode SSL cipher enable flags */
+ ssl0 = LGDB_GETLONG(encoded->ssl);
+ ssl1 = LGDB_GETLONG(encoded->ssl + 4);
+
+ slotOffset = LGDB_GETSHORT(encoded->slotOffset);
+ namesOffset = LGDB_GETSHORT(encoded->nameStart);
+
+ /*--------------------------------------------------------------
+ ** Now process the variable length set of names.
+ ** The names have this structure:
+ ** struct {
+ ** BYTE commonNameLen[ 2 ];
+ ** BYTE commonName [ commonNameLen ];
+ ** BTTE libNameLen [ 2 ];
+ ** BYTE libName [ libNameLen ];
+ ** If it is "extended" it also has these members:
+ ** BYTE initStringLen[ 2 ];
+ ** BYTE initString [ initStringLen ];
+ ** }
+ */
+
+ namesRunningOffset = namesOffset;
+ /* copy the module's common name */
+ CHECK_SIZE(namesRunningOffset + 2);
+ names = (unsigned char *)data->data;
+ len = LGDB_GETSHORT(names + namesRunningOffset);
+
+ CHECK_SIZE(namesRunningOffset + 2 + len);
+ commonName = (char *)PORT_ArenaAlloc(arena, len + 1);
+ if (commonName == NULL)
+ goto loser;
+ PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
+ commonName[len] = 0;
+ namesRunningOffset += len + 2;
+
+ /* copy the module's shared library file name. */
+ CHECK_SIZE(namesRunningOffset + 2);
+ len = LGDB_GETSHORT(names + namesRunningOffset);
+ if (len) {
+ CHECK_SIZE(namesRunningOffset + 2 + len);
+ dllName = (char *)PORT_ArenaAlloc(arena, len + 1);
+ if (dllName == NULL)
+ goto loser;
+ PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
+ dllName[len] = 0;
+ }
+ namesRunningOffset += len + 2;
+
+ /* copy the module's initialization string, if present. */
+ if (!internal && extended) {
+ CHECK_SIZE(namesRunningOffset + 2);
+ len = LGDB_GETSHORT(names + namesRunningOffset);
+ if (len) {
+ CHECK_SIZE(namesRunningOffset + 2 + len);
+ parameters = (char *)PORT_ArenaAlloc(arena, len + 1);
+ if (parameters == NULL)
+ goto loser;
+ PORT_Memcpy(parameters, names + namesRunningOffset + 2, len);
+ parameters[len] = 0;
+ }
+ namesRunningOffset += len + 2;
+ }
+
+ /*
+ * Consistency check: Make sure the slot and names blocks don't
+ * overlap. These blocks can occur in any order, so this check is made
+ * in 2 parts. First we check the case where the slot block starts
+ * after the name block. Later, when we have the slot block length,
+ * we check the case where slot block starts before the name block.
+ * NOTE: in most cases any overlap will likely be detected by invalid
+ * data read from the blocks, but it's better to find out sooner
+ * than later.
+ */
+ if (slotOffset >= namesOffset) { /* slot block starts after name block */
+ if (slotOffset < namesRunningOffset) {
+ goto db_loser;
+ }
+ }
+
+ /* ------------------------------------------------------------------
+ ** Part 3, process the slot table.
+ ** This part has this structure:
+ ** struct {
+ ** BYTE slotCount [ 2 ];
+ ** lgdbSlotData [ slotCount ];
+ ** {
+ */
+
+ CHECK_SIZE(slotOffset + 2);
+ slotCount = LGDB_GETSHORT((unsigned char *)data->data + slotOffset);
+
+ /*
+ * Consistency check: Part 2. We now have the slot block length, we can
+ * check the case where the slotblock procedes the name block.
+ */
+ if (slotOffset < namesOffset) { /* slot block starts before name block */
+ if (namesOffset < slotOffset + 2 + slotCount * sizeof(lgdbSlotData)) {
+ goto db_loser;
+ }
+ }
+
+ CHECK_SIZE((slotOffset + 2 + slotCount * sizeof(lgdbSlotData)));
+ slots = (lgdbSlotData *)((unsigned char *)data->data + slotOffset + 2);
+
+ /* slotCount; */
+ slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
+ if (slotStrings == NULL)
+ goto loser;
+ for (i = 0; i < (int)slotCount; i++, slots++) {
+ PRBool hasRootCerts = PR_FALSE;
+ PRBool hasRootTrust = PR_FALSE;
+ slotID = LGDB_GETLONG(slots->slotID);
+ defaultFlags = LGDB_GETLONG(slots->defaultFlags);
+ timeout = LGDB_GETLONG(slots->timeout);
+ hasRootCerts = slots->hasRootCerts;
+ if (isOldVersion && internal && (slotID != 2)) {
+ unsigned long internalFlags =
+ NSSUTIL_ArgParseSlotFlags("slotFlags",
+ NSSUTIL_DEFAULT_SFTKN_FLAGS);
+ defaultFlags |= internalFlags;
+ }
+ if (hasRootCerts && !extended) {
+ trustOrder = 100;
+ }
+
+ slotStrings[i] = NSSUTIL_MkSlotString(slotID, defaultFlags, timeout,
+ (unsigned char)slots->askpw,
+ hasRootCerts, hasRootTrust);
+ if (slotStrings[i] == NULL) {
+ lgdb_FreeSlotStrings(slotStrings, i);
+ goto loser;
+ }
+ }
+
+ nss = NSSUTIL_MkNSSString(slotStrings, slotCount, internal, isFIPS,
+ isModuleDB, isModuleDBOnly, internal, trustOrder,
+ cipherOrder, ssl0, ssl1);
+ lgdb_FreeSlotStrings(slotStrings, slotCount);
+ /* it's permissible (and normal) for nss to be NULL. it simply means
+ * there are no NSS specific parameters in the database */
+ moduleSpec = NSSUTIL_MkModuleSpec(dllName, commonName, parameters, nss);
+ PR_smprintf_free(nss);
+ PORT_FreeArena(arena, PR_TRUE);
+ return moduleSpec;
+
+db_loser:
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+loser:
+ PORT_FreeArena(arena, PR_TRUE);
+ return NULL;
+}
+
+static DB *
+lgdb_OpenDB(const char *appName, const char *filename, const char *dbName,
+ PRBool readOnly, PRBool update)
+{
+ DB *pkcs11db = NULL;
+
+ if (appName) {
+ char *secname = PORT_Strdup(filename);
+ int len = strlen(secname);
+ int status = RDB_FAIL;
+
+ if (len >= 3 && PORT_Strcmp(&secname[len - 3], ".db") == 0) {
+ secname[len - 3] = 0;
+ }
+ pkcs11db =
+ rdbopen(appName, "", secname, readOnly ? NO_RDONLY : NO_RDWR, NULL);
+ if (update && !pkcs11db) {
+ DB *updatedb;
+
+ pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
+ if (!pkcs11db) {
+ if (status == RDB_RETRY) {
+ pkcs11db = rdbopen(appName, "", secname,
+ readOnly ? NO_RDONLY : NO_RDWR, NULL);
+ }
+ PORT_Free(secname);
+ return pkcs11db;
+ }
+ updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
+ if (updatedb) {
+ db_Copy(pkcs11db, updatedb);
+ (*updatedb->close)(updatedb);
+ } else {
+ (*pkcs11db->close)(pkcs11db);
+ PORT_Free(secname);
+ return NULL;
+ }
+ }
+ PORT_Free(secname);
+ return pkcs11db;
+ }
+
+ /* I'm sure we should do more checks here sometime... */
+ pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
+
+ /* didn't exist? create it */
+ if (pkcs11db == NULL) {
+ if (readOnly)
+ return NULL;
+
+ pkcs11db = dbopen(dbName, NO_CREATE, 0600, DB_HASH, 0);
+ if (pkcs11db)
+ (*pkcs11db->sync)(pkcs11db, 0);
+ }
+ return pkcs11db;
+}
+
+static void
+lgdb_CloseDB(DB *pkcs11db)
+{
+ (*pkcs11db->close)(pkcs11db);
+}
+
+SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *module, PRBool rw);
+
+#define LGDB_STEP 10
+/*
+ * Read all the existing modules in
+ */
+char **
+legacy_ReadSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *params, PRBool rw)
+{
+ DBT key, data;
+ int ret;
+ DB *pkcs11db = NULL;
+ char **moduleList = NULL, **newModuleList = NULL;
+ int moduleCount = 1;
+ int useCount = LGDB_STEP;
+
+ moduleList = (char **)PORT_ZAlloc(useCount * sizeof(char **));
+ if (moduleList == NULL)
+ return NULL;
+
+ pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_TRUE, rw);
+ if (pkcs11db == NULL)
+ goto done;
+
+ /* read and parse the file or data base */
+ ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
+ if (ret)
+ goto done;
+
+ do {
+ char *moduleString;
+ PRBool internal = PR_FALSE;
+ if ((moduleCount + 1) >= useCount) {
+ useCount += LGDB_STEP;
+ newModuleList =
+ (char **)PORT_Realloc(moduleList, useCount * sizeof(char *));
+ if (newModuleList == NULL)
+ goto done;
+ moduleList = newModuleList;
+ PORT_Memset(&moduleList[moduleCount + 1], 0,
+ sizeof(char *) * LGDB_STEP);
+ }
+ moduleString = lgdb_DecodeData(params, &data, &internal);
+ if (internal) {
+ moduleList[0] = moduleString;
+ } else {
+ moduleList[moduleCount] = moduleString;
+ moduleCount++;
+ }
+ } while ((*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
+
+done:
+ if (!moduleList[0]) {
+ char *newparams = NSSUTIL_Quote(params, '"');
+ if (newparams) {
+ moduleList[0] = PR_smprintf(
+ NSSUTIL_DEFAULT_INTERNAL_INIT1 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT2 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT3,
+ newparams, NSSUTIL_DEFAULT_SFTKN_FLAGS);
+ PORT_Free(newparams);
+ }
+ }
+ /* deal with trust cert db here */
+
+ if (pkcs11db) {
+ lgdb_CloseDB(pkcs11db);
+ } else if (moduleList[0] && rw) {
+ legacy_AddSecmodDB(appName, filename, dbname, moduleList[0], rw);
+ }
+ if (!moduleList[0]) {
+ PORT_Free(moduleList);
+ moduleList = NULL;
+ }
+ return moduleList;
+}
+
+SECStatus
+legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
+ const char *dbname, char **moduleSpecList, PRBool rw)
+{
+ if (moduleSpecList) {
+ char **index;
+ for (index = moduleSpecList; *index; index++) {
+ PR_smprintf_free(*index);
+ }
+ PORT_Free(moduleSpecList);
+ }
+ return SECSuccess;
+}
+
+/*
+ * Delete a module from the Data Base
+ */
+SECStatus
+legacy_DeleteSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *args, PRBool rw)
+{
+ DBT key;
+ SECStatus rv = SECFailure;
+ DB *pkcs11db = NULL;
+ int ret;
+
+ if (!rw)
+ return SECFailure;
+
+ /* make sure we have a db handle */
+ pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE);
+ if (pkcs11db == NULL) {
+ return SECFailure;
+ }
+
+ rv = lgdb_MakeKey(&key, args);
+ if (rv != SECSuccess)
+ goto done;
+ rv = SECFailure;
+ ret = (*pkcs11db->del)(pkcs11db, &key, 0);
+ lgdb_FreeKey(&key);
+ if (ret != 0)
+ goto done;
+
+ ret = (*pkcs11db->sync)(pkcs11db, 0);
+ if (ret == 0)
+ rv = SECSuccess;
+
+done:
+ lgdb_CloseDB(pkcs11db);
+ return rv;
+}
+
+/*
+ * Add a module to the Data base
+ */
+SECStatus
+legacy_AddSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *module, PRBool rw)
+{
+ DBT key, data;
+ SECStatus rv = SECFailure;
+ DB *pkcs11db = NULL;
+ int ret;
+
+ if (!rw)
+ return SECFailure;
+
+ /* make sure we have a db handle */
+ pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE);
+ if (pkcs11db == NULL) {
+ return SECFailure;
+ }
+
+ rv = lgdb_MakeKey(&key, module);
+ if (rv != SECSuccess)
+ goto done;
+ rv = lgdb_EncodeData(&data, module);
+ if (rv != SECSuccess) {
+ lgdb_FreeKey(&key);
+ goto done;
+ }
+ rv = SECFailure;
+ ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
+ lgdb_FreeKey(&key);
+ lgdb_FreeData(&data);
+ if (ret != 0)
+ goto done;
+
+ ret = (*pkcs11db->sync)(pkcs11db, 0);
+ if (ret == 0)
+ rv = SECSuccess;
+
+done:
+ lgdb_CloseDB(pkcs11db);
+ return rv;
+}