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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial