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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/softoken/legacydb/pk11db.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,717 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/* 
     1.8 + *  The following code handles the storage of PKCS 11 modules used by the
     1.9 + * NSS. This file is written to abstract away how the modules are
    1.10 + * stored so we can deside that later.
    1.11 + */
    1.12 +
    1.13 +#include "lgdb.h"
    1.14 +#include "mcom_db.h"
    1.15 +#include "secerr.h"
    1.16 +#include "utilpars.h"
    1.17 +
    1.18 +#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
    1.19 +
    1.20 +/* Construct a database key for a given module */
    1.21 +static SECStatus lgdb_MakeKey(DBT *key, char * module) {
    1.22 +    int len = 0;
    1.23 +    char *commonName;
    1.24 +
    1.25 +    commonName = NSSUTIL_ArgGetParamValue("name",module);
    1.26 +    if (commonName == NULL) {
    1.27 +	commonName = NSSUTIL_ArgGetParamValue("library",module);
    1.28 +    }
    1.29 +    if (commonName == NULL) return SECFailure;
    1.30 +    len = PORT_Strlen(commonName);
    1.31 +    key->data = commonName;
    1.32 +    key->size = len;
    1.33 +    return SECSuccess;
    1.34 +}
    1.35 +
    1.36 +/* free out constructed database key */
    1.37 +static void 
    1.38 +lgdb_FreeKey(DBT *key) 
    1.39 +{
    1.40 +    if (key->data) {
    1.41 +	PORT_Free(key->data);
    1.42 +    }
    1.43 +    key->data = NULL;
    1.44 +    key->size = 0;
    1.45 +}
    1.46 +
    1.47 +typedef struct lgdbDataStr lgdbData;
    1.48 +typedef struct lgdbSlotDataStr lgdbSlotData;
    1.49 +struct lgdbDataStr {
    1.50 +    unsigned char major;
    1.51 +    unsigned char minor;
    1.52 +    unsigned char nameStart[2];
    1.53 +    unsigned char slotOffset[2];
    1.54 +    unsigned char internal;
    1.55 +    unsigned char fips;
    1.56 +    unsigned char ssl[8];
    1.57 +    unsigned char trustOrder[4];
    1.58 +    unsigned char cipherOrder[4];
    1.59 +    unsigned char reserved1;
    1.60 +    unsigned char isModuleDB;
    1.61 +    unsigned char isModuleDBOnly;
    1.62 +    unsigned char isCritical;
    1.63 +    unsigned char reserved[4];
    1.64 +    unsigned char names[6];	/* enough space for the length fields */
    1.65 +};
    1.66 +
    1.67 +struct lgdbSlotDataStr {
    1.68 +    unsigned char slotID[4];
    1.69 +    unsigned char defaultFlags[4];
    1.70 +    unsigned char timeout[4];
    1.71 +    unsigned char askpw;
    1.72 +    unsigned char hasRootCerts;
    1.73 +    unsigned char reserved[18]; /* this makes it a round 32 bytes */
    1.74 +};
    1.75 +
    1.76 +#define LGDB_DB_VERSION_MAJOR 0
    1.77 +#define LGDB_DB_VERSION_MINOR 6
    1.78 +#define LGDB_DB_EXT1_VERSION_MAJOR 0
    1.79 +#define LGDB_DB_EXT1_VERSION_MINOR 6
    1.80 +#define LGDB_DB_NOUI_VERSION_MAJOR 0
    1.81 +#define LGDB_DB_NOUI_VERSION_MINOR 4
    1.82 +
    1.83 +#define LGDB_PUTSHORT(dest,src) \
    1.84 +	(dest)[1] = (unsigned char) ((src)&0xff); \
    1.85 +	(dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
    1.86 +#define LGDB_PUTLONG(dest,src) \
    1.87 +	(dest)[3] = (unsigned char) ((src)&0xff); \
    1.88 +	(dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
    1.89 +	(dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
    1.90 +	(dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
    1.91 +#define LGDB_GETSHORT(src) \
    1.92 +	((unsigned short) (((src)[0] << 8) | (src)[1]))
    1.93 +#define LGDB_GETLONG(src) \
    1.94 +	((unsigned long) (( (unsigned long) (src)[0] << 24) | \
    1.95 +			( (unsigned long) (src)[1] << 16)  | \
    1.96 +			( (unsigned long) (src)[2] << 8) | \
    1.97 +			(unsigned long) (src)[3]))
    1.98 +
    1.99 +/*
   1.100 + * build a data base entry from a module 
   1.101 + */
   1.102 +static SECStatus 
   1.103 +lgdb_EncodeData(DBT *data, char * module) 
   1.104 +{
   1.105 +    lgdbData *encoded = NULL;
   1.106 +    lgdbSlotData *slot;
   1.107 +    unsigned char *dataPtr;
   1.108 +    unsigned short len, len2 = 0, len3 = 0;
   1.109 +    int count = 0;
   1.110 +    unsigned short offset;
   1.111 +    int dataLen, i;
   1.112 +    unsigned long order;
   1.113 +    unsigned long  ssl[2];
   1.114 +    char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
   1.115 +    char *slotParams, *ciphers;
   1.116 +    struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
   1.117 +    SECStatus rv = SECFailure;
   1.118 +
   1.119 +    rv = NSSUTIL_ArgParseModuleSpec(module,&dllName,&commonName,&param,&nss);
   1.120 +    if (rv != SECSuccess) return rv;
   1.121 +    rv = SECFailure;
   1.122 +
   1.123 +    if (commonName == NULL) {
   1.124 +	/* set error */
   1.125 +	goto loser;
   1.126 +    }
   1.127 +
   1.128 +    len = PORT_Strlen(commonName);
   1.129 +    if (dllName) {
   1.130 +    	len2 = PORT_Strlen(dllName);
   1.131 +    }
   1.132 +    if (param) {
   1.133 +	len3 = PORT_Strlen(param);
   1.134 +    }
   1.135 +
   1.136 +    slotParams = NSSUTIL_ArgGetParamValue("slotParams",nss); 
   1.137 +    slotInfo = NSSUTIL_ArgParseSlotInfo(NULL,slotParams,&count);
   1.138 +    if (slotParams) PORT_Free(slotParams);
   1.139 +
   1.140 +    if (count && slotInfo == NULL) {
   1.141 +	/* set error */
   1.142 +	goto loser;
   1.143 +    }
   1.144 +
   1.145 +    dataLen = sizeof(lgdbData) + len + len2 + len3 + sizeof(unsigned short) +
   1.146 +				 count*sizeof(lgdbSlotData);
   1.147 +
   1.148 +    data->data = (unsigned char *) PORT_ZAlloc(dataLen);
   1.149 +    encoded = (lgdbData *)data->data;
   1.150 +    dataPtr = (unsigned char *) data->data;
   1.151 +    data->size = dataLen;
   1.152 +
   1.153 +    if (encoded == NULL) {
   1.154 +	/* set error */
   1.155 +	goto loser;
   1.156 +    }
   1.157 +
   1.158 +    encoded->major = LGDB_DB_VERSION_MAJOR;
   1.159 +    encoded->minor = LGDB_DB_VERSION_MINOR;
   1.160 +    encoded->internal = (unsigned char) 
   1.161 +			(NSSUTIL_ArgHasFlag("flags","internal",nss) ? 1 : 0);
   1.162 +    encoded->fips = (unsigned char) 
   1.163 +			(NSSUTIL_ArgHasFlag("flags","FIPS",nss) ? 1 : 0);
   1.164 +    encoded->isModuleDB = (unsigned char) 
   1.165 +			(NSSUTIL_ArgHasFlag("flags","isModuleDB",nss) ? 1 : 0);
   1.166 +    encoded->isModuleDBOnly = (unsigned char) 
   1.167 +		    (NSSUTIL_ArgHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
   1.168 +    encoded->isCritical = (unsigned char) 
   1.169 +			(NSSUTIL_ArgHasFlag("flags","critical",nss) ? 1 : 0);
   1.170 +
   1.171 +    order = NSSUTIL_ArgReadLong("trustOrder", nss,
   1.172 +				 NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
   1.173 +    LGDB_PUTLONG(encoded->trustOrder,order);
   1.174 +    order = NSSUTIL_ArgReadLong("cipherOrder", nss, 
   1.175 +				NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
   1.176 +    LGDB_PUTLONG(encoded->cipherOrder,order);
   1.177 +
   1.178 +   
   1.179 +    ciphers = NSSUTIL_ArgGetParamValue("ciphers",nss); 
   1.180 +    NSSUTIL_ArgParseCipherFlags(&ssl[0], ciphers);
   1.181 +    LGDB_PUTLONG(encoded->ssl,ssl[0]);
   1.182 +    LGDB_PUTLONG(&encoded->ssl[4],ssl[1]);
   1.183 +    if (ciphers) PORT_Free(ciphers);
   1.184 +
   1.185 +    offset = (unsigned short) offsetof(lgdbData, names);
   1.186 +    LGDB_PUTSHORT(encoded->nameStart,offset);
   1.187 +    offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
   1.188 +    LGDB_PUTSHORT(encoded->slotOffset,offset);
   1.189 +
   1.190 +
   1.191 +    LGDB_PUTSHORT(&dataPtr[offset],((unsigned short)count));
   1.192 +    slot = (lgdbSlotData *)(dataPtr+offset+sizeof(unsigned short));
   1.193 +
   1.194 +    offset = 0;
   1.195 +    LGDB_PUTSHORT(encoded->names,len);
   1.196 +    offset += sizeof(unsigned short);
   1.197 +    PORT_Memcpy(&encoded->names[offset],commonName,len);
   1.198 +    offset += len;
   1.199 +
   1.200 +
   1.201 +    LGDB_PUTSHORT(&encoded->names[offset],len2);
   1.202 +    offset += sizeof(unsigned short);
   1.203 +    if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
   1.204 +    offset += len2;
   1.205 +
   1.206 +    LGDB_PUTSHORT(&encoded->names[offset],len3);
   1.207 +    offset += sizeof(unsigned short);
   1.208 +    if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
   1.209 +    offset += len3;
   1.210 +
   1.211 +    if (count) {
   1.212 +	for (i=0; i < count; i++) {
   1.213 +	    LGDB_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
   1.214 +	    LGDB_PUTLONG(slot[i].defaultFlags,
   1.215 +					slotInfo[i].defaultFlags);
   1.216 +	    LGDB_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
   1.217 +	    slot[i].askpw = slotInfo[i].askpw;
   1.218 +	    slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
   1.219 +	    PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
   1.220 +	}
   1.221 +    }
   1.222 +    rv = SECSuccess;
   1.223 +
   1.224 +loser:
   1.225 +    if (commonName) PORT_Free(commonName);
   1.226 +    if (dllName) PORT_Free(dllName);
   1.227 +    if (param) PORT_Free(param);
   1.228 +    if (slotInfo) PORT_Free(slotInfo);
   1.229 +    if (nss) PORT_Free(nss);
   1.230 +    return rv;
   1.231 +
   1.232 +}
   1.233 +
   1.234 +static void 
   1.235 +lgdb_FreeData(DBT *data)
   1.236 +{
   1.237 +    if (data->data) {
   1.238 +	PORT_Free(data->data);
   1.239 +    }
   1.240 +}
   1.241 +
   1.242 +static void
   1.243 +lgdb_FreeSlotStrings(char **slotStrings, int count)
   1.244 +{
   1.245 +    int i;
   1.246 +
   1.247 +    for (i=0; i < count; i++) {
   1.248 +	if (slotStrings[i]) {
   1.249 +	    PR_smprintf_free(slotStrings[i]);
   1.250 +	    slotStrings[i] = NULL;
   1.251 +	}
   1.252 +    }
   1.253 +}
   1.254 +
   1.255 +/*
   1.256 + * build a module from the data base entry.
   1.257 + */
   1.258 +static char *
   1.259 +lgdb_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
   1.260 +{
   1.261 +    lgdbData *encoded;
   1.262 +    lgdbSlotData *slots;
   1.263 +    PLArenaPool *arena;
   1.264 +    char *commonName 		= NULL;
   1.265 +    char *dllName    		= NULL;
   1.266 +    char *parameters 		= NULL;
   1.267 +    char *nss;
   1.268 +    char *moduleSpec;
   1.269 +    char **slotStrings 		= NULL;
   1.270 +    unsigned char *names;
   1.271 +    unsigned long slotCount;
   1.272 +    unsigned long ssl0		=0;
   1.273 +    unsigned long ssl1		=0;
   1.274 +    unsigned long slotID;
   1.275 +    unsigned long defaultFlags;
   1.276 +    unsigned long timeout;
   1.277 +    unsigned long trustOrder	= NSSUTIL_DEFAULT_TRUST_ORDER;
   1.278 +    unsigned long cipherOrder	= NSSUTIL_DEFAULT_CIPHER_ORDER;
   1.279 +    unsigned short len;
   1.280 +    unsigned short namesOffset  = 0;	/* start of the names block */
   1.281 +    unsigned long namesRunningOffset;	/* offset to name we are 
   1.282 +					 * currently processing */
   1.283 +    unsigned short slotOffset;
   1.284 +    PRBool isOldVersion  	= PR_FALSE;
   1.285 +    PRBool internal;
   1.286 +    PRBool isFIPS;
   1.287 +    PRBool isModuleDB    	=PR_FALSE;
   1.288 +    PRBool isModuleDBOnly	=PR_FALSE;
   1.289 +    PRBool extended      	=PR_FALSE;
   1.290 +    int i;
   1.291 +
   1.292 +
   1.293 +    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.294 +    if (arena == NULL) 
   1.295 +    	return NULL;
   1.296 +
   1.297 +#define CHECK_SIZE(x) \
   1.298 +    if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
   1.299 +
   1.300 +    /* -------------------------------------------------------------
   1.301 +    ** Process the buffer header, which is the lgdbData struct. 
   1.302 +    ** It may be an old or new version.  Check the length for each. 
   1.303 +    */
   1.304 +
   1.305 +    CHECK_SIZE( offsetof(lgdbData, trustOrder[0]) );
   1.306 +
   1.307 +    encoded = (lgdbData *)data->data;
   1.308 +
   1.309 +    internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
   1.310 +    isFIPS   = (encoded->fips     != 0) ? PR_TRUE: PR_FALSE;
   1.311 +
   1.312 +    if (retInternal)
   1.313 +	*retInternal = internal;
   1.314 +    if (internal) {
   1.315 +	parameters = PORT_ArenaStrdup(arena,defParams);
   1.316 +	if (parameters == NULL) 
   1.317 +	    goto loser;
   1.318 +    }
   1.319 +    if (internal && (encoded->major == LGDB_DB_NOUI_VERSION_MAJOR) &&
   1.320 + 	(encoded->minor <= LGDB_DB_NOUI_VERSION_MINOR)) {
   1.321 +	isOldVersion = PR_TRUE;
   1.322 +    }
   1.323 +    if ((encoded->major == LGDB_DB_EXT1_VERSION_MAJOR) &&
   1.324 +	(encoded->minor >= LGDB_DB_EXT1_VERSION_MINOR)) {
   1.325 +	CHECK_SIZE( sizeof(lgdbData));
   1.326 +	trustOrder     = LGDB_GETLONG(encoded->trustOrder);
   1.327 +	cipherOrder    = LGDB_GETLONG(encoded->cipherOrder);
   1.328 +	isModuleDB     = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
   1.329 +	isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
   1.330 +	extended       = PR_TRUE;
   1.331 +    } 
   1.332 +    if (internal && !extended) {
   1.333 +	trustOrder = 0;
   1.334 +	cipherOrder = 100;
   1.335 +    }
   1.336 +    /* decode SSL cipher enable flags */
   1.337 +    ssl0 = LGDB_GETLONG(encoded->ssl);
   1.338 +    ssl1 = LGDB_GETLONG(encoded->ssl + 4);
   1.339 +
   1.340 +    slotOffset  = LGDB_GETSHORT(encoded->slotOffset);
   1.341 +    namesOffset = LGDB_GETSHORT(encoded->nameStart);
   1.342 +
   1.343 +
   1.344 +    /*--------------------------------------------------------------
   1.345 +    ** Now process the variable length set of names.                
   1.346 +    ** The names have this structure:
   1.347 +    ** struct {
   1.348 +    **     BYTE  commonNameLen[ 2 ];
   1.349 +    **     BYTE  commonName   [ commonNameLen ];
   1.350 +    **     BTTE  libNameLen   [ 2 ];
   1.351 +    **     BYTE  libName      [ libNameLen ];
   1.352 +    ** If it is "extended" it also has these members:
   1.353 +    **     BYTE  initStringLen[ 2 ];
   1.354 +    **     BYTE  initString   [ initStringLen ];
   1.355 +    ** }
   1.356 +    */
   1.357 +
   1.358 +    namesRunningOffset = namesOffset;
   1.359 +    /* copy the module's common name */
   1.360 +    CHECK_SIZE( namesRunningOffset + 2);
   1.361 +    names = (unsigned char *)data->data;
   1.362 +    len   = LGDB_GETSHORT(names+namesRunningOffset);
   1.363 +
   1.364 +    CHECK_SIZE( namesRunningOffset + 2 + len);
   1.365 +    commonName = (char*)PORT_ArenaAlloc(arena,len+1);
   1.366 +    if (commonName == NULL) 
   1.367 +	goto loser;
   1.368 +    PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
   1.369 +    commonName[len] = 0;
   1.370 +    namesRunningOffset += len + 2;
   1.371 +
   1.372 +    /* copy the module's shared library file name. */
   1.373 +    CHECK_SIZE( namesRunningOffset + 2);
   1.374 +    len = LGDB_GETSHORT(names + namesRunningOffset);
   1.375 +    if (len) {
   1.376 +	CHECK_SIZE( namesRunningOffset + 2 + len);
   1.377 +	dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
   1.378 +	if (dllName == NULL) 
   1.379 +	    goto loser;
   1.380 +	PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
   1.381 +	dllName[len] = 0;
   1.382 +    }
   1.383 +    namesRunningOffset += len + 2;
   1.384 +
   1.385 +    /* copy the module's initialization string, if present. */
   1.386 +    if (!internal && extended) {
   1.387 +	CHECK_SIZE( namesRunningOffset + 2);
   1.388 +	len = LGDB_GETSHORT(names+namesRunningOffset);
   1.389 +	if (len) {
   1.390 +	    CHECK_SIZE( namesRunningOffset + 2 + len );
   1.391 +	    parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
   1.392 +	    if (parameters == NULL) 
   1.393 +		goto loser;
   1.394 +	    PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
   1.395 +	    parameters[len] = 0;
   1.396 +	}
   1.397 +	namesRunningOffset += len + 2;
   1.398 +    }
   1.399 +
   1.400 +    /* 
   1.401 +     * Consistency check: Make sure the slot and names blocks don't
   1.402 +     * overlap. These blocks can occur in any order, so this check is made 
   1.403 +     * in 2 parts. First we check the case where the slot block starts 
   1.404 +     * after the name block. Later, when we have the slot block length,
   1.405 +     * we check the case where slot block starts before the name block.
   1.406 +     * NOTE: in most cases any overlap will likely be detected by invalid 
   1.407 +     * data read from the blocks, but it's better to find out sooner 
   1.408 +     * than later.
   1.409 +     */
   1.410 +    if (slotOffset >= namesOffset) { /* slot block starts after name block */
   1.411 +	if (slotOffset < namesRunningOffset) {
   1.412 +	    goto db_loser;
   1.413 +	}
   1.414 +    }
   1.415 +
   1.416 +    /* ------------------------------------------------------------------
   1.417 +    ** Part 3, process the slot table.
   1.418 +    ** This part has this structure:
   1.419 +    ** struct {
   1.420 +    **     BYTE slotCount [ 2 ];
   1.421 +    **     lgdbSlotData [ slotCount ];
   1.422 +    ** {
   1.423 +    */
   1.424 +
   1.425 +    CHECK_SIZE( slotOffset + 2 );
   1.426 +    slotCount = LGDB_GETSHORT((unsigned char *)data->data + slotOffset);
   1.427 +
   1.428 +    /* 
   1.429 +     * Consistency check: Part 2. We now have the slot block length, we can 
   1.430 +     * check the case where the slotblock procedes the name block.
   1.431 +     */
   1.432 +    if (slotOffset < namesOffset) { /* slot block starts before name block */
   1.433 +	if (namesOffset < slotOffset + 2 + slotCount*sizeof(lgdbSlotData)) {
   1.434 +	    goto db_loser;
   1.435 +	}
   1.436 +    }
   1.437 +
   1.438 +    CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(lgdbSlotData)));
   1.439 +    slots = (lgdbSlotData *) ((unsigned char *)data->data + slotOffset + 2);
   1.440 +
   1.441 +    /*  slotCount; */
   1.442 +    slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
   1.443 +    if (slotStrings == NULL)
   1.444 +	goto loser;
   1.445 +    for (i=0; i < (int) slotCount; i++, slots++) {
   1.446 +	PRBool hasRootCerts	=PR_FALSE;
   1.447 +	PRBool hasRootTrust	=PR_FALSE;
   1.448 +	slotID       = LGDB_GETLONG(slots->slotID);
   1.449 +	defaultFlags = LGDB_GETLONG(slots->defaultFlags);
   1.450 +	timeout      = LGDB_GETLONG(slots->timeout);
   1.451 +	hasRootCerts = slots->hasRootCerts;
   1.452 +	if (isOldVersion && internal && (slotID != 2)) {
   1.453 +	    unsigned long internalFlags=
   1.454 +	         NSSUTIL_ArgParseSlotFlags("slotFlags", 
   1.455 +					NSSUTIL_DEFAULT_SFTKN_FLAGS);
   1.456 +	    defaultFlags |= internalFlags;
   1.457 +	}
   1.458 +	if (hasRootCerts && !extended) {
   1.459 +	    trustOrder = 100;
   1.460 +	}
   1.461 +
   1.462 +	slotStrings[i] = NSSUTIL_MkSlotString(slotID, defaultFlags, timeout, 
   1.463 +	                                   (unsigned char)slots->askpw, 
   1.464 +	                                   hasRootCerts, hasRootTrust);
   1.465 +	if (slotStrings[i] == NULL) {
   1.466 +	    lgdb_FreeSlotStrings(slotStrings,i);
   1.467 +	    goto loser;
   1.468 +	}
   1.469 +    }
   1.470 +
   1.471 +    nss = NSSUTIL_MkNSSString(slotStrings, slotCount, internal, isFIPS, 
   1.472 +		     isModuleDB, isModuleDBOnly, internal, trustOrder, 
   1.473 +		     cipherOrder, ssl0, ssl1);
   1.474 +    lgdb_FreeSlotStrings(slotStrings,slotCount);
   1.475 +    /* it's permissible (and normal) for nss to be NULL. it simply means
   1.476 +     * there are no NSS specific parameters in the database */
   1.477 +    moduleSpec = NSSUTIL_MkModuleSpec(dllName,commonName,parameters,nss);
   1.478 +    PR_smprintf_free(nss);
   1.479 +    PORT_FreeArena(arena,PR_TRUE);
   1.480 +    return moduleSpec;
   1.481 +
   1.482 +db_loser:
   1.483 +    PORT_SetError(SEC_ERROR_BAD_DATABASE);
   1.484 +loser:
   1.485 +    PORT_FreeArena(arena,PR_TRUE);
   1.486 +    return NULL;
   1.487 +}
   1.488 +
   1.489 +static DB *
   1.490 +lgdb_OpenDB(const char *appName, const char *filename, const char *dbName, 
   1.491 +				PRBool readOnly, PRBool update)
   1.492 +{
   1.493 +    DB *pkcs11db = NULL;
   1.494 +
   1.495 +
   1.496 +    if (appName) {
   1.497 +	char *secname = PORT_Strdup(filename);
   1.498 +	int len = strlen(secname);
   1.499 +	int status = RDB_FAIL;
   1.500 +
   1.501 +	if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
   1.502 +	   secname[len-3] = 0;
   1.503 +	}
   1.504 +    	pkcs11db=
   1.505 +	   rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
   1.506 +	if (update && !pkcs11db) {
   1.507 +	    DB *updatedb;
   1.508 +
   1.509 +    	    pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
   1.510 +	    if (!pkcs11db) {
   1.511 +		if (status == RDB_RETRY) {
   1.512 + 		    pkcs11db= rdbopen(appName, "", secname, 
   1.513 +					readOnly ? NO_RDONLY:NO_RDWR, NULL);
   1.514 +		}
   1.515 +		PORT_Free(secname);
   1.516 +		return pkcs11db;
   1.517 +	    }
   1.518 +	    updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
   1.519 +	    if (updatedb) {
   1.520 +		db_Copy(pkcs11db,updatedb);
   1.521 +		(*updatedb->close)(updatedb);
   1.522 +	    } else {
   1.523 +		(*pkcs11db->close)(pkcs11db);
   1.524 +		PORT_Free(secname);
   1.525 +		return NULL;
   1.526 +	   }
   1.527 +	}
   1.528 +	PORT_Free(secname);
   1.529 +	return pkcs11db;
   1.530 +    }
   1.531 +  
   1.532 +    /* I'm sure we should do more checks here sometime... */
   1.533 +    pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
   1.534 +
   1.535 +    /* didn't exist? create it */
   1.536 +    if (pkcs11db == NULL) {
   1.537 +	 if (readOnly) 
   1.538 +	     return NULL;
   1.539 +
   1.540 +	 pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
   1.541 +	 if (pkcs11db) 
   1.542 +	     (* pkcs11db->sync)(pkcs11db, 0);
   1.543 +    }
   1.544 +    return pkcs11db;
   1.545 +}
   1.546 +
   1.547 +static void 
   1.548 +lgdb_CloseDB(DB *pkcs11db) 
   1.549 +{
   1.550 +     (*pkcs11db->close)(pkcs11db);
   1.551 +}
   1.552 +
   1.553 +
   1.554 +SECStatus legacy_AddSecmodDB(const char *appName, const char *filename, 
   1.555 +			const char *dbname, char *module, PRBool rw);
   1.556 +
   1.557 +#define LGDB_STEP 10
   1.558 +/*
   1.559 + * Read all the existing modules in
   1.560 + */
   1.561 +char **
   1.562 +legacy_ReadSecmodDB(const char *appName, const char *filename,
   1.563 +				const char *dbname, char *params, PRBool rw)
   1.564 +{
   1.565 +    DBT key,data;
   1.566 +    int ret;
   1.567 +    DB *pkcs11db = NULL;
   1.568 +    char **moduleList = NULL, **newModuleList = NULL;
   1.569 +    int moduleCount = 1;
   1.570 +    int useCount = LGDB_STEP;
   1.571 +
   1.572 +    moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
   1.573 +    if (moduleList == NULL) return NULL;
   1.574 +
   1.575 +    pkcs11db = lgdb_OpenDB(appName,filename,dbname,PR_TRUE,rw);
   1.576 +    if (pkcs11db == NULL) goto done;
   1.577 +
   1.578 +    /* read and parse the file or data base */
   1.579 +    ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
   1.580 +    if (ret)  goto done;
   1.581 +
   1.582 +
   1.583 +    do {
   1.584 +	char *moduleString;
   1.585 +	PRBool internal = PR_FALSE;
   1.586 +	if ((moduleCount+1) >= useCount) {
   1.587 +	    useCount += LGDB_STEP;
   1.588 +	    newModuleList =
   1.589 +		(char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
   1.590 +	    if (newModuleList == NULL) goto done;
   1.591 +	    moduleList = newModuleList;
   1.592 +	    PORT_Memset(&moduleList[moduleCount+1],0,
   1.593 +						sizeof(char *)*LGDB_STEP);
   1.594 +	}
   1.595 +	moduleString = lgdb_DecodeData(params,&data,&internal);
   1.596 +	if (internal) {
   1.597 +	    moduleList[0] = moduleString;
   1.598 +	} else {
   1.599 +	    moduleList[moduleCount] = moduleString;
   1.600 +	    moduleCount++;
   1.601 +	}
   1.602 +    } while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
   1.603 +
   1.604 +done:
   1.605 +    if (!moduleList[0]) {
   1.606 +	char * newparams = NSSUTIL_Quote(params,'"');
   1.607 +	if (newparams) {
   1.608 +	    moduleList[0] = PR_smprintf(
   1.609 +		NSSUTIL_DEFAULT_INTERNAL_INIT1 "%s" 
   1.610 +		NSSUTIL_DEFAULT_INTERNAL_INIT2 "%s"
   1.611 +		NSSUTIL_DEFAULT_INTERNAL_INIT3,
   1.612 +		newparams, NSSUTIL_DEFAULT_SFTKN_FLAGS);
   1.613 +	    PORT_Free(newparams);
   1.614 +	}
   1.615 +    }
   1.616 +    /* deal with trust cert db here */
   1.617 +
   1.618 +    if (pkcs11db) {
   1.619 +	lgdb_CloseDB(pkcs11db);
   1.620 +    } else if (moduleList[0] && rw) {
   1.621 +	legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
   1.622 +    }
   1.623 +    if (!moduleList[0]) {
   1.624 +	PORT_Free(moduleList);
   1.625 +	moduleList = NULL;
   1.626 +    }
   1.627 +    return moduleList;
   1.628 +}
   1.629 +
   1.630 +SECStatus
   1.631 +legacy_ReleaseSecmodDBData(const char *appName, const char *filename, 
   1.632 +			const char *dbname, char **moduleSpecList, PRBool rw)
   1.633 +{
   1.634 +    if (moduleSpecList) {
   1.635 +	char **index;
   1.636 +	for(index = moduleSpecList; *index; index++) {
   1.637 +	    PR_smprintf_free(*index);
   1.638 +	}
   1.639 +	PORT_Free(moduleSpecList);
   1.640 +    }
   1.641 +    return SECSuccess;
   1.642 +}
   1.643 +
   1.644 +/*
   1.645 + * Delete a module from the Data Base
   1.646 + */
   1.647 +SECStatus
   1.648 +legacy_DeleteSecmodDB(const char *appName, const char *filename, 
   1.649 +			const char *dbname, char *args, PRBool rw)
   1.650 +{
   1.651 +    DBT key;
   1.652 +    SECStatus rv = SECFailure;
   1.653 +    DB *pkcs11db = NULL;
   1.654 +    int ret;
   1.655 +
   1.656 +    if (!rw) return SECFailure;
   1.657 +
   1.658 +    /* make sure we have a db handle */
   1.659 +    pkcs11db = lgdb_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
   1.660 +    if (pkcs11db == NULL) {
   1.661 +	return SECFailure;
   1.662 +    }
   1.663 +
   1.664 +    rv = lgdb_MakeKey(&key,args);
   1.665 +    if (rv != SECSuccess) goto done;
   1.666 +    rv = SECFailure;
   1.667 +    ret = (*pkcs11db->del)(pkcs11db, &key, 0);
   1.668 +    lgdb_FreeKey(&key);
   1.669 +    if (ret != 0) goto done;
   1.670 +
   1.671 +
   1.672 +    ret = (*pkcs11db->sync)(pkcs11db, 0);
   1.673 +    if (ret == 0) rv = SECSuccess;
   1.674 +
   1.675 +done:
   1.676 +    lgdb_CloseDB(pkcs11db);
   1.677 +    return rv;
   1.678 +}
   1.679 +
   1.680 +/*
   1.681 + * Add a module to the Data base 
   1.682 + */
   1.683 +SECStatus
   1.684 +legacy_AddSecmodDB(const char *appName, const char *filename, 
   1.685 +			const char *dbname, char *module, PRBool rw)
   1.686 +{
   1.687 +    DBT key,data;
   1.688 +    SECStatus rv = SECFailure;
   1.689 +    DB *pkcs11db = NULL;
   1.690 +    int ret;
   1.691 +
   1.692 +
   1.693 +    if (!rw) return SECFailure;
   1.694 +
   1.695 +    /* make sure we have a db handle */
   1.696 +    pkcs11db = lgdb_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
   1.697 +    if (pkcs11db == NULL) {
   1.698 +	return SECFailure;
   1.699 +    }
   1.700 +
   1.701 +    rv = lgdb_MakeKey(&key,module);
   1.702 +    if (rv != SECSuccess) goto done;
   1.703 +    rv = lgdb_EncodeData(&data,module);
   1.704 +    if (rv != SECSuccess) {
   1.705 +	lgdb_FreeKey(&key);
   1.706 +	goto done;
   1.707 +    }
   1.708 +    rv = SECFailure;
   1.709 +    ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
   1.710 +    lgdb_FreeKey(&key);
   1.711 +    lgdb_FreeData(&data);
   1.712 +    if (ret != 0) goto done;
   1.713 +
   1.714 +    ret = (*pkcs11db->sync)(pkcs11db, 0);
   1.715 +    if (ret == 0) rv = SECSuccess;
   1.716 +
   1.717 +done:
   1.718 +    lgdb_CloseDB(pkcs11db);
   1.719 +    return rv;
   1.720 +}

mercurial