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