Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/pk11wrap/pk11pars.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 handles the loading, unloading and management of | |
6 * various PCKS #11 modules | |
7 */ | |
8 | |
9 #include <ctype.h> | |
10 #include "pkcs11.h" | |
11 #include "seccomon.h" | |
12 #include "secmod.h" | |
13 #include "secmodi.h" | |
14 #include "secmodti.h" | |
15 #include "pki3hack.h" | |
16 #include "secerr.h" | |
17 | |
18 #include "utilpars.h" | |
19 | |
20 /* create a new module */ | |
21 static SECMODModule * | |
22 secmod_NewModule(void) | |
23 { | |
24 SECMODModule *newMod; | |
25 PLArenaPool *arena; | |
26 | |
27 | |
28 /* create an arena in which dllName and commonName can be | |
29 * allocated. | |
30 */ | |
31 arena = PORT_NewArena(512); | |
32 if (arena == NULL) { | |
33 return NULL; | |
34 } | |
35 | |
36 newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule)); | |
37 if (newMod == NULL) { | |
38 PORT_FreeArena(arena,PR_FALSE); | |
39 return NULL; | |
40 } | |
41 | |
42 /* | |
43 * initialize of the fields of the module | |
44 */ | |
45 newMod->arena = arena; | |
46 newMod->internal = PR_FALSE; | |
47 newMod->loaded = PR_FALSE; | |
48 newMod->isFIPS = PR_FALSE; | |
49 newMod->dllName = NULL; | |
50 newMod->commonName = NULL; | |
51 newMod->library = NULL; | |
52 newMod->functionList = NULL; | |
53 newMod->slotCount = 0; | |
54 newMod->slots = NULL; | |
55 newMod->slotInfo = NULL; | |
56 newMod->slotInfoCount = 0; | |
57 newMod->refCount = 1; | |
58 newMod->ssl[0] = 0; | |
59 newMod->ssl[1] = 0; | |
60 newMod->libraryParams = NULL; | |
61 newMod->moduleDBFunc = NULL; | |
62 newMod->parent = NULL; | |
63 newMod->isCritical = PR_FALSE; | |
64 newMod->isModuleDB = PR_FALSE; | |
65 newMod->moduleDBOnly = PR_FALSE; | |
66 newMod->trustOrder = 0; | |
67 newMod->cipherOrder = 0; | |
68 newMod->evControlMask = 0; | |
69 newMod->refLock = PZ_NewLock(nssILockRefLock); | |
70 if (newMod->refLock == NULL) { | |
71 PORT_FreeArena(arena,PR_FALSE); | |
72 return NULL; | |
73 } | |
74 return newMod; | |
75 | |
76 } | |
77 | |
78 /* private flags for isModuleDB (field in SECMODModule). */ | |
79 /* The meaing of these flags is as follows: | |
80 * | |
81 * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the | |
82 * database of other modules to load. Module DBs are loadable modules that | |
83 * tells NSS which PKCS #11 modules to load and when. These module DBs are | |
84 * chainable. That is, one module DB can load another one. NSS system init | |
85 * design takes advantage of this feature. In system NSS, a fixed system | |
86 * module DB loads the system defined libraries, then chains out to the | |
87 * traditional module DBs to load any system or user configured modules | |
88 * (like smart cards). This bit is the same as the already existing meaning | |
89 * of isModuleDB = PR_TRUE. None of the other module db flags should be set | |
90 * if this flag isn't on. | |
91 * | |
92 * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first | |
93 * PKCS #11 module presented by a module DB. This allows the OS to load a | |
94 * softoken from the system module, then ask the existing module DB code to | |
95 * load the other PKCS #11 modules in that module DB (skipping it's request | |
96 * to load softoken). This gives the system init finer control over the | |
97 * configuration of that softoken module. | |
98 * | |
99 * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a | |
100 * different module DB as the 'default' module DB (the one in which | |
101 * 'Add module' changes will go). Without this flag NSS takes the first | |
102 * module as the default Module DB, but in system NSS, that first module | |
103 * is the system module, which is likely read only (at least to the user). | |
104 * This allows system NSS to delegate those changes to the user's module DB, | |
105 * preserving the user's ability to load new PKCS #11 modules (which only | |
106 * affect him), from existing applications like Firefox. | |
107 */ | |
108 #define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the | |
109 *other flags are set */ | |
110 #define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02 | |
111 #define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04 | |
112 | |
113 | |
114 /* private flags for internal (field in SECMODModule). */ | |
115 /* The meaing of these flags is as follows: | |
116 * | |
117 * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is | |
118 * the internal module (that is, softoken). This bit is the same as the | |
119 * already existing meaning of internal = PR_TRUE. None of the other | |
120 * internal flags should be set if this flag isn't on. | |
121 * | |
122 * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark | |
123 * a different slot returned byt PK11_GetInternalKeySlot(). The 'primary' | |
124 * slot defined by this module will be the new internal key slot. | |
125 */ | |
126 #define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of | |
127 *the other flags are set */ | |
128 #define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02 | |
129 | |
130 /* | |
131 * for 3.4 we continue to use the old SECMODModule structure | |
132 */ | |
133 SECMODModule * | |
134 SECMOD_CreateModule(const char *library, const char *moduleName, | |
135 const char *parameters, const char *nss) | |
136 { | |
137 SECMODModule *mod = secmod_NewModule(); | |
138 char *slotParams,*ciphers; | |
139 /* pk11pars.h still does not have const char * interfaces */ | |
140 char *nssc = (char *)nss; | |
141 if (mod == NULL) return NULL; | |
142 | |
143 mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : ""); | |
144 if (library) { | |
145 mod->dllName = PORT_ArenaStrdup(mod->arena,library); | |
146 } | |
147 /* new field */ | |
148 if (parameters) { | |
149 mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters); | |
150 } | |
151 mod->internal = NSSUTIL_ArgHasFlag("flags","internal",nssc); | |
152 mod->isFIPS = NSSUTIL_ArgHasFlag("flags","FIPS",nssc); | |
153 mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc); | |
154 slotParams = NSSUTIL_ArgGetParamValue("slotParams",nssc); | |
155 mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams, | |
156 &mod->slotInfoCount); | |
157 if (slotParams) PORT_Free(slotParams); | |
158 /* new field */ | |
159 mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder",nssc, | |
160 NSSUTIL_DEFAULT_TRUST_ORDER,NULL); | |
161 /* new field */ | |
162 mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder",nssc, | |
163 NSSUTIL_DEFAULT_CIPHER_ORDER,NULL); | |
164 /* new field */ | |
165 mod->isModuleDB = NSSUTIL_ArgHasFlag("flags","moduleDB",nssc); | |
166 mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags","moduleDBOnly",nssc); | |
167 if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE; | |
168 | |
169 /* we need more bits, but we also want to preserve binary compatibility | |
170 * so we overload the isModuleDB PRBool with additional flags. | |
171 * These flags are only valid if mod->isModuleDB is already set. | |
172 * NOTE: this depends on the fact that PRBool is at least a char on | |
173 * all platforms. These flags are only valid if moduleDB is set, so | |
174 * code checking if (mod->isModuleDB) will continue to work correctly. */ | |
175 if (mod->isModuleDB) { | |
176 char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB; | |
177 if (NSSUTIL_ArgHasFlag("flags","skipFirst",nssc)) { | |
178 flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST; | |
179 } | |
180 if (NSSUTIL_ArgHasFlag("flags","defaultModDB",nssc)) { | |
181 flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB; | |
182 } | |
183 /* additional moduleDB flags could be added here in the future */ | |
184 mod->isModuleDB = (PRBool) flags; | |
185 } | |
186 | |
187 if (mod->internal) { | |
188 char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL; | |
189 | |
190 if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) { | |
191 flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; | |
192 } | |
193 mod->internal = (PRBool) flags; | |
194 } | |
195 | |
196 ciphers = NSSUTIL_ArgGetParamValue("ciphers",nssc); | |
197 NSSUTIL_ArgParseCipherFlags(&mod->ssl[0],ciphers); | |
198 if (ciphers) PORT_Free(ciphers); | |
199 | |
200 secmod_PrivateModuleCount++; | |
201 | |
202 return mod; | |
203 } | |
204 | |
205 PRBool | |
206 SECMOD_GetSkipFirstFlag(SECMODModule *mod) | |
207 { | |
208 char flags = (char) mod->isModuleDB; | |
209 | |
210 return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE; | |
211 } | |
212 | |
213 PRBool | |
214 SECMOD_GetDefaultModDBFlag(SECMODModule *mod) | |
215 { | |
216 char flags = (char) mod->isModuleDB; | |
217 | |
218 return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; | |
219 } | |
220 | |
221 PRBool | |
222 secmod_IsInternalKeySlot(SECMODModule *mod) | |
223 { | |
224 char flags = (char) mod->internal; | |
225 | |
226 return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE; | |
227 } | |
228 | |
229 void | |
230 secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val) | |
231 { | |
232 char flags = (char) mod->internal; | |
233 | |
234 if (val) { | |
235 flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; | |
236 } else { | |
237 flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT; | |
238 } | |
239 mod->internal = flags; | |
240 } | |
241 | |
242 /* | |
243 * copy desc and value into target. Target is known to be big enough to | |
244 * hold desc +2 +value, which is good because the result of this will be | |
245 * *desc"*value". We may, however, have to add some escapes for special | |
246 * characters imbedded into value (rare). This string potentially comes from | |
247 * a user, so we don't want the user overflowing the target buffer by using | |
248 * excessive escapes. To prevent this we count the escapes we need to add and | |
249 * try to expand the buffer with Realloc. | |
250 */ | |
251 static char * | |
252 secmod_doDescCopy(char *target, int *targetLen, const char *desc, | |
253 int descLen, char *value) | |
254 { | |
255 int diff, esc_len; | |
256 | |
257 esc_len = NSSUTIL_EscapeSize(value, '\"') - 1; | |
258 diff = esc_len - strlen(value); | |
259 if (diff > 0) { | |
260 /* we need to escape... expand newSpecPtr as well to make sure | |
261 * we don't overflow it */ | |
262 char *newPtr = PORT_Realloc(target, *targetLen * diff); | |
263 if (!newPtr) { | |
264 return target; /* not enough space, just drop the whole copy */ | |
265 } | |
266 *targetLen += diff; | |
267 target = newPtr; | |
268 value = NSSUTIL_Escape(value, '\"'); | |
269 if (value == NULL) { | |
270 return target; /* couldn't escape value, just drop the copy */ | |
271 } | |
272 } | |
273 PORT_Memcpy(target, desc, descLen); | |
274 target += descLen; | |
275 *target++='\"'; | |
276 PORT_Memcpy(target, value, esc_len); | |
277 target += esc_len; | |
278 *target++='\"'; | |
279 if (diff > 0) { | |
280 PORT_Free(value); | |
281 } | |
282 return target; | |
283 } | |
284 | |
285 #define SECMOD_SPEC_COPY(new, start, end) \ | |
286 if (end > start) { \ | |
287 int _cnt = end - start; \ | |
288 PORT_Memcpy(new, start, _cnt); \ | |
289 new += _cnt; \ | |
290 } | |
291 #define SECMOD_TOKEN_DESCRIPTION "tokenDescription=" | |
292 #define SECMOD_SLOT_DESCRIPTION "slotDescription=" | |
293 | |
294 | |
295 /* | |
296 * Find any tokens= values in the module spec. | |
297 * Always return a new spec which does not have any tokens= arguments. | |
298 * If tokens= arguments are found, Split the the various tokens defined into | |
299 * an array of child specs to return. | |
300 * | |
301 * Caller is responsible for freeing the child spec and the new token | |
302 * spec. | |
303 */ | |
304 char * | |
305 secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS, | |
306 char *moduleSpec, char ***children, | |
307 CK_SLOT_ID **ids) | |
308 { | |
309 int newSpecLen = PORT_Strlen(moduleSpec)+2; | |
310 char *newSpec = PORT_Alloc(newSpecLen); | |
311 char *newSpecPtr = newSpec; | |
312 char *modulePrev = moduleSpec; | |
313 char *target = NULL; | |
314 char *tmp = NULL; | |
315 char **childArray = NULL; | |
316 char *tokenIndex; | |
317 CK_SLOT_ID *idArray = NULL; | |
318 int tokenCount = 0; | |
319 int i; | |
320 | |
321 if (newSpec == NULL) { | |
322 return NULL; | |
323 } | |
324 | |
325 *children = NULL; | |
326 if (ids) { | |
327 *ids = NULL; | |
328 } | |
329 moduleSpec = NSSUTIL_ArgStrip(moduleSpec); | |
330 SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); | |
331 | |
332 /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening | |
333 * a new softoken module takes the following parameters to name the | |
334 * various tokens: | |
335 * | |
336 * cryptoTokenDescription: name of the non-fips crypto token. | |
337 * cryptoSlotDescription: name of the non-fips crypto slot. | |
338 * dbTokenDescription: name of the non-fips db token. | |
339 * dbSlotDescription: name of the non-fips db slot. | |
340 * FIPSTokenDescription: name of the fips db/crypto token. | |
341 * FIPSSlotDescription: name of the fips db/crypto slot. | |
342 * | |
343 * if we are opening a new slot, we need to have the following | |
344 * parameters: | |
345 * tokenDescription: name of the token. | |
346 * slotDescription: name of the slot. | |
347 * | |
348 * | |
349 * The convert flag tells us to drop the unnecessary *TokenDescription | |
350 * and *SlotDescription arguments and convert the appropriate pair | |
351 * (either db or FIPS based on the isFIPS flag) to tokenDescription and | |
352 * slotDescription). | |
353 */ | |
354 /* | |
355 * walk down the list. if we find a tokens= argument, save it, | |
356 * otherise copy the argument. | |
357 */ | |
358 while (*moduleSpec) { | |
359 int next; | |
360 modulePrev = moduleSpec; | |
361 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=", | |
362 modulePrev = moduleSpec; /* skip copying */ ) | |
363 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoTokenDescription=", | |
364 if (convert) { modulePrev = moduleSpec; } ); | |
365 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoSlotDescription=", | |
366 if (convert) { modulePrev = moduleSpec; } ); | |
367 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbTokenDescription=", | |
368 if (convert) { | |
369 modulePrev = moduleSpec; | |
370 if (!isFIPS) { | |
371 newSpecPtr = secmod_doDescCopy(newSpecPtr, | |
372 &newSpecLen, SECMOD_TOKEN_DESCRIPTION, | |
373 sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); | |
374 } | |
375 }); | |
376 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbSlotDescription=", | |
377 if (convert) { | |
378 modulePrev = moduleSpec; /* skip copying */ | |
379 if (!isFIPS) { | |
380 newSpecPtr = secmod_doDescCopy(newSpecPtr, | |
381 &newSpecLen, SECMOD_SLOT_DESCRIPTION, | |
382 sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); | |
383 } | |
384 } ); | |
385 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSTokenDescription=", | |
386 if (convert) { | |
387 modulePrev = moduleSpec; /* skip copying */ | |
388 if (isFIPS) { | |
389 newSpecPtr = secmod_doDescCopy(newSpecPtr, | |
390 &newSpecLen, SECMOD_TOKEN_DESCRIPTION, | |
391 sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); | |
392 } | |
393 } ); | |
394 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSSlotDescription=", | |
395 if (convert) { | |
396 modulePrev = moduleSpec; /* skip copying */ | |
397 if (isFIPS) { | |
398 newSpecPtr = secmod_doDescCopy(newSpecPtr, | |
399 &newSpecLen, SECMOD_SLOT_DESCRIPTION, | |
400 sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); | |
401 } | |
402 } ); | |
403 NSSUTIL_HANDLE_FINAL_ARG(moduleSpec) | |
404 SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); | |
405 } | |
406 if (tmp) { | |
407 PORT_Free(tmp); | |
408 tmp = NULL; | |
409 } | |
410 *newSpecPtr = 0; | |
411 | |
412 /* no target found, return the newSpec */ | |
413 if (target == NULL) { | |
414 return newSpec; | |
415 } | |
416 | |
417 /* now build the child array from target */ | |
418 /*first count them */ | |
419 for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex; | |
420 tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) { | |
421 tokenCount++; | |
422 } | |
423 | |
424 childArray = PORT_NewArray(char *, tokenCount+1); | |
425 if (childArray == NULL) { | |
426 /* just return the spec as is then */ | |
427 PORT_Free(target); | |
428 return newSpec; | |
429 } | |
430 if (ids) { | |
431 idArray = PORT_NewArray(CK_SLOT_ID, tokenCount+1); | |
432 if (idArray == NULL) { | |
433 PORT_Free(childArray); | |
434 PORT_Free(target); | |
435 return newSpec; | |
436 } | |
437 } | |
438 | |
439 /* now fill them in */ | |
440 for (tokenIndex = NSSUTIL_ArgStrip(target), i=0 ; | |
441 *tokenIndex && (i < tokenCount); | |
442 tokenIndex=NSSUTIL_ArgStrip(tokenIndex)) { | |
443 int next; | |
444 char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next); | |
445 tokenIndex += next; | |
446 | |
447 if (idArray) { | |
448 idArray[i] = NSSUTIL_ArgDecodeNumber(name); | |
449 } | |
450 | |
451 PORT_Free(name); /* drop the explicit number */ | |
452 | |
453 /* if anything is left, copy the args to the child array */ | |
454 if (!NSSUTIL_ArgIsBlank(*tokenIndex)) { | |
455 childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next); | |
456 tokenIndex += next; | |
457 } | |
458 } | |
459 | |
460 PORT_Free(target); | |
461 childArray[i] = 0; | |
462 if (idArray) { | |
463 idArray[i] = 0; | |
464 } | |
465 | |
466 /* return it */ | |
467 *children = childArray; | |
468 if (ids) { | |
469 *ids = idArray; | |
470 } | |
471 return newSpec; | |
472 } | |
473 | |
474 /* get the database and flags from the spec */ | |
475 static char * | |
476 secmod_getConfigDir(char *spec, char **certPrefix, char **keyPrefix, | |
477 PRBool *readOnly) | |
478 { | |
479 char * config = NULL; | |
480 | |
481 *certPrefix = NULL; | |
482 *keyPrefix = NULL; | |
483 *readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",spec); | |
484 | |
485 spec = NSSUTIL_ArgStrip(spec); | |
486 while (*spec) { | |
487 int next; | |
488 NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;) | |
489 NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;) | |
490 NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;) | |
491 NSSUTIL_HANDLE_FINAL_ARG(spec) | |
492 } | |
493 return config; | |
494 } | |
495 | |
496 struct SECMODConfigListStr { | |
497 char *config; | |
498 char *certPrefix; | |
499 char *keyPrefix; | |
500 PRBool isReadOnly; | |
501 }; | |
502 | |
503 /* | |
504 * return an array of already openned databases from a spec list. | |
505 */ | |
506 SECMODConfigList * | |
507 secmod_GetConfigList(PRBool isFIPS, char *spec, int *count) | |
508 { | |
509 char **children; | |
510 CK_SLOT_ID *ids; | |
511 char *strippedSpec; | |
512 int childCount; | |
513 SECMODConfigList *conflist = NULL; | |
514 int i; | |
515 | |
516 strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS, | |
517 spec,&children,&ids); | |
518 if (strippedSpec == NULL) { | |
519 return NULL; | |
520 } | |
521 | |
522 for (childCount=0; children && children[childCount]; childCount++) ; | |
523 *count = childCount+1; /* include strippedSpec */ | |
524 conflist = PORT_NewArray(SECMODConfigList,*count); | |
525 if (conflist == NULL) { | |
526 *count = 0; | |
527 goto loser; | |
528 } | |
529 | |
530 conflist[0].config = secmod_getConfigDir(strippedSpec, | |
531 &conflist[0].certPrefix, | |
532 &conflist[0].keyPrefix, | |
533 &conflist[0].isReadOnly); | |
534 for (i=0; i < childCount; i++) { | |
535 conflist[i+1].config = secmod_getConfigDir(children[i], | |
536 &conflist[i+1].certPrefix, | |
537 &conflist[i+1].keyPrefix, | |
538 &conflist[i+1].isReadOnly); | |
539 } | |
540 | |
541 loser: | |
542 secmod_FreeChildren(children, ids); | |
543 PORT_Free(strippedSpec); | |
544 return conflist; | |
545 } | |
546 | |
547 /* | |
548 * determine if we are trying to open an old dbm database. For this test | |
549 * RDB databases should return PR_FALSE. | |
550 */ | |
551 static PRBool | |
552 secmod_configIsDBM(char *configDir) | |
553 { | |
554 char *env; | |
555 | |
556 /* explicit dbm open */ | |
557 if (strncmp(configDir, "dbm:", 4) == 0) { | |
558 return PR_TRUE; | |
559 } | |
560 /* explicit open of a non-dbm database */ | |
561 if ((strncmp(configDir, "sql:",4) == 0) | |
562 || (strncmp(configDir, "rdb:", 4) == 0) | |
563 || (strncmp(configDir, "extern:", 7) == 0)) { | |
564 return PR_FALSE; | |
565 } | |
566 env = PR_GetEnv("NSS_DEFAULT_DB_TYPE"); | |
567 /* implicit dbm open */ | |
568 if ((env == NULL) || (strcmp(env,"dbm") == 0)) { | |
569 return PR_TRUE; | |
570 } | |
571 /* implicit non-dbm open */ | |
572 return PR_FALSE; | |
573 } | |
574 | |
575 /* | |
576 * match two prefixes. prefix may be NULL. NULL patches '\0' | |
577 */ | |
578 static PRBool | |
579 secmod_matchPrefix(char *prefix1, char *prefix2) | |
580 { | |
581 if ((prefix1 == NULL) || (*prefix1 == 0)) { | |
582 if ((prefix2 == NULL) || (*prefix2 == 0)) { | |
583 return PR_TRUE; | |
584 } | |
585 return PR_FALSE; | |
586 } | |
587 if (strcmp(prefix1, prefix2) == 0) { | |
588 return PR_TRUE; | |
589 } | |
590 return PR_FALSE; | |
591 } | |
592 | |
593 /* | |
594 * return true if we are requesting a database that is already openned. | |
595 */ | |
596 PRBool | |
597 secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count) | |
598 { | |
599 char *config; | |
600 char *certPrefix; | |
601 char *keyPrefix; | |
602 PRBool isReadOnly; | |
603 PRBool ret=PR_FALSE; | |
604 int i; | |
605 | |
606 config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly); | |
607 if (!config) { | |
608 ret=PR_TRUE; | |
609 goto done; | |
610 } | |
611 | |
612 /* NOTE: we dbm isn't multiple open safe. If we open the same database | |
613 * twice from two different locations, then we can corrupt our database | |
614 * (the cache will be inconsistent). Protect against this by claiming | |
615 * for comparison only that we are always openning dbm databases read only. | |
616 */ | |
617 if (secmod_configIsDBM(config)) { | |
618 isReadOnly = 1; | |
619 } | |
620 for (i=0; i < count; i++) { | |
621 if ((strcmp(config,conflist[i].config) == 0) && | |
622 secmod_matchPrefix(certPrefix, conflist[i].certPrefix) && | |
623 secmod_matchPrefix(keyPrefix, conflist[i].keyPrefix) && | |
624 /* this last test -- if we just need the DB open read only, | |
625 * than any open will suffice, but if we requested it read/write | |
626 * and it's only open read only, we need to open it again */ | |
627 (isReadOnly || !conflist[i].isReadOnly)) { | |
628 ret = PR_TRUE; | |
629 goto done; | |
630 } | |
631 } | |
632 | |
633 ret = PR_FALSE; | |
634 done: | |
635 PORT_Free(config); | |
636 PORT_Free(certPrefix); | |
637 PORT_Free(keyPrefix); | |
638 return ret; | |
639 } | |
640 | |
641 void | |
642 secmod_FreeConfigList(SECMODConfigList *conflist, int count) | |
643 { | |
644 int i; | |
645 for (i=0; i < count; i++) { | |
646 PORT_Free(conflist[i].config); | |
647 PORT_Free(conflist[i].certPrefix); | |
648 PORT_Free(conflist[i].keyPrefix); | |
649 } | |
650 PORT_Free(conflist); | |
651 } | |
652 | |
653 void | |
654 secmod_FreeChildren(char **children, CK_SLOT_ID *ids) | |
655 { | |
656 char **thisChild; | |
657 | |
658 if (!children) { | |
659 return; | |
660 } | |
661 | |
662 for (thisChild = children; thisChild && *thisChild; thisChild++ ) { | |
663 PORT_Free(*thisChild); | |
664 } | |
665 PORT_Free(children); | |
666 if (ids) { | |
667 PORT_Free(ids); | |
668 } | |
669 return; | |
670 } | |
671 | |
672 /* | |
673 * caclulate the length of each child record: | |
674 * " 0x{id}=<{escaped_child}>" | |
675 */ | |
676 static int | |
677 secmod_getChildLength(char *child, CK_SLOT_ID id) | |
678 { | |
679 int length = NSSUTIL_DoubleEscapeSize(child, '>', ']'); | |
680 if (id == 0) { | |
681 length++; | |
682 } | |
683 while (id) { | |
684 length++; | |
685 id = id >> 4; | |
686 } | |
687 length += 6; /* {sp}0x[id]=<{child}> */ | |
688 return length; | |
689 } | |
690 | |
691 /* | |
692 * Build a child record: | |
693 * " 0x{id}=<{escaped_child}>" | |
694 */ | |
695 static SECStatus | |
696 secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id) | |
697 { | |
698 int len; | |
699 char *escSpec; | |
700 | |
701 len = PR_snprintf(*next, *length, " 0x%x=<",id); | |
702 if (len < 0) { | |
703 return SECFailure; | |
704 } | |
705 *next += len; | |
706 *length -= len; | |
707 escSpec = NSSUTIL_DoubleEscape(child, '>', ']'); | |
708 if (escSpec == NULL) { | |
709 return SECFailure; | |
710 } | |
711 if (*child && (*escSpec == 0)) { | |
712 PORT_Free(escSpec); | |
713 return SECFailure; | |
714 } | |
715 len = strlen(escSpec); | |
716 if (len+1 > *length) { | |
717 PORT_Free(escSpec); | |
718 return SECFailure; | |
719 } | |
720 PORT_Memcpy(*next,escSpec, len); | |
721 *next += len; | |
722 *length -= len; | |
723 PORT_Free(escSpec); | |
724 **next = '>'; | |
725 (*next)++; | |
726 (*length)--; | |
727 return SECSuccess; | |
728 } | |
729 | |
730 #define TOKEN_STRING " tokens=[" | |
731 | |
732 char * | |
733 secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken, | |
734 CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids) | |
735 { | |
736 char *rawParam = NULL; /* oldParam with tokens stripped off */ | |
737 char *newParam = NULL; /* space for the return parameter */ | |
738 char *nextParam = NULL; /* current end of the new parameter */ | |
739 char **oldChildren = NULL; | |
740 CK_SLOT_ID *oldIds = NULL; | |
741 void *mark = NULL; /* mark the arena pool in case we need | |
742 * to release it */ | |
743 int length, i, tmpLen; | |
744 SECStatus rv; | |
745 | |
746 /* first strip out and save the old tokenlist */ | |
747 rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE,PR_FALSE, | |
748 oldParam,&oldChildren,&oldIds); | |
749 if (!rawParam) { | |
750 goto loser; | |
751 } | |
752 | |
753 /* now calculate the total length of the new buffer */ | |
754 /* First the 'fixed stuff', length of rawparam (does not include a NULL), | |
755 * length of the token string (does include the NULL), closing bracket */ | |
756 length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1; | |
757 /* now add then length of all the old children */ | |
758 for (i=0; oldChildren && oldChildren[i]; i++) { | |
759 length += secmod_getChildLength(oldChildren[i], oldIds[i]); | |
760 } | |
761 | |
762 /* add the new token */ | |
763 length += secmod_getChildLength(newToken, newID); | |
764 | |
765 /* and it's new children */ | |
766 for (i=0; children && children[i]; i++) { | |
767 if (ids[i] == -1) { | |
768 continue; | |
769 } | |
770 length += secmod_getChildLength(children[i], ids[i]); | |
771 } | |
772 | |
773 /* now allocate and build the string */ | |
774 mark = PORT_ArenaMark(arena); | |
775 if (!mark) { | |
776 goto loser; | |
777 } | |
778 newParam = PORT_ArenaAlloc(arena,length); | |
779 if (!newParam) { | |
780 goto loser; | |
781 } | |
782 | |
783 PORT_Strcpy(newParam, oldParam); | |
784 tmpLen = strlen(oldParam); | |
785 nextParam = newParam + tmpLen; | |
786 length -= tmpLen; | |
787 PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING)-1); | |
788 nextParam += sizeof(TOKEN_STRING)-1; | |
789 length -= sizeof(TOKEN_STRING)-1; | |
790 | |
791 for (i=0; oldChildren && oldChildren[i]; i++) { | |
792 rv = secmod_mkTokenChild(&nextParam,&length,oldChildren[i],oldIds[i]); | |
793 if (rv != SECSuccess) { | |
794 goto loser; | |
795 } | |
796 } | |
797 | |
798 rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID); | |
799 if (rv != SECSuccess) { | |
800 goto loser; | |
801 } | |
802 | |
803 for (i=0; children && children[i]; i++) { | |
804 if (ids[i] == -1) { | |
805 continue; | |
806 } | |
807 rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]); | |
808 if (rv != SECSuccess) { | |
809 goto loser; | |
810 } | |
811 } | |
812 | |
813 if (length < 2) { | |
814 goto loser; | |
815 } | |
816 | |
817 *nextParam++ = ']'; | |
818 *nextParam++ = 0; | |
819 | |
820 /* we are going to return newParam now, don't release the mark */ | |
821 PORT_ArenaUnmark(arena, mark); | |
822 mark = NULL; | |
823 | |
824 loser: | |
825 if (mark) { | |
826 PORT_ArenaRelease(arena, mark); | |
827 newParam = NULL; /* if the mark is still active, | |
828 * don't return the param */ | |
829 } | |
830 if (rawParam) { | |
831 PORT_Free(rawParam); | |
832 } | |
833 if (oldChildren) { | |
834 secmod_FreeChildren(oldChildren, oldIds); | |
835 } | |
836 return newParam; | |
837 } | |
838 | |
839 static char * | |
840 secmod_mkModuleSpec(SECMODModule * module) | |
841 { | |
842 char *nss = NULL, *modSpec = NULL, **slotStrings = NULL; | |
843 int slotCount, i, si; | |
844 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); | |
845 | |
846 /* allocate target slot info strings */ | |
847 slotCount = 0; | |
848 | |
849 SECMOD_GetReadLock(moduleLock); | |
850 if (module->slotCount) { | |
851 for (i=0; i < module->slotCount; i++) { | |
852 if (module->slots[i]->defaultFlags !=0) { | |
853 slotCount++; | |
854 } | |
855 } | |
856 } else { | |
857 slotCount = module->slotInfoCount; | |
858 } | |
859 | |
860 slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *)); | |
861 if (slotStrings == NULL) { | |
862 SECMOD_ReleaseReadLock(moduleLock); | |
863 goto loser; | |
864 } | |
865 | |
866 | |
867 /* build the slot info strings */ | |
868 if (module->slotCount) { | |
869 for (i=0, si= 0; i < module->slotCount; i++) { | |
870 if (module->slots[i]->defaultFlags) { | |
871 PORT_Assert(si < slotCount); | |
872 if (si >= slotCount) break; | |
873 slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID, | |
874 module->slots[i]->defaultFlags, | |
875 module->slots[i]->timeout, | |
876 module->slots[i]->askpw, | |
877 module->slots[i]->hasRootCerts, | |
878 module->slots[i]->hasRootTrust); | |
879 si++; | |
880 } | |
881 } | |
882 } else { | |
883 for (i=0; i < slotCount; i++) { | |
884 slotStrings[i] = NSSUTIL_MkSlotString( | |
885 module->slotInfo[i].slotID, | |
886 module->slotInfo[i].defaultFlags, | |
887 module->slotInfo[i].timeout, | |
888 module->slotInfo[i].askpw, | |
889 module->slotInfo[i].hasRootCerts, | |
890 module->slotInfo[i].hasRootTrust); | |
891 } | |
892 } | |
893 | |
894 SECMOD_ReleaseReadLock(moduleLock); | |
895 nss = NSSUTIL_MkNSSString(slotStrings,slotCount,module->internal, | |
896 module->isFIPS, module->isModuleDB, | |
897 module->moduleDBOnly, module->isCritical, | |
898 module->trustOrder, module->cipherOrder, | |
899 module->ssl[0],module->ssl[1]); | |
900 modSpec= NSSUTIL_MkModuleSpec(module->dllName,module->commonName, | |
901 module->libraryParams,nss); | |
902 PORT_Free(slotStrings); | |
903 PR_smprintf_free(nss); | |
904 loser: | |
905 return (modSpec); | |
906 } | |
907 | |
908 | |
909 char ** | |
910 SECMOD_GetModuleSpecList(SECMODModule *module) | |
911 { | |
912 SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; | |
913 if (func) { | |
914 return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, | |
915 module->libraryParams,NULL); | |
916 } | |
917 return NULL; | |
918 } | |
919 | |
920 SECStatus | |
921 SECMOD_AddPermDB(SECMODModule *module) | |
922 { | |
923 SECMODModuleDBFunc func; | |
924 char *moduleSpec; | |
925 char **retString; | |
926 | |
927 if (module->parent == NULL) return SECFailure; | |
928 | |
929 func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; | |
930 if (func) { | |
931 moduleSpec = secmod_mkModuleSpec(module); | |
932 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD, | |
933 module->parent->libraryParams,moduleSpec); | |
934 PORT_Free(moduleSpec); | |
935 if (retString != NULL) return SECSuccess; | |
936 } | |
937 return SECFailure; | |
938 } | |
939 | |
940 SECStatus | |
941 SECMOD_DeletePermDB(SECMODModule *module) | |
942 { | |
943 SECMODModuleDBFunc func; | |
944 char *moduleSpec; | |
945 char **retString; | |
946 | |
947 if (module->parent == NULL) return SECFailure; | |
948 | |
949 func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; | |
950 if (func) { | |
951 moduleSpec = secmod_mkModuleSpec(module); | |
952 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL, | |
953 module->parent->libraryParams,moduleSpec); | |
954 PORT_Free(moduleSpec); | |
955 if (retString != NULL) return SECSuccess; | |
956 } | |
957 return SECFailure; | |
958 } | |
959 | |
960 SECStatus | |
961 SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList) | |
962 { | |
963 SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; | |
964 char **retString; | |
965 if (func) { | |
966 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE, | |
967 module->libraryParams,moduleSpecList); | |
968 if (retString != NULL) return SECSuccess; | |
969 } | |
970 return SECFailure; | |
971 } | |
972 | |
973 /* | |
974 * load a PKCS#11 module but do not add it to the default NSS trust domain | |
975 */ | |
976 SECMODModule * | |
977 SECMOD_LoadModule(char *modulespec,SECMODModule *parent, PRBool recurse) | |
978 { | |
979 char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL; | |
980 SECStatus status; | |
981 SECMODModule *module = NULL; | |
982 SECMODModule *oldModule = NULL; | |
983 SECStatus rv; | |
984 | |
985 /* initialize the underlying module structures */ | |
986 SECMOD_Init(); | |
987 | |
988 status = NSSUTIL_ArgParseModuleSpec(modulespec, &library, &moduleName, | |
989 ¶meters, &nss); | |
990 if (status != SECSuccess) { | |
991 goto loser; | |
992 } | |
993 | |
994 module = SECMOD_CreateModule(library, moduleName, parameters, nss); | |
995 if (library) PORT_Free(library); | |
996 if (moduleName) PORT_Free(moduleName); | |
997 if (parameters) PORT_Free(parameters); | |
998 if (nss) PORT_Free(nss); | |
999 if (!module) { | |
1000 goto loser; | |
1001 } | |
1002 if (parent) { | |
1003 module->parent = SECMOD_ReferenceModule(parent); | |
1004 if (module->internal && secmod_IsInternalKeySlot(parent)) { | |
1005 module->internal = parent->internal; | |
1006 } | |
1007 } | |
1008 | |
1009 /* load it */ | |
1010 rv = secmod_LoadPKCS11Module(module, &oldModule); | |
1011 if (rv != SECSuccess) { | |
1012 goto loser; | |
1013 } | |
1014 | |
1015 /* if we just reload an old module, no need to add it to any lists. | |
1016 * we simple release all our references */ | |
1017 if (oldModule) { | |
1018 /* This module already exists, don't link it anywhere. This | |
1019 * will probably destroy this module */ | |
1020 SECMOD_DestroyModule(module); | |
1021 return oldModule; | |
1022 } | |
1023 | |
1024 if (recurse && module->isModuleDB) { | |
1025 char ** moduleSpecList; | |
1026 PORT_SetError(0); | |
1027 | |
1028 moduleSpecList = SECMOD_GetModuleSpecList(module); | |
1029 if (moduleSpecList) { | |
1030 char **index; | |
1031 | |
1032 index = moduleSpecList; | |
1033 if (*index && SECMOD_GetSkipFirstFlag(module)) { | |
1034 index++; | |
1035 } | |
1036 | |
1037 for (; *index; index++) { | |
1038 SECMODModule *child; | |
1039 if (0 == PORT_Strcmp(*index, modulespec)) { | |
1040 /* avoid trivial infinite recursion */ | |
1041 PORT_SetError(SEC_ERROR_NO_MODULE); | |
1042 rv = SECFailure; | |
1043 break; | |
1044 } | |
1045 child = SECMOD_LoadModule(*index,module,PR_TRUE); | |
1046 if (!child) break; | |
1047 if (child->isCritical && !child->loaded) { | |
1048 int err = PORT_GetError(); | |
1049 if (!err) | |
1050 err = SEC_ERROR_NO_MODULE; | |
1051 SECMOD_DestroyModule(child); | |
1052 PORT_SetError(err); | |
1053 rv = SECFailure; | |
1054 break; | |
1055 } | |
1056 SECMOD_DestroyModule(child); | |
1057 } | |
1058 SECMOD_FreeModuleSpecList(module,moduleSpecList); | |
1059 } else { | |
1060 if (!PORT_GetError()) | |
1061 PORT_SetError(SEC_ERROR_NO_MODULE); | |
1062 rv = SECFailure; | |
1063 } | |
1064 } | |
1065 | |
1066 if (rv != SECSuccess) { | |
1067 goto loser; | |
1068 } | |
1069 | |
1070 | |
1071 /* inherit the reference */ | |
1072 if (!module->moduleDBOnly) { | |
1073 SECMOD_AddModuleToList(module); | |
1074 } else { | |
1075 SECMOD_AddModuleToDBOnlyList(module); | |
1076 } | |
1077 | |
1078 /* handle any additional work here */ | |
1079 return module; | |
1080 | |
1081 loser: | |
1082 if (module) { | |
1083 if (module->loaded) { | |
1084 SECMOD_UnloadModule(module); | |
1085 } | |
1086 SECMOD_AddModuleToUnloadList(module); | |
1087 } | |
1088 return module; | |
1089 } | |
1090 | |
1091 /* | |
1092 * load a PKCS#11 module and add it to the default NSS trust domain | |
1093 */ | |
1094 SECMODModule * | |
1095 SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse) | |
1096 { | |
1097 SECStatus rv = SECSuccess; | |
1098 SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse); | |
1099 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); | |
1100 | |
1101 if (newmod) { | |
1102 SECMOD_GetReadLock(moduleLock); | |
1103 rv = STAN_AddModuleToDefaultTrustDomain(newmod); | |
1104 SECMOD_ReleaseReadLock(moduleLock); | |
1105 if (SECSuccess != rv) { | |
1106 SECMOD_DestroyModule(newmod); | |
1107 return NULL; | |
1108 } | |
1109 } | |
1110 return newmod; | |
1111 } | |
1112 | |
1113 /* | |
1114 * remove the PKCS#11 module from the default NSS trust domain, call | |
1115 * C_Finalize, and destroy the module structure | |
1116 */ | |
1117 SECStatus SECMOD_UnloadUserModule(SECMODModule *mod) | |
1118 { | |
1119 SECStatus rv = SECSuccess; | |
1120 int atype = 0; | |
1121 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); | |
1122 if (!mod) { | |
1123 return SECFailure; | |
1124 } | |
1125 | |
1126 SECMOD_GetReadLock(moduleLock); | |
1127 rv = STAN_RemoveModuleFromDefaultTrustDomain(mod); | |
1128 SECMOD_ReleaseReadLock(moduleLock); | |
1129 if (SECSuccess != rv) { | |
1130 return SECFailure; | |
1131 } | |
1132 return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE); | |
1133 } | |
1134 |