Blame nss/lib/softoken/legacydb/pk11db.c

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