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