Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / softoken / legacydb / pk11db.c
blobf85a0a6c34a911abcbe7155d1169fea13d963f75
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
36 /*
37 * The following code handles the storage of PKCS 11 modules used by the
38 * NSS. This file is written to abstract away how the modules are
39 * stored so we can deside that later.
42 #include "pk11pars.h"
43 #include "lgdb.h"
44 #include "mcom_db.h"
45 #include "secerr.h"
47 #define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
49 /* Construct a database key for a given module */
50 static SECStatus secmod_MakeKey(DBT *key, char * module) {
51 int len = 0;
52 char *commonName;
54 commonName = secmod_argGetParamValue("name",module);
55 if (commonName == NULL) {
56 commonName = secmod_argGetParamValue("library",module);
58 if (commonName == NULL) return SECFailure;
59 len = PORT_Strlen(commonName);
60 key->data = commonName;
61 key->size = len;
62 return SECSuccess;
65 /* free out constructed database key */
66 static void
67 secmod_FreeKey(DBT *key)
69 if (key->data) {
70 PORT_Free(key->data);
72 key->data = NULL;
73 key->size = 0;
76 typedef struct secmodDataStr secmodData;
77 typedef struct secmodSlotDataStr secmodSlotData;
78 struct secmodDataStr {
79 unsigned char major;
80 unsigned char minor;
81 unsigned char nameStart[2];
82 unsigned char slotOffset[2];
83 unsigned char internal;
84 unsigned char fips;
85 unsigned char ssl[8];
86 unsigned char trustOrder[4];
87 unsigned char cipherOrder[4];
88 unsigned char reserved1;
89 unsigned char isModuleDB;
90 unsigned char isModuleDBOnly;
91 unsigned char isCritical;
92 unsigned char reserved[4];
93 unsigned char names[6]; /* enough space for the length fields */
96 struct secmodSlotDataStr {
97 unsigned char slotID[4];
98 unsigned char defaultFlags[4];
99 unsigned char timeout[4];
100 unsigned char askpw;
101 unsigned char hasRootCerts;
102 unsigned char reserved[18]; /* this makes it a round 32 bytes */
105 #define SECMOD_DB_VERSION_MAJOR 0
106 #define SECMOD_DB_VERSION_MINOR 6
107 #define SECMOD_DB_EXT1_VERSION_MAJOR 0
108 #define SECMOD_DB_EXT1_VERSION_MINOR 6
109 #define SECMOD_DB_NOUI_VERSION_MAJOR 0
110 #define SECMOD_DB_NOUI_VERSION_MINOR 4
112 #define SECMOD_PUTSHORT(dest,src) \
113 (dest)[1] = (unsigned char) ((src)&0xff); \
114 (dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
115 #define SECMOD_PUTLONG(dest,src) \
116 (dest)[3] = (unsigned char) ((src)&0xff); \
117 (dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
118 (dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
119 (dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
120 #define SECMOD_GETSHORT(src) \
121 ((unsigned short) (((src)[0] << 8) | (src)[1]))
122 #define SECMOD_GETLONG(src) \
123 ((unsigned long) (( (unsigned long) (src)[0] << 24) | \
124 ( (unsigned long) (src)[1] << 16) | \
125 ( (unsigned long) (src)[2] << 8) | \
126 (unsigned long) (src)[3]))
129 * build a data base entry from a module
131 static SECStatus
132 secmod_EncodeData(DBT *data, char * module)
134 secmodData *encoded = NULL;
135 secmodSlotData *slot;
136 unsigned char *dataPtr;
137 unsigned short len, len2 = 0, len3 = 0;
138 int count = 0;
139 unsigned short offset;
140 int dataLen, i;
141 unsigned long order;
142 unsigned long ssl[2];
143 char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
144 char *slotParams, *ciphers;
145 PK11PreSlotInfo *slotInfo = NULL;
146 SECStatus rv = SECFailure;
148 rv = secmod_argParseModuleSpec(module,&dllName,&commonName,&param,&nss);
149 if (rv != SECSuccess) return rv;
150 rv = SECFailure;
152 if (commonName == NULL) {
153 /* set error */
154 goto loser;
157 len = PORT_Strlen(commonName);
158 if (dllName) {
159 len2 = PORT_Strlen(dllName);
161 if (param) {
162 len3 = PORT_Strlen(param);
165 slotParams = secmod_argGetParamValue("slotParams",nss);
166 slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
167 if (slotParams) PORT_Free(slotParams);
169 if (count && slotInfo == NULL) {
170 /* set error */
171 goto loser;
174 dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
175 count*sizeof(secmodSlotData);
177 data->data = (unsigned char *) PORT_ZAlloc(dataLen);
178 encoded = (secmodData *)data->data;
179 dataPtr = (unsigned char *) data->data;
180 data->size = dataLen;
182 if (encoded == NULL) {
183 /* set error */
184 goto loser;
187 encoded->major = SECMOD_DB_VERSION_MAJOR;
188 encoded->minor = SECMOD_DB_VERSION_MINOR;
189 encoded->internal = (unsigned char)
190 (secmod_argHasFlag("flags","internal",nss) ? 1 : 0);
191 encoded->fips = (unsigned char)
192 (secmod_argHasFlag("flags","FIPS",nss) ? 1 : 0);
193 encoded->isModuleDB = (unsigned char)
194 (secmod_argHasFlag("flags","isModuleDB",nss) ? 1 : 0);
195 encoded->isModuleDBOnly = (unsigned char)
196 (secmod_argHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
197 encoded->isCritical = (unsigned char)
198 (secmod_argHasFlag("flags","critical",nss) ? 1 : 0);
200 order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER,
201 NULL);
202 SECMOD_PUTLONG(encoded->trustOrder,order);
203 order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER,
204 NULL);
205 SECMOD_PUTLONG(encoded->cipherOrder,order);
208 ciphers = secmod_argGetParamValue("ciphers",nss);
209 secmod_argSetNewCipherFlags(&ssl[0], ciphers);
210 SECMOD_PUTLONG(encoded->ssl,ssl[0]);
211 SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]);
212 if (ciphers) PORT_Free(ciphers);
214 offset = (unsigned short) &(((secmodData *)0)->names[0]);
215 SECMOD_PUTSHORT(encoded->nameStart,offset);
216 offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
217 SECMOD_PUTSHORT(encoded->slotOffset,offset);
220 SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
221 slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
223 offset = 0;
224 SECMOD_PUTSHORT(encoded->names,len);
225 offset += sizeof(unsigned short);
226 PORT_Memcpy(&encoded->names[offset],commonName,len);
227 offset += len;
230 SECMOD_PUTSHORT(&encoded->names[offset],len2);
231 offset += sizeof(unsigned short);
232 if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
233 offset += len2;
235 SECMOD_PUTSHORT(&encoded->names[offset],len3);
236 offset += sizeof(unsigned short);
237 if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
238 offset += len3;
240 if (count) {
241 for (i=0; i < count; i++) {
242 SECMOD_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
243 SECMOD_PUTLONG(slot[i].defaultFlags,
244 slotInfo[i].defaultFlags);
245 SECMOD_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
246 slot[i].askpw = slotInfo[i].askpw;
247 slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
248 PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
251 rv = SECSuccess;
253 loser:
254 if (commonName) PORT_Free(commonName);
255 if (dllName) PORT_Free(dllName);
256 if (param) PORT_Free(param);
257 if (slotInfo) PORT_Free(slotInfo);
258 if (nss) PORT_Free(nss);
259 return rv;
263 static void
264 secmod_FreeData(DBT *data)
266 if (data->data) {
267 PORT_Free(data->data);
271 static void
272 secmod_FreeSlotStrings(char **slotStrings, int count)
274 int i;
276 for (i=0; i < count; i++) {
277 if (slotStrings[i]) {
278 PR_smprintf_free(slotStrings[i]);
279 slotStrings[i] = NULL;
285 * build a module from the data base entry.
287 static char *
288 secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
290 secmodData *encoded;
291 secmodSlotData *slots;
292 PLArenaPool *arena;
293 char *commonName = NULL;
294 char *dllName = NULL;
295 char *parameters = NULL;
296 char *nss;
297 char *moduleSpec;
298 char **slotStrings = NULL;
299 unsigned char *names;
300 unsigned long slotCount;
301 unsigned long ssl0 =0;
302 unsigned long ssl1 =0;
303 unsigned long slotID;
304 unsigned long defaultFlags;
305 unsigned long timeout;
306 unsigned long trustOrder =SECMOD_DEFAULT_TRUST_ORDER;
307 unsigned long cipherOrder =SECMOD_DEFAULT_CIPHER_ORDER;
308 unsigned short len;
309 unsigned short namesOffset = 0; /* start of the names block */
310 unsigned long namesRunningOffset; /* offset to name we are
311 * currently processing */
312 unsigned short slotOffset;
313 PRBool isOldVersion = PR_FALSE;
314 PRBool internal;
315 PRBool isFIPS;
316 PRBool isModuleDB =PR_FALSE;
317 PRBool isModuleDBOnly =PR_FALSE;
318 PRBool extended =PR_FALSE;
319 int i;
322 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
323 if (arena == NULL)
324 return NULL;
326 #define CHECK_SIZE(x) \
327 if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
329 /* -------------------------------------------------------------
330 ** Process the buffer header, which is the secmodData struct.
331 ** It may be an old or new version. Check the length for each.
334 CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
336 encoded = (secmodData *)data->data;
338 internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
339 isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
341 if (retInternal)
342 *retInternal = internal;
343 if (internal) {
344 parameters = PORT_ArenaStrdup(arena,defParams);
345 if (parameters == NULL)
346 goto loser;
348 if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
349 (encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
350 isOldVersion = PR_TRUE;
352 if ((encoded->major == SECMOD_DB_EXT1_VERSION_MAJOR) &&
353 (encoded->minor >= SECMOD_DB_EXT1_VERSION_MINOR)) {
354 CHECK_SIZE( sizeof(secmodData));
355 trustOrder = SECMOD_GETLONG(encoded->trustOrder);
356 cipherOrder = SECMOD_GETLONG(encoded->cipherOrder);
357 isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
358 isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
359 extended = PR_TRUE;
361 if (internal && !extended) {
362 trustOrder = 0;
363 cipherOrder = 100;
365 /* decode SSL cipher enable flags */
366 ssl0 = SECMOD_GETLONG(encoded->ssl);
367 ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
369 slotOffset = SECMOD_GETSHORT(encoded->slotOffset);
370 namesOffset = SECMOD_GETSHORT(encoded->nameStart);
373 /*--------------------------------------------------------------
374 ** Now process the variable length set of names.
375 ** The names have this structure:
376 ** struct {
377 ** BYTE commonNameLen[ 2 ];
378 ** BYTE commonName [ commonNameLen ];
379 ** BTTE libNameLen [ 2 ];
380 ** BYTE libName [ libNameLen ];
381 ** If it is "extended" it also has these members:
382 ** BYTE initStringLen[ 2 ];
383 ** BYTE initString [ initStringLen ];
384 ** }
387 namesRunningOffset = namesOffset;
388 /* copy the module's common name */
389 CHECK_SIZE( namesRunningOffset + 2);
390 names = (unsigned char *)data->data;
391 len = SECMOD_GETSHORT(names+namesRunningOffset);
393 CHECK_SIZE( namesRunningOffset + 2 + len);
394 commonName = (char*)PORT_ArenaAlloc(arena,len+1);
395 if (commonName == NULL)
396 goto loser;
397 PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
398 commonName[len] = 0;
399 namesRunningOffset += len + 2;
401 /* copy the module's shared library file name. */
402 CHECK_SIZE( namesRunningOffset + 2);
403 len = SECMOD_GETSHORT(names + namesRunningOffset);
404 if (len) {
405 CHECK_SIZE( namesRunningOffset + 2 + len);
406 dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
407 if (dllName == NULL)
408 goto loser;
409 PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
410 dllName[len] = 0;
412 namesRunningOffset += len + 2;
414 /* copy the module's initialization string, if present. */
415 if (!internal && extended) {
416 CHECK_SIZE( namesRunningOffset + 2);
417 len = SECMOD_GETSHORT(names+namesRunningOffset);
418 if (len) {
419 CHECK_SIZE( namesRunningOffset + 2 + len );
420 parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
421 if (parameters == NULL)
422 goto loser;
423 PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
424 parameters[len] = 0;
426 namesRunningOffset += len + 2;
430 * Consistency check: Make sure the slot and names blocks don't
431 * overlap. These blocks can occur in any order, so this check is made
432 * in 2 parts. First we check the case where the slot block starts
433 * after the name block. Later, when we have the slot block length,
434 * we check the case where slot block starts before the name block.
435 * NOTE: in most cases any overlap will likely be detected by invalid
436 * data read from the blocks, but it's better to find out sooner
437 * than later.
439 if (slotOffset >= namesOffset) { /* slot block starts after name block */
440 if (slotOffset < namesRunningOffset) {
441 goto db_loser;
445 /* ------------------------------------------------------------------
446 ** Part 3, process the slot table.
447 ** This part has this structure:
448 ** struct {
449 ** BYTE slotCount [ 2 ];
450 ** secmodSlotData [ slotCount ];
451 ** {
454 CHECK_SIZE( slotOffset + 2 );
455 slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
458 * Consistency check: Part 2. We now have the slot block length, we can
459 * check the case where the slotblock procedes the name block.
461 if (slotOffset < namesOffset) { /* slot block starts before name block */
462 if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
463 goto db_loser;
467 CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
468 slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
470 /* slotCount; */
471 slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
472 if (slotStrings == NULL)
473 goto loser;
474 for (i=0; i < (int) slotCount; i++, slots++) {
475 PRBool hasRootCerts =PR_FALSE;
476 PRBool hasRootTrust =PR_FALSE;
477 slotID = SECMOD_GETLONG(slots->slotID);
478 defaultFlags = SECMOD_GETLONG(slots->defaultFlags);
479 timeout = SECMOD_GETLONG(slots->timeout);
480 hasRootCerts = slots->hasRootCerts;
481 if (isOldVersion && internal && (slotID != 2)) {
482 unsigned long internalFlags=
483 secmod_argSlotFlags("slotFlags",SECMOD_SLOT_FLAGS);
484 defaultFlags |= internalFlags;
486 if (hasRootCerts && !extended) {
487 trustOrder = 100;
490 slotStrings[i] = secmod_mkSlotString(slotID, defaultFlags, timeout,
491 (unsigned char)slots->askpw,
492 hasRootCerts, hasRootTrust);
493 if (slotStrings[i] == NULL) {
494 secmod_FreeSlotStrings(slotStrings,i);
495 goto loser;
499 nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB,
500 isModuleDBOnly, internal, trustOrder, cipherOrder,
501 ssl0, ssl1);
502 secmod_FreeSlotStrings(slotStrings,slotCount);
503 /* it's permissible (and normal) for nss to be NULL. it simply means
504 * there are no NSS specific parameters in the database */
505 moduleSpec = secmod_mkNewModuleSpec(dllName,commonName,parameters,nss);
506 PR_smprintf_free(nss);
507 PORT_FreeArena(arena,PR_TRUE);
508 return moduleSpec;
510 db_loser:
511 PORT_SetError(SEC_ERROR_BAD_DATABASE);
512 loser:
513 PORT_FreeArena(arena,PR_TRUE);
514 return NULL;
517 static DB *
518 secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
519 PRBool readOnly, PRBool update)
521 DB *pkcs11db = NULL;
524 if (appName) {
525 char *secname = PORT_Strdup(filename);
526 int len = strlen(secname);
527 int status = RDB_FAIL;
529 if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
530 secname[len-3] = 0;
532 pkcs11db=
533 rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
534 if (update && !pkcs11db) {
535 DB *updatedb;
537 pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
538 if (!pkcs11db) {
539 if (status == RDB_RETRY) {
540 pkcs11db= rdbopen(appName, "", secname,
541 readOnly ? NO_RDONLY:NO_RDWR, NULL);
543 PORT_Free(secname);
544 return pkcs11db;
546 updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
547 if (updatedb) {
548 db_Copy(pkcs11db,updatedb);
549 (*updatedb->close)(updatedb);
550 } else {
551 (*pkcs11db->close)(pkcs11db);
552 PORT_Free(secname);
553 return NULL;
556 PORT_Free(secname);
557 return pkcs11db;
560 /* I'm sure we should do more checks here sometime... */
561 pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
563 /* didn't exist? create it */
564 if (pkcs11db == NULL) {
565 if (readOnly)
566 return NULL;
568 pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
569 if (pkcs11db)
570 (* pkcs11db->sync)(pkcs11db, 0);
572 return pkcs11db;
575 static void
576 secmod_CloseDB(DB *pkcs11db)
578 (*pkcs11db->close)(pkcs11db);
581 static char *
582 secmod_addEscape(const char *string, char quote)
584 char *newString = 0;
585 int escapes = 0, size = 0;
586 const char *src;
587 char *dest;
589 for (src=string; *src ; src++) {
590 if ((*src == quote) || (*src == '\\')) escapes++;
591 size++;
594 newString = PORT_ZAlloc(escapes+size+1);
595 if (newString == NULL) {
596 return NULL;
599 for (src=string, dest=newString; *src; src++,dest++) {
600 if ((*src == '\\') || (*src == quote)) {
601 *dest++ = '\\';
603 *dest = *src;
606 return newString;
609 SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
610 const char *dbname, char *module, PRBool rw);
612 #define SECMOD_STEP 10
613 #define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
615 * Read all the existing modules in
617 char **
618 legacy_ReadSecmodDB(const char *appName, const char *filename,
619 const char *dbname, char *params, PRBool rw)
621 DBT key,data;
622 int ret;
623 DB *pkcs11db = NULL;
624 char **moduleList = NULL, **newModuleList = NULL;
625 int moduleCount = 1;
626 int useCount = SECMOD_STEP;
628 moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
629 if (moduleList == NULL) return NULL;
631 pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
632 if (pkcs11db == NULL) goto done;
634 /* read and parse the file or data base */
635 ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
636 if (ret) goto done;
639 do {
640 char *moduleString;
641 PRBool internal = PR_FALSE;
642 if ((moduleCount+1) >= useCount) {
643 useCount += SECMOD_STEP;
644 newModuleList =
645 (char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
646 if (newModuleList == NULL) goto done;
647 moduleList = newModuleList;
648 PORT_Memset(&moduleList[moduleCount+1],0,
649 sizeof(char *)*SECMOD_STEP);
651 moduleString = secmod_DecodeData(params,&data,&internal);
652 if (internal) {
653 moduleList[0] = moduleString;
654 } else {
655 moduleList[moduleCount] = moduleString;
656 moduleCount++;
658 } while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
660 done:
661 if (!moduleList[0]) {
662 char * newparams = secmod_addEscape(params,'"');
663 if (newparams) {
664 moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
665 SECMOD_SLOT_FLAGS);
666 PORT_Free(newparams);
669 /* deal with trust cert db here */
671 if (pkcs11db) {
672 secmod_CloseDB(pkcs11db);
673 } else if (moduleList[0] && rw) {
674 legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
676 if (!moduleList[0]) {
677 PORT_Free(moduleList);
678 moduleList = NULL;
680 return moduleList;
683 SECStatus
684 legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
685 const char *dbname, char **moduleSpecList, PRBool rw)
687 if (moduleSpecList) {
688 char **index;
689 for(index = moduleSpecList; *index; index++) {
690 PR_smprintf_free(*index);
692 PORT_Free(moduleSpecList);
694 return SECSuccess;
698 * Delete a module from the Data Base
700 SECStatus
701 legacy_DeleteSecmodDB(const char *appName, const char *filename,
702 const char *dbname, char *args, PRBool rw)
704 DBT key;
705 SECStatus rv = SECFailure;
706 DB *pkcs11db = NULL;
707 int ret;
709 if (!rw) return SECFailure;
711 /* make sure we have a db handle */
712 pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
713 if (pkcs11db == NULL) {
714 return SECFailure;
717 rv = secmod_MakeKey(&key,args);
718 if (rv != SECSuccess) goto done;
719 rv = SECFailure;
720 ret = (*pkcs11db->del)(pkcs11db, &key, 0);
721 secmod_FreeKey(&key);
722 if (ret != 0) goto done;
725 ret = (*pkcs11db->sync)(pkcs11db, 0);
726 if (ret == 0) rv = SECSuccess;
728 done:
729 secmod_CloseDB(pkcs11db);
730 return rv;
734 * Add a module to the Data base
736 SECStatus
737 legacy_AddSecmodDB(const char *appName, const char *filename,
738 const char *dbname, char *module, PRBool rw)
740 DBT key,data;
741 SECStatus rv = SECFailure;
742 DB *pkcs11db = NULL;
743 int ret;
746 if (!rw) return SECFailure;
748 /* make sure we have a db handle */
749 pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
750 if (pkcs11db == NULL) {
751 return SECFailure;
754 rv = secmod_MakeKey(&key,module);
755 if (rv != SECSuccess) goto done;
756 rv = secmod_EncodeData(&data,module);
757 if (rv != SECSuccess) {
758 secmod_FreeKey(&key);
759 goto done;
761 rv = SECFailure;
762 ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
763 secmod_FreeKey(&key);
764 secmod_FreeData(&data);
765 if (ret != 0) goto done;
767 ret = (*pkcs11db->sync)(pkcs11db, 0);
768 if (ret == 0) rv = SECSuccess;
770 done:
771 secmod_CloseDB(pkcs11db);
772 return rv;