1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11pars.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1134 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * The following handles the loading, unloading and management of 1.9 + * various PCKS #11 modules 1.10 + */ 1.11 + 1.12 +#include <ctype.h> 1.13 +#include "pkcs11.h" 1.14 +#include "seccomon.h" 1.15 +#include "secmod.h" 1.16 +#include "secmodi.h" 1.17 +#include "secmodti.h" 1.18 +#include "pki3hack.h" 1.19 +#include "secerr.h" 1.20 + 1.21 +#include "utilpars.h" 1.22 + 1.23 +/* create a new module */ 1.24 +static SECMODModule * 1.25 +secmod_NewModule(void) 1.26 +{ 1.27 + SECMODModule *newMod; 1.28 + PLArenaPool *arena; 1.29 + 1.30 + 1.31 + /* create an arena in which dllName and commonName can be 1.32 + * allocated. 1.33 + */ 1.34 + arena = PORT_NewArena(512); 1.35 + if (arena == NULL) { 1.36 + return NULL; 1.37 + } 1.38 + 1.39 + newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule)); 1.40 + if (newMod == NULL) { 1.41 + PORT_FreeArena(arena,PR_FALSE); 1.42 + return NULL; 1.43 + } 1.44 + 1.45 + /* 1.46 + * initialize of the fields of the module 1.47 + */ 1.48 + newMod->arena = arena; 1.49 + newMod->internal = PR_FALSE; 1.50 + newMod->loaded = PR_FALSE; 1.51 + newMod->isFIPS = PR_FALSE; 1.52 + newMod->dllName = NULL; 1.53 + newMod->commonName = NULL; 1.54 + newMod->library = NULL; 1.55 + newMod->functionList = NULL; 1.56 + newMod->slotCount = 0; 1.57 + newMod->slots = NULL; 1.58 + newMod->slotInfo = NULL; 1.59 + newMod->slotInfoCount = 0; 1.60 + newMod->refCount = 1; 1.61 + newMod->ssl[0] = 0; 1.62 + newMod->ssl[1] = 0; 1.63 + newMod->libraryParams = NULL; 1.64 + newMod->moduleDBFunc = NULL; 1.65 + newMod->parent = NULL; 1.66 + newMod->isCritical = PR_FALSE; 1.67 + newMod->isModuleDB = PR_FALSE; 1.68 + newMod->moduleDBOnly = PR_FALSE; 1.69 + newMod->trustOrder = 0; 1.70 + newMod->cipherOrder = 0; 1.71 + newMod->evControlMask = 0; 1.72 + newMod->refLock = PZ_NewLock(nssILockRefLock); 1.73 + if (newMod->refLock == NULL) { 1.74 + PORT_FreeArena(arena,PR_FALSE); 1.75 + return NULL; 1.76 + } 1.77 + return newMod; 1.78 + 1.79 +} 1.80 + 1.81 +/* private flags for isModuleDB (field in SECMODModule). */ 1.82 +/* The meaing of these flags is as follows: 1.83 + * 1.84 + * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the 1.85 + * database of other modules to load. Module DBs are loadable modules that 1.86 + * tells NSS which PKCS #11 modules to load and when. These module DBs are 1.87 + * chainable. That is, one module DB can load another one. NSS system init 1.88 + * design takes advantage of this feature. In system NSS, a fixed system 1.89 + * module DB loads the system defined libraries, then chains out to the 1.90 + * traditional module DBs to load any system or user configured modules 1.91 + * (like smart cards). This bit is the same as the already existing meaning 1.92 + * of isModuleDB = PR_TRUE. None of the other module db flags should be set 1.93 + * if this flag isn't on. 1.94 + * 1.95 + * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first 1.96 + * PKCS #11 module presented by a module DB. This allows the OS to load a 1.97 + * softoken from the system module, then ask the existing module DB code to 1.98 + * load the other PKCS #11 modules in that module DB (skipping it's request 1.99 + * to load softoken). This gives the system init finer control over the 1.100 + * configuration of that softoken module. 1.101 + * 1.102 + * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a 1.103 + * different module DB as the 'default' module DB (the one in which 1.104 + * 'Add module' changes will go). Without this flag NSS takes the first 1.105 + * module as the default Module DB, but in system NSS, that first module 1.106 + * is the system module, which is likely read only (at least to the user). 1.107 + * This allows system NSS to delegate those changes to the user's module DB, 1.108 + * preserving the user's ability to load new PKCS #11 modules (which only 1.109 + * affect him), from existing applications like Firefox. 1.110 + */ 1.111 +#define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the 1.112 + *other flags are set */ 1.113 +#define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02 1.114 +#define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04 1.115 + 1.116 + 1.117 +/* private flags for internal (field in SECMODModule). */ 1.118 +/* The meaing of these flags is as follows: 1.119 + * 1.120 + * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is 1.121 + * the internal module (that is, softoken). This bit is the same as the 1.122 + * already existing meaning of internal = PR_TRUE. None of the other 1.123 + * internal flags should be set if this flag isn't on. 1.124 + * 1.125 + * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark 1.126 + * a different slot returned byt PK11_GetInternalKeySlot(). The 'primary' 1.127 + * slot defined by this module will be the new internal key slot. 1.128 + */ 1.129 +#define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of 1.130 + *the other flags are set */ 1.131 +#define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02 1.132 + 1.133 +/* 1.134 + * for 3.4 we continue to use the old SECMODModule structure 1.135 + */ 1.136 +SECMODModule * 1.137 +SECMOD_CreateModule(const char *library, const char *moduleName, 1.138 + const char *parameters, const char *nss) 1.139 +{ 1.140 + SECMODModule *mod = secmod_NewModule(); 1.141 + char *slotParams,*ciphers; 1.142 + /* pk11pars.h still does not have const char * interfaces */ 1.143 + char *nssc = (char *)nss; 1.144 + if (mod == NULL) return NULL; 1.145 + 1.146 + mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : ""); 1.147 + if (library) { 1.148 + mod->dllName = PORT_ArenaStrdup(mod->arena,library); 1.149 + } 1.150 + /* new field */ 1.151 + if (parameters) { 1.152 + mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters); 1.153 + } 1.154 + mod->internal = NSSUTIL_ArgHasFlag("flags","internal",nssc); 1.155 + mod->isFIPS = NSSUTIL_ArgHasFlag("flags","FIPS",nssc); 1.156 + mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc); 1.157 + slotParams = NSSUTIL_ArgGetParamValue("slotParams",nssc); 1.158 + mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams, 1.159 + &mod->slotInfoCount); 1.160 + if (slotParams) PORT_Free(slotParams); 1.161 + /* new field */ 1.162 + mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder",nssc, 1.163 + NSSUTIL_DEFAULT_TRUST_ORDER,NULL); 1.164 + /* new field */ 1.165 + mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder",nssc, 1.166 + NSSUTIL_DEFAULT_CIPHER_ORDER,NULL); 1.167 + /* new field */ 1.168 + mod->isModuleDB = NSSUTIL_ArgHasFlag("flags","moduleDB",nssc); 1.169 + mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags","moduleDBOnly",nssc); 1.170 + if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE; 1.171 + 1.172 + /* we need more bits, but we also want to preserve binary compatibility 1.173 + * so we overload the isModuleDB PRBool with additional flags. 1.174 + * These flags are only valid if mod->isModuleDB is already set. 1.175 + * NOTE: this depends on the fact that PRBool is at least a char on 1.176 + * all platforms. These flags are only valid if moduleDB is set, so 1.177 + * code checking if (mod->isModuleDB) will continue to work correctly. */ 1.178 + if (mod->isModuleDB) { 1.179 + char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB; 1.180 + if (NSSUTIL_ArgHasFlag("flags","skipFirst",nssc)) { 1.181 + flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST; 1.182 + } 1.183 + if (NSSUTIL_ArgHasFlag("flags","defaultModDB",nssc)) { 1.184 + flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB; 1.185 + } 1.186 + /* additional moduleDB flags could be added here in the future */ 1.187 + mod->isModuleDB = (PRBool) flags; 1.188 + } 1.189 + 1.190 + if (mod->internal) { 1.191 + char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL; 1.192 + 1.193 + if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) { 1.194 + flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; 1.195 + } 1.196 + mod->internal = (PRBool) flags; 1.197 + } 1.198 + 1.199 + ciphers = NSSUTIL_ArgGetParamValue("ciphers",nssc); 1.200 + NSSUTIL_ArgParseCipherFlags(&mod->ssl[0],ciphers); 1.201 + if (ciphers) PORT_Free(ciphers); 1.202 + 1.203 + secmod_PrivateModuleCount++; 1.204 + 1.205 + return mod; 1.206 +} 1.207 + 1.208 +PRBool 1.209 +SECMOD_GetSkipFirstFlag(SECMODModule *mod) 1.210 +{ 1.211 + char flags = (char) mod->isModuleDB; 1.212 + 1.213 + return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE; 1.214 +} 1.215 + 1.216 +PRBool 1.217 +SECMOD_GetDefaultModDBFlag(SECMODModule *mod) 1.218 +{ 1.219 + char flags = (char) mod->isModuleDB; 1.220 + 1.221 + return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; 1.222 +} 1.223 + 1.224 +PRBool 1.225 +secmod_IsInternalKeySlot(SECMODModule *mod) 1.226 +{ 1.227 + char flags = (char) mod->internal; 1.228 + 1.229 + return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE; 1.230 +} 1.231 + 1.232 +void 1.233 +secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val) 1.234 +{ 1.235 + char flags = (char) mod->internal; 1.236 + 1.237 + if (val) { 1.238 + flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; 1.239 + } else { 1.240 + flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT; 1.241 + } 1.242 + mod->internal = flags; 1.243 +} 1.244 + 1.245 +/* 1.246 + * copy desc and value into target. Target is known to be big enough to 1.247 + * hold desc +2 +value, which is good because the result of this will be 1.248 + * *desc"*value". We may, however, have to add some escapes for special 1.249 + * characters imbedded into value (rare). This string potentially comes from 1.250 + * a user, so we don't want the user overflowing the target buffer by using 1.251 + * excessive escapes. To prevent this we count the escapes we need to add and 1.252 + * try to expand the buffer with Realloc. 1.253 + */ 1.254 +static char * 1.255 +secmod_doDescCopy(char *target, int *targetLen, const char *desc, 1.256 + int descLen, char *value) 1.257 +{ 1.258 + int diff, esc_len; 1.259 + 1.260 + esc_len = NSSUTIL_EscapeSize(value, '\"') - 1; 1.261 + diff = esc_len - strlen(value); 1.262 + if (diff > 0) { 1.263 + /* we need to escape... expand newSpecPtr as well to make sure 1.264 + * we don't overflow it */ 1.265 + char *newPtr = PORT_Realloc(target, *targetLen * diff); 1.266 + if (!newPtr) { 1.267 + return target; /* not enough space, just drop the whole copy */ 1.268 + } 1.269 + *targetLen += diff; 1.270 + target = newPtr; 1.271 + value = NSSUTIL_Escape(value, '\"'); 1.272 + if (value == NULL) { 1.273 + return target; /* couldn't escape value, just drop the copy */ 1.274 + } 1.275 + } 1.276 + PORT_Memcpy(target, desc, descLen); 1.277 + target += descLen; 1.278 + *target++='\"'; 1.279 + PORT_Memcpy(target, value, esc_len); 1.280 + target += esc_len; 1.281 + *target++='\"'; 1.282 + if (diff > 0) { 1.283 + PORT_Free(value); 1.284 + } 1.285 + return target; 1.286 +} 1.287 + 1.288 +#define SECMOD_SPEC_COPY(new, start, end) \ 1.289 + if (end > start) { \ 1.290 + int _cnt = end - start; \ 1.291 + PORT_Memcpy(new, start, _cnt); \ 1.292 + new += _cnt; \ 1.293 + } 1.294 +#define SECMOD_TOKEN_DESCRIPTION "tokenDescription=" 1.295 +#define SECMOD_SLOT_DESCRIPTION "slotDescription=" 1.296 + 1.297 + 1.298 +/* 1.299 + * Find any tokens= values in the module spec. 1.300 + * Always return a new spec which does not have any tokens= arguments. 1.301 + * If tokens= arguments are found, Split the the various tokens defined into 1.302 + * an array of child specs to return. 1.303 + * 1.304 + * Caller is responsible for freeing the child spec and the new token 1.305 + * spec. 1.306 + */ 1.307 +char * 1.308 +secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS, 1.309 + char *moduleSpec, char ***children, 1.310 + CK_SLOT_ID **ids) 1.311 +{ 1.312 + int newSpecLen = PORT_Strlen(moduleSpec)+2; 1.313 + char *newSpec = PORT_Alloc(newSpecLen); 1.314 + char *newSpecPtr = newSpec; 1.315 + char *modulePrev = moduleSpec; 1.316 + char *target = NULL; 1.317 + char *tmp = NULL; 1.318 + char **childArray = NULL; 1.319 + char *tokenIndex; 1.320 + CK_SLOT_ID *idArray = NULL; 1.321 + int tokenCount = 0; 1.322 + int i; 1.323 + 1.324 + if (newSpec == NULL) { 1.325 + return NULL; 1.326 + } 1.327 + 1.328 + *children = NULL; 1.329 + if (ids) { 1.330 + *ids = NULL; 1.331 + } 1.332 + moduleSpec = NSSUTIL_ArgStrip(moduleSpec); 1.333 + SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); 1.334 + 1.335 + /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening 1.336 + * a new softoken module takes the following parameters to name the 1.337 + * various tokens: 1.338 + * 1.339 + * cryptoTokenDescription: name of the non-fips crypto token. 1.340 + * cryptoSlotDescription: name of the non-fips crypto slot. 1.341 + * dbTokenDescription: name of the non-fips db token. 1.342 + * dbSlotDescription: name of the non-fips db slot. 1.343 + * FIPSTokenDescription: name of the fips db/crypto token. 1.344 + * FIPSSlotDescription: name of the fips db/crypto slot. 1.345 + * 1.346 + * if we are opening a new slot, we need to have the following 1.347 + * parameters: 1.348 + * tokenDescription: name of the token. 1.349 + * slotDescription: name of the slot. 1.350 + * 1.351 + * 1.352 + * The convert flag tells us to drop the unnecessary *TokenDescription 1.353 + * and *SlotDescription arguments and convert the appropriate pair 1.354 + * (either db or FIPS based on the isFIPS flag) to tokenDescription and 1.355 + * slotDescription). 1.356 + */ 1.357 + /* 1.358 + * walk down the list. if we find a tokens= argument, save it, 1.359 + * otherise copy the argument. 1.360 + */ 1.361 + while (*moduleSpec) { 1.362 + int next; 1.363 + modulePrev = moduleSpec; 1.364 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=", 1.365 + modulePrev = moduleSpec; /* skip copying */ ) 1.366 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoTokenDescription=", 1.367 + if (convert) { modulePrev = moduleSpec; } ); 1.368 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoSlotDescription=", 1.369 + if (convert) { modulePrev = moduleSpec; } ); 1.370 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbTokenDescription=", 1.371 + if (convert) { 1.372 + modulePrev = moduleSpec; 1.373 + if (!isFIPS) { 1.374 + newSpecPtr = secmod_doDescCopy(newSpecPtr, 1.375 + &newSpecLen, SECMOD_TOKEN_DESCRIPTION, 1.376 + sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); 1.377 + } 1.378 + }); 1.379 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbSlotDescription=", 1.380 + if (convert) { 1.381 + modulePrev = moduleSpec; /* skip copying */ 1.382 + if (!isFIPS) { 1.383 + newSpecPtr = secmod_doDescCopy(newSpecPtr, 1.384 + &newSpecLen, SECMOD_SLOT_DESCRIPTION, 1.385 + sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); 1.386 + } 1.387 + } ); 1.388 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSTokenDescription=", 1.389 + if (convert) { 1.390 + modulePrev = moduleSpec; /* skip copying */ 1.391 + if (isFIPS) { 1.392 + newSpecPtr = secmod_doDescCopy(newSpecPtr, 1.393 + &newSpecLen, SECMOD_TOKEN_DESCRIPTION, 1.394 + sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); 1.395 + } 1.396 + } ); 1.397 + NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSSlotDescription=", 1.398 + if (convert) { 1.399 + modulePrev = moduleSpec; /* skip copying */ 1.400 + if (isFIPS) { 1.401 + newSpecPtr = secmod_doDescCopy(newSpecPtr, 1.402 + &newSpecLen, SECMOD_SLOT_DESCRIPTION, 1.403 + sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); 1.404 + } 1.405 + } ); 1.406 + NSSUTIL_HANDLE_FINAL_ARG(moduleSpec) 1.407 + SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); 1.408 + } 1.409 + if (tmp) { 1.410 + PORT_Free(tmp); 1.411 + tmp = NULL; 1.412 + } 1.413 + *newSpecPtr = 0; 1.414 + 1.415 + /* no target found, return the newSpec */ 1.416 + if (target == NULL) { 1.417 + return newSpec; 1.418 + } 1.419 + 1.420 + /* now build the child array from target */ 1.421 + /*first count them */ 1.422 + for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex; 1.423 + tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) { 1.424 + tokenCount++; 1.425 + } 1.426 + 1.427 + childArray = PORT_NewArray(char *, tokenCount+1); 1.428 + if (childArray == NULL) { 1.429 + /* just return the spec as is then */ 1.430 + PORT_Free(target); 1.431 + return newSpec; 1.432 + } 1.433 + if (ids) { 1.434 + idArray = PORT_NewArray(CK_SLOT_ID, tokenCount+1); 1.435 + if (idArray == NULL) { 1.436 + PORT_Free(childArray); 1.437 + PORT_Free(target); 1.438 + return newSpec; 1.439 + } 1.440 + } 1.441 + 1.442 + /* now fill them in */ 1.443 + for (tokenIndex = NSSUTIL_ArgStrip(target), i=0 ; 1.444 + *tokenIndex && (i < tokenCount); 1.445 + tokenIndex=NSSUTIL_ArgStrip(tokenIndex)) { 1.446 + int next; 1.447 + char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next); 1.448 + tokenIndex += next; 1.449 + 1.450 + if (idArray) { 1.451 + idArray[i] = NSSUTIL_ArgDecodeNumber(name); 1.452 + } 1.453 + 1.454 + PORT_Free(name); /* drop the explicit number */ 1.455 + 1.456 + /* if anything is left, copy the args to the child array */ 1.457 + if (!NSSUTIL_ArgIsBlank(*tokenIndex)) { 1.458 + childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next); 1.459 + tokenIndex += next; 1.460 + } 1.461 + } 1.462 + 1.463 + PORT_Free(target); 1.464 + childArray[i] = 0; 1.465 + if (idArray) { 1.466 + idArray[i] = 0; 1.467 + } 1.468 + 1.469 + /* return it */ 1.470 + *children = childArray; 1.471 + if (ids) { 1.472 + *ids = idArray; 1.473 + } 1.474 + return newSpec; 1.475 +} 1.476 + 1.477 +/* get the database and flags from the spec */ 1.478 +static char * 1.479 +secmod_getConfigDir(char *spec, char **certPrefix, char **keyPrefix, 1.480 + PRBool *readOnly) 1.481 +{ 1.482 + char * config = NULL; 1.483 + 1.484 + *certPrefix = NULL; 1.485 + *keyPrefix = NULL; 1.486 + *readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",spec); 1.487 + 1.488 + spec = NSSUTIL_ArgStrip(spec); 1.489 + while (*spec) { 1.490 + int next; 1.491 + NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;) 1.492 + NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;) 1.493 + NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;) 1.494 + NSSUTIL_HANDLE_FINAL_ARG(spec) 1.495 + } 1.496 + return config; 1.497 +} 1.498 + 1.499 +struct SECMODConfigListStr { 1.500 + char *config; 1.501 + char *certPrefix; 1.502 + char *keyPrefix; 1.503 + PRBool isReadOnly; 1.504 +}; 1.505 + 1.506 +/* 1.507 + * return an array of already openned databases from a spec list. 1.508 + */ 1.509 +SECMODConfigList * 1.510 +secmod_GetConfigList(PRBool isFIPS, char *spec, int *count) 1.511 +{ 1.512 + char **children; 1.513 + CK_SLOT_ID *ids; 1.514 + char *strippedSpec; 1.515 + int childCount; 1.516 + SECMODConfigList *conflist = NULL; 1.517 + int i; 1.518 + 1.519 + strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS, 1.520 + spec,&children,&ids); 1.521 + if (strippedSpec == NULL) { 1.522 + return NULL; 1.523 + } 1.524 + 1.525 + for (childCount=0; children && children[childCount]; childCount++) ; 1.526 + *count = childCount+1; /* include strippedSpec */ 1.527 + conflist = PORT_NewArray(SECMODConfigList,*count); 1.528 + if (conflist == NULL) { 1.529 + *count = 0; 1.530 + goto loser; 1.531 + } 1.532 + 1.533 + conflist[0].config = secmod_getConfigDir(strippedSpec, 1.534 + &conflist[0].certPrefix, 1.535 + &conflist[0].keyPrefix, 1.536 + &conflist[0].isReadOnly); 1.537 + for (i=0; i < childCount; i++) { 1.538 + conflist[i+1].config = secmod_getConfigDir(children[i], 1.539 + &conflist[i+1].certPrefix, 1.540 + &conflist[i+1].keyPrefix, 1.541 + &conflist[i+1].isReadOnly); 1.542 + } 1.543 + 1.544 +loser: 1.545 + secmod_FreeChildren(children, ids); 1.546 + PORT_Free(strippedSpec); 1.547 + return conflist; 1.548 +} 1.549 + 1.550 +/* 1.551 + * determine if we are trying to open an old dbm database. For this test 1.552 + * RDB databases should return PR_FALSE. 1.553 + */ 1.554 +static PRBool 1.555 +secmod_configIsDBM(char *configDir) 1.556 +{ 1.557 + char *env; 1.558 + 1.559 + /* explicit dbm open */ 1.560 + if (strncmp(configDir, "dbm:", 4) == 0) { 1.561 + return PR_TRUE; 1.562 + } 1.563 + /* explicit open of a non-dbm database */ 1.564 + if ((strncmp(configDir, "sql:",4) == 0) 1.565 + || (strncmp(configDir, "rdb:", 4) == 0) 1.566 + || (strncmp(configDir, "extern:", 7) == 0)) { 1.567 + return PR_FALSE; 1.568 + } 1.569 + env = PR_GetEnv("NSS_DEFAULT_DB_TYPE"); 1.570 + /* implicit dbm open */ 1.571 + if ((env == NULL) || (strcmp(env,"dbm") == 0)) { 1.572 + return PR_TRUE; 1.573 + } 1.574 + /* implicit non-dbm open */ 1.575 + return PR_FALSE; 1.576 +} 1.577 + 1.578 +/* 1.579 + * match two prefixes. prefix may be NULL. NULL patches '\0' 1.580 + */ 1.581 +static PRBool 1.582 +secmod_matchPrefix(char *prefix1, char *prefix2) 1.583 +{ 1.584 + if ((prefix1 == NULL) || (*prefix1 == 0)) { 1.585 + if ((prefix2 == NULL) || (*prefix2 == 0)) { 1.586 + return PR_TRUE; 1.587 + } 1.588 + return PR_FALSE; 1.589 + } 1.590 + if (strcmp(prefix1, prefix2) == 0) { 1.591 + return PR_TRUE; 1.592 + } 1.593 + return PR_FALSE; 1.594 +} 1.595 + 1.596 +/* 1.597 + * return true if we are requesting a database that is already openned. 1.598 + */ 1.599 +PRBool 1.600 +secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count) 1.601 +{ 1.602 + char *config; 1.603 + char *certPrefix; 1.604 + char *keyPrefix; 1.605 + PRBool isReadOnly; 1.606 + PRBool ret=PR_FALSE; 1.607 + int i; 1.608 + 1.609 + config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly); 1.610 + if (!config) { 1.611 + ret=PR_TRUE; 1.612 + goto done; 1.613 + } 1.614 + 1.615 + /* NOTE: we dbm isn't multiple open safe. If we open the same database 1.616 + * twice from two different locations, then we can corrupt our database 1.617 + * (the cache will be inconsistent). Protect against this by claiming 1.618 + * for comparison only that we are always openning dbm databases read only. 1.619 + */ 1.620 + if (secmod_configIsDBM(config)) { 1.621 + isReadOnly = 1; 1.622 + } 1.623 + for (i=0; i < count; i++) { 1.624 + if ((strcmp(config,conflist[i].config) == 0) && 1.625 + secmod_matchPrefix(certPrefix, conflist[i].certPrefix) && 1.626 + secmod_matchPrefix(keyPrefix, conflist[i].keyPrefix) && 1.627 + /* this last test -- if we just need the DB open read only, 1.628 + * than any open will suffice, but if we requested it read/write 1.629 + * and it's only open read only, we need to open it again */ 1.630 + (isReadOnly || !conflist[i].isReadOnly)) { 1.631 + ret = PR_TRUE; 1.632 + goto done; 1.633 + } 1.634 + } 1.635 + 1.636 + ret = PR_FALSE; 1.637 +done: 1.638 + PORT_Free(config); 1.639 + PORT_Free(certPrefix); 1.640 + PORT_Free(keyPrefix); 1.641 + return ret; 1.642 +} 1.643 + 1.644 +void 1.645 +secmod_FreeConfigList(SECMODConfigList *conflist, int count) 1.646 +{ 1.647 + int i; 1.648 + for (i=0; i < count; i++) { 1.649 + PORT_Free(conflist[i].config); 1.650 + PORT_Free(conflist[i].certPrefix); 1.651 + PORT_Free(conflist[i].keyPrefix); 1.652 + } 1.653 + PORT_Free(conflist); 1.654 +} 1.655 + 1.656 +void 1.657 +secmod_FreeChildren(char **children, CK_SLOT_ID *ids) 1.658 +{ 1.659 + char **thisChild; 1.660 + 1.661 + if (!children) { 1.662 + return; 1.663 + } 1.664 + 1.665 + for (thisChild = children; thisChild && *thisChild; thisChild++ ) { 1.666 + PORT_Free(*thisChild); 1.667 + } 1.668 + PORT_Free(children); 1.669 + if (ids) { 1.670 + PORT_Free(ids); 1.671 + } 1.672 + return; 1.673 +} 1.674 + 1.675 +/* 1.676 + * caclulate the length of each child record: 1.677 + * " 0x{id}=<{escaped_child}>" 1.678 + */ 1.679 +static int 1.680 +secmod_getChildLength(char *child, CK_SLOT_ID id) 1.681 +{ 1.682 + int length = NSSUTIL_DoubleEscapeSize(child, '>', ']'); 1.683 + if (id == 0) { 1.684 + length++; 1.685 + } 1.686 + while (id) { 1.687 + length++; 1.688 + id = id >> 4; 1.689 + } 1.690 + length += 6; /* {sp}0x[id]=<{child}> */ 1.691 + return length; 1.692 +} 1.693 + 1.694 +/* 1.695 + * Build a child record: 1.696 + * " 0x{id}=<{escaped_child}>" 1.697 + */ 1.698 +static SECStatus 1.699 +secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id) 1.700 +{ 1.701 + int len; 1.702 + char *escSpec; 1.703 + 1.704 + len = PR_snprintf(*next, *length, " 0x%x=<",id); 1.705 + if (len < 0) { 1.706 + return SECFailure; 1.707 + } 1.708 + *next += len; 1.709 + *length -= len; 1.710 + escSpec = NSSUTIL_DoubleEscape(child, '>', ']'); 1.711 + if (escSpec == NULL) { 1.712 + return SECFailure; 1.713 + } 1.714 + if (*child && (*escSpec == 0)) { 1.715 + PORT_Free(escSpec); 1.716 + return SECFailure; 1.717 + } 1.718 + len = strlen(escSpec); 1.719 + if (len+1 > *length) { 1.720 + PORT_Free(escSpec); 1.721 + return SECFailure; 1.722 + } 1.723 + PORT_Memcpy(*next,escSpec, len); 1.724 + *next += len; 1.725 + *length -= len; 1.726 + PORT_Free(escSpec); 1.727 + **next = '>'; 1.728 + (*next)++; 1.729 + (*length)--; 1.730 + return SECSuccess; 1.731 +} 1.732 + 1.733 +#define TOKEN_STRING " tokens=[" 1.734 + 1.735 +char * 1.736 +secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken, 1.737 + CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids) 1.738 +{ 1.739 + char *rawParam = NULL; /* oldParam with tokens stripped off */ 1.740 + char *newParam = NULL; /* space for the return parameter */ 1.741 + char *nextParam = NULL; /* current end of the new parameter */ 1.742 + char **oldChildren = NULL; 1.743 + CK_SLOT_ID *oldIds = NULL; 1.744 + void *mark = NULL; /* mark the arena pool in case we need 1.745 + * to release it */ 1.746 + int length, i, tmpLen; 1.747 + SECStatus rv; 1.748 + 1.749 + /* first strip out and save the old tokenlist */ 1.750 + rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE,PR_FALSE, 1.751 + oldParam,&oldChildren,&oldIds); 1.752 + if (!rawParam) { 1.753 + goto loser; 1.754 + } 1.755 + 1.756 + /* now calculate the total length of the new buffer */ 1.757 + /* First the 'fixed stuff', length of rawparam (does not include a NULL), 1.758 + * length of the token string (does include the NULL), closing bracket */ 1.759 + length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1; 1.760 + /* now add then length of all the old children */ 1.761 + for (i=0; oldChildren && oldChildren[i]; i++) { 1.762 + length += secmod_getChildLength(oldChildren[i], oldIds[i]); 1.763 + } 1.764 + 1.765 + /* add the new token */ 1.766 + length += secmod_getChildLength(newToken, newID); 1.767 + 1.768 + /* and it's new children */ 1.769 + for (i=0; children && children[i]; i++) { 1.770 + if (ids[i] == -1) { 1.771 + continue; 1.772 + } 1.773 + length += secmod_getChildLength(children[i], ids[i]); 1.774 + } 1.775 + 1.776 + /* now allocate and build the string */ 1.777 + mark = PORT_ArenaMark(arena); 1.778 + if (!mark) { 1.779 + goto loser; 1.780 + } 1.781 + newParam = PORT_ArenaAlloc(arena,length); 1.782 + if (!newParam) { 1.783 + goto loser; 1.784 + } 1.785 + 1.786 + PORT_Strcpy(newParam, oldParam); 1.787 + tmpLen = strlen(oldParam); 1.788 + nextParam = newParam + tmpLen; 1.789 + length -= tmpLen; 1.790 + PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING)-1); 1.791 + nextParam += sizeof(TOKEN_STRING)-1; 1.792 + length -= sizeof(TOKEN_STRING)-1; 1.793 + 1.794 + for (i=0; oldChildren && oldChildren[i]; i++) { 1.795 + rv = secmod_mkTokenChild(&nextParam,&length,oldChildren[i],oldIds[i]); 1.796 + if (rv != SECSuccess) { 1.797 + goto loser; 1.798 + } 1.799 + } 1.800 + 1.801 + rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID); 1.802 + if (rv != SECSuccess) { 1.803 + goto loser; 1.804 + } 1.805 + 1.806 + for (i=0; children && children[i]; i++) { 1.807 + if (ids[i] == -1) { 1.808 + continue; 1.809 + } 1.810 + rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]); 1.811 + if (rv != SECSuccess) { 1.812 + goto loser; 1.813 + } 1.814 + } 1.815 + 1.816 + if (length < 2) { 1.817 + goto loser; 1.818 + } 1.819 + 1.820 + *nextParam++ = ']'; 1.821 + *nextParam++ = 0; 1.822 + 1.823 + /* we are going to return newParam now, don't release the mark */ 1.824 + PORT_ArenaUnmark(arena, mark); 1.825 + mark = NULL; 1.826 + 1.827 +loser: 1.828 + if (mark) { 1.829 + PORT_ArenaRelease(arena, mark); 1.830 + newParam = NULL; /* if the mark is still active, 1.831 + * don't return the param */ 1.832 + } 1.833 + if (rawParam) { 1.834 + PORT_Free(rawParam); 1.835 + } 1.836 + if (oldChildren) { 1.837 + secmod_FreeChildren(oldChildren, oldIds); 1.838 + } 1.839 + return newParam; 1.840 +} 1.841 + 1.842 +static char * 1.843 +secmod_mkModuleSpec(SECMODModule * module) 1.844 +{ 1.845 + char *nss = NULL, *modSpec = NULL, **slotStrings = NULL; 1.846 + int slotCount, i, si; 1.847 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.848 + 1.849 + /* allocate target slot info strings */ 1.850 + slotCount = 0; 1.851 + 1.852 + SECMOD_GetReadLock(moduleLock); 1.853 + if (module->slotCount) { 1.854 + for (i=0; i < module->slotCount; i++) { 1.855 + if (module->slots[i]->defaultFlags !=0) { 1.856 + slotCount++; 1.857 + } 1.858 + } 1.859 + } else { 1.860 + slotCount = module->slotInfoCount; 1.861 + } 1.862 + 1.863 + slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *)); 1.864 + if (slotStrings == NULL) { 1.865 + SECMOD_ReleaseReadLock(moduleLock); 1.866 + goto loser; 1.867 + } 1.868 + 1.869 + 1.870 + /* build the slot info strings */ 1.871 + if (module->slotCount) { 1.872 + for (i=0, si= 0; i < module->slotCount; i++) { 1.873 + if (module->slots[i]->defaultFlags) { 1.874 + PORT_Assert(si < slotCount); 1.875 + if (si >= slotCount) break; 1.876 + slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID, 1.877 + module->slots[i]->defaultFlags, 1.878 + module->slots[i]->timeout, 1.879 + module->slots[i]->askpw, 1.880 + module->slots[i]->hasRootCerts, 1.881 + module->slots[i]->hasRootTrust); 1.882 + si++; 1.883 + } 1.884 + } 1.885 + } else { 1.886 + for (i=0; i < slotCount; i++) { 1.887 + slotStrings[i] = NSSUTIL_MkSlotString( 1.888 + module->slotInfo[i].slotID, 1.889 + module->slotInfo[i].defaultFlags, 1.890 + module->slotInfo[i].timeout, 1.891 + module->slotInfo[i].askpw, 1.892 + module->slotInfo[i].hasRootCerts, 1.893 + module->slotInfo[i].hasRootTrust); 1.894 + } 1.895 + } 1.896 + 1.897 + SECMOD_ReleaseReadLock(moduleLock); 1.898 + nss = NSSUTIL_MkNSSString(slotStrings,slotCount,module->internal, 1.899 + module->isFIPS, module->isModuleDB, 1.900 + module->moduleDBOnly, module->isCritical, 1.901 + module->trustOrder, module->cipherOrder, 1.902 + module->ssl[0],module->ssl[1]); 1.903 + modSpec= NSSUTIL_MkModuleSpec(module->dllName,module->commonName, 1.904 + module->libraryParams,nss); 1.905 + PORT_Free(slotStrings); 1.906 + PR_smprintf_free(nss); 1.907 +loser: 1.908 + return (modSpec); 1.909 +} 1.910 + 1.911 + 1.912 +char ** 1.913 +SECMOD_GetModuleSpecList(SECMODModule *module) 1.914 +{ 1.915 + SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; 1.916 + if (func) { 1.917 + return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, 1.918 + module->libraryParams,NULL); 1.919 + } 1.920 + return NULL; 1.921 +} 1.922 + 1.923 +SECStatus 1.924 +SECMOD_AddPermDB(SECMODModule *module) 1.925 +{ 1.926 + SECMODModuleDBFunc func; 1.927 + char *moduleSpec; 1.928 + char **retString; 1.929 + 1.930 + if (module->parent == NULL) return SECFailure; 1.931 + 1.932 + func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; 1.933 + if (func) { 1.934 + moduleSpec = secmod_mkModuleSpec(module); 1.935 + retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD, 1.936 + module->parent->libraryParams,moduleSpec); 1.937 + PORT_Free(moduleSpec); 1.938 + if (retString != NULL) return SECSuccess; 1.939 + } 1.940 + return SECFailure; 1.941 +} 1.942 + 1.943 +SECStatus 1.944 +SECMOD_DeletePermDB(SECMODModule *module) 1.945 +{ 1.946 + SECMODModuleDBFunc func; 1.947 + char *moduleSpec; 1.948 + char **retString; 1.949 + 1.950 + if (module->parent == NULL) return SECFailure; 1.951 + 1.952 + func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; 1.953 + if (func) { 1.954 + moduleSpec = secmod_mkModuleSpec(module); 1.955 + retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL, 1.956 + module->parent->libraryParams,moduleSpec); 1.957 + PORT_Free(moduleSpec); 1.958 + if (retString != NULL) return SECSuccess; 1.959 + } 1.960 + return SECFailure; 1.961 +} 1.962 + 1.963 +SECStatus 1.964 +SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList) 1.965 +{ 1.966 + SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; 1.967 + char **retString; 1.968 + if (func) { 1.969 + retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE, 1.970 + module->libraryParams,moduleSpecList); 1.971 + if (retString != NULL) return SECSuccess; 1.972 + } 1.973 + return SECFailure; 1.974 +} 1.975 + 1.976 +/* 1.977 + * load a PKCS#11 module but do not add it to the default NSS trust domain 1.978 + */ 1.979 +SECMODModule * 1.980 +SECMOD_LoadModule(char *modulespec,SECMODModule *parent, PRBool recurse) 1.981 +{ 1.982 + char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL; 1.983 + SECStatus status; 1.984 + SECMODModule *module = NULL; 1.985 + SECMODModule *oldModule = NULL; 1.986 + SECStatus rv; 1.987 + 1.988 + /* initialize the underlying module structures */ 1.989 + SECMOD_Init(); 1.990 + 1.991 + status = NSSUTIL_ArgParseModuleSpec(modulespec, &library, &moduleName, 1.992 + ¶meters, &nss); 1.993 + if (status != SECSuccess) { 1.994 + goto loser; 1.995 + } 1.996 + 1.997 + module = SECMOD_CreateModule(library, moduleName, parameters, nss); 1.998 + if (library) PORT_Free(library); 1.999 + if (moduleName) PORT_Free(moduleName); 1.1000 + if (parameters) PORT_Free(parameters); 1.1001 + if (nss) PORT_Free(nss); 1.1002 + if (!module) { 1.1003 + goto loser; 1.1004 + } 1.1005 + if (parent) { 1.1006 + module->parent = SECMOD_ReferenceModule(parent); 1.1007 + if (module->internal && secmod_IsInternalKeySlot(parent)) { 1.1008 + module->internal = parent->internal; 1.1009 + } 1.1010 + } 1.1011 + 1.1012 + /* load it */ 1.1013 + rv = secmod_LoadPKCS11Module(module, &oldModule); 1.1014 + if (rv != SECSuccess) { 1.1015 + goto loser; 1.1016 + } 1.1017 + 1.1018 + /* if we just reload an old module, no need to add it to any lists. 1.1019 + * we simple release all our references */ 1.1020 + if (oldModule) { 1.1021 + /* This module already exists, don't link it anywhere. This 1.1022 + * will probably destroy this module */ 1.1023 + SECMOD_DestroyModule(module); 1.1024 + return oldModule; 1.1025 + } 1.1026 + 1.1027 + if (recurse && module->isModuleDB) { 1.1028 + char ** moduleSpecList; 1.1029 + PORT_SetError(0); 1.1030 + 1.1031 + moduleSpecList = SECMOD_GetModuleSpecList(module); 1.1032 + if (moduleSpecList) { 1.1033 + char **index; 1.1034 + 1.1035 + index = moduleSpecList; 1.1036 + if (*index && SECMOD_GetSkipFirstFlag(module)) { 1.1037 + index++; 1.1038 + } 1.1039 + 1.1040 + for (; *index; index++) { 1.1041 + SECMODModule *child; 1.1042 + if (0 == PORT_Strcmp(*index, modulespec)) { 1.1043 + /* avoid trivial infinite recursion */ 1.1044 + PORT_SetError(SEC_ERROR_NO_MODULE); 1.1045 + rv = SECFailure; 1.1046 + break; 1.1047 + } 1.1048 + child = SECMOD_LoadModule(*index,module,PR_TRUE); 1.1049 + if (!child) break; 1.1050 + if (child->isCritical && !child->loaded) { 1.1051 + int err = PORT_GetError(); 1.1052 + if (!err) 1.1053 + err = SEC_ERROR_NO_MODULE; 1.1054 + SECMOD_DestroyModule(child); 1.1055 + PORT_SetError(err); 1.1056 + rv = SECFailure; 1.1057 + break; 1.1058 + } 1.1059 + SECMOD_DestroyModule(child); 1.1060 + } 1.1061 + SECMOD_FreeModuleSpecList(module,moduleSpecList); 1.1062 + } else { 1.1063 + if (!PORT_GetError()) 1.1064 + PORT_SetError(SEC_ERROR_NO_MODULE); 1.1065 + rv = SECFailure; 1.1066 + } 1.1067 + } 1.1068 + 1.1069 + if (rv != SECSuccess) { 1.1070 + goto loser; 1.1071 + } 1.1072 + 1.1073 + 1.1074 + /* inherit the reference */ 1.1075 + if (!module->moduleDBOnly) { 1.1076 + SECMOD_AddModuleToList(module); 1.1077 + } else { 1.1078 + SECMOD_AddModuleToDBOnlyList(module); 1.1079 + } 1.1080 + 1.1081 + /* handle any additional work here */ 1.1082 + return module; 1.1083 + 1.1084 +loser: 1.1085 + if (module) { 1.1086 + if (module->loaded) { 1.1087 + SECMOD_UnloadModule(module); 1.1088 + } 1.1089 + SECMOD_AddModuleToUnloadList(module); 1.1090 + } 1.1091 + return module; 1.1092 +} 1.1093 + 1.1094 +/* 1.1095 + * load a PKCS#11 module and add it to the default NSS trust domain 1.1096 + */ 1.1097 +SECMODModule * 1.1098 +SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse) 1.1099 +{ 1.1100 + SECStatus rv = SECSuccess; 1.1101 + SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse); 1.1102 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.1103 + 1.1104 + if (newmod) { 1.1105 + SECMOD_GetReadLock(moduleLock); 1.1106 + rv = STAN_AddModuleToDefaultTrustDomain(newmod); 1.1107 + SECMOD_ReleaseReadLock(moduleLock); 1.1108 + if (SECSuccess != rv) { 1.1109 + SECMOD_DestroyModule(newmod); 1.1110 + return NULL; 1.1111 + } 1.1112 + } 1.1113 + return newmod; 1.1114 +} 1.1115 + 1.1116 +/* 1.1117 + * remove the PKCS#11 module from the default NSS trust domain, call 1.1118 + * C_Finalize, and destroy the module structure 1.1119 + */ 1.1120 +SECStatus SECMOD_UnloadUserModule(SECMODModule *mod) 1.1121 +{ 1.1122 + SECStatus rv = SECSuccess; 1.1123 + int atype = 0; 1.1124 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.1125 + if (!mod) { 1.1126 + return SECFailure; 1.1127 + } 1.1128 + 1.1129 + SECMOD_GetReadLock(moduleLock); 1.1130 + rv = STAN_RemoveModuleFromDefaultTrustDomain(mod); 1.1131 + SECMOD_ReleaseReadLock(moduleLock); 1.1132 + if (SECSuccess != rv) { 1.1133 + return SECFailure; 1.1134 + } 1.1135 + return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE); 1.1136 +} 1.1137 +