| OLD | NEW |
| (Empty) |
| 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 PRArenaPool *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(PRArenaPool *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 | |
| OLD | NEW |