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