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 &parameters, &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
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)