Index: mozilla/security/nss/lib/pk11wrap/pk11pars.c |
=================================================================== |
--- mozilla/security/nss/lib/pk11wrap/pk11pars.c (revision 191424) |
+++ mozilla/security/nss/lib/pk11wrap/pk11pars.c (working copy) |
@@ -1,1134 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* |
- * The following handles the loading, unloading and management of |
- * various PCKS #11 modules |
- */ |
- |
-#include <ctype.h> |
-#include "pkcs11.h" |
-#include "seccomon.h" |
-#include "secmod.h" |
-#include "secmodi.h" |
-#include "secmodti.h" |
-#include "pki3hack.h" |
-#include "secerr.h" |
- |
-#include "utilpars.h" |
- |
-/* create a new module */ |
-static SECMODModule * |
-secmod_NewModule(void) |
-{ |
- SECMODModule *newMod; |
- PRArenaPool *arena; |
- |
- |
- /* create an arena in which dllName and commonName can be |
- * allocated. |
- */ |
- arena = PORT_NewArena(512); |
- if (arena == NULL) { |
- return NULL; |
- } |
- |
- newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule)); |
- if (newMod == NULL) { |
- PORT_FreeArena(arena,PR_FALSE); |
- return NULL; |
- } |
- |
- /* |
- * initialize of the fields of the module |
- */ |
- newMod->arena = arena; |
- newMod->internal = PR_FALSE; |
- newMod->loaded = PR_FALSE; |
- newMod->isFIPS = PR_FALSE; |
- newMod->dllName = NULL; |
- newMod->commonName = NULL; |
- newMod->library = NULL; |
- newMod->functionList = NULL; |
- newMod->slotCount = 0; |
- newMod->slots = NULL; |
- newMod->slotInfo = NULL; |
- newMod->slotInfoCount = 0; |
- newMod->refCount = 1; |
- newMod->ssl[0] = 0; |
- newMod->ssl[1] = 0; |
- newMod->libraryParams = NULL; |
- newMod->moduleDBFunc = NULL; |
- newMod->parent = NULL; |
- newMod->isCritical = PR_FALSE; |
- newMod->isModuleDB = PR_FALSE; |
- newMod->moduleDBOnly = PR_FALSE; |
- newMod->trustOrder = 0; |
- newMod->cipherOrder = 0; |
- newMod->evControlMask = 0; |
- newMod->refLock = PZ_NewLock(nssILockRefLock); |
- if (newMod->refLock == NULL) { |
- PORT_FreeArena(arena,PR_FALSE); |
- return NULL; |
- } |
- return newMod; |
- |
-} |
- |
-/* private flags for isModuleDB (field in SECMODModule). */ |
-/* The meaing of these flags is as follows: |
- * |
- * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the |
- * database of other modules to load. Module DBs are loadable modules that |
- * tells NSS which PKCS #11 modules to load and when. These module DBs are |
- * chainable. That is, one module DB can load another one. NSS system init |
- * design takes advantage of this feature. In system NSS, a fixed system |
- * module DB loads the system defined libraries, then chains out to the |
- * traditional module DBs to load any system or user configured modules |
- * (like smart cards). This bit is the same as the already existing meaning |
- * of isModuleDB = PR_TRUE. None of the other module db flags should be set |
- * if this flag isn't on. |
- * |
- * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first |
- * PKCS #11 module presented by a module DB. This allows the OS to load a |
- * softoken from the system module, then ask the existing module DB code to |
- * load the other PKCS #11 modules in that module DB (skipping it's request |
- * to load softoken). This gives the system init finer control over the |
- * configuration of that softoken module. |
- * |
- * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a |
- * different module DB as the 'default' module DB (the one in which |
- * 'Add module' changes will go). Without this flag NSS takes the first |
- * module as the default Module DB, but in system NSS, that first module |
- * is the system module, which is likely read only (at least to the user). |
- * This allows system NSS to delegate those changes to the user's module DB, |
- * preserving the user's ability to load new PKCS #11 modules (which only |
- * affect him), from existing applications like Firefox. |
- */ |
-#define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the |
- *other flags are set */ |
-#define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02 |
-#define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04 |
- |
- |
-/* private flags for internal (field in SECMODModule). */ |
-/* The meaing of these flags is as follows: |
- * |
- * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is |
- * the internal module (that is, softoken). This bit is the same as the |
- * already existing meaning of internal = PR_TRUE. None of the other |
- * internal flags should be set if this flag isn't on. |
- * |
- * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark |
- * a different slot returned byt PK11_GetInternalKeySlot(). The 'primary' |
- * slot defined by this module will be the new internal key slot. |
- */ |
-#define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of |
- *the other flags are set */ |
-#define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02 |
- |
-/* |
- * for 3.4 we continue to use the old SECMODModule structure |
- */ |
-SECMODModule * |
-SECMOD_CreateModule(const char *library, const char *moduleName, |
- const char *parameters, const char *nss) |
-{ |
- SECMODModule *mod = secmod_NewModule(); |
- char *slotParams,*ciphers; |
- /* pk11pars.h still does not have const char * interfaces */ |
- char *nssc = (char *)nss; |
- if (mod == NULL) return NULL; |
- |
- mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : ""); |
- if (library) { |
- mod->dllName = PORT_ArenaStrdup(mod->arena,library); |
- } |
- /* new field */ |
- if (parameters) { |
- mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters); |
- } |
- mod->internal = NSSUTIL_ArgHasFlag("flags","internal",nssc); |
- mod->isFIPS = NSSUTIL_ArgHasFlag("flags","FIPS",nssc); |
- mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc); |
- slotParams = NSSUTIL_ArgGetParamValue("slotParams",nssc); |
- mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams, |
- &mod->slotInfoCount); |
- if (slotParams) PORT_Free(slotParams); |
- /* new field */ |
- mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder",nssc, |
- NSSUTIL_DEFAULT_TRUST_ORDER,NULL); |
- /* new field */ |
- mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder",nssc, |
- NSSUTIL_DEFAULT_CIPHER_ORDER,NULL); |
- /* new field */ |
- mod->isModuleDB = NSSUTIL_ArgHasFlag("flags","moduleDB",nssc); |
- mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags","moduleDBOnly",nssc); |
- if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE; |
- |
- /* we need more bits, but we also want to preserve binary compatibility |
- * so we overload the isModuleDB PRBool with additional flags. |
- * These flags are only valid if mod->isModuleDB is already set. |
- * NOTE: this depends on the fact that PRBool is at least a char on |
- * all platforms. These flags are only valid if moduleDB is set, so |
- * code checking if (mod->isModuleDB) will continue to work correctly. */ |
- if (mod->isModuleDB) { |
- char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB; |
- if (NSSUTIL_ArgHasFlag("flags","skipFirst",nssc)) { |
- flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST; |
- } |
- if (NSSUTIL_ArgHasFlag("flags","defaultModDB",nssc)) { |
- flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB; |
- } |
- /* additional moduleDB flags could be added here in the future */ |
- mod->isModuleDB = (PRBool) flags; |
- } |
- |
- if (mod->internal) { |
- char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL; |
- |
- if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) { |
- flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; |
- } |
- mod->internal = (PRBool) flags; |
- } |
- |
- ciphers = NSSUTIL_ArgGetParamValue("ciphers",nssc); |
- NSSUTIL_ArgParseCipherFlags(&mod->ssl[0],ciphers); |
- if (ciphers) PORT_Free(ciphers); |
- |
- secmod_PrivateModuleCount++; |
- |
- return mod; |
-} |
- |
-PRBool |
-SECMOD_GetSkipFirstFlag(SECMODModule *mod) |
-{ |
- char flags = (char) mod->isModuleDB; |
- |
- return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE; |
-} |
- |
-PRBool |
-SECMOD_GetDefaultModDBFlag(SECMODModule *mod) |
-{ |
- char flags = (char) mod->isModuleDB; |
- |
- return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; |
-} |
- |
-PRBool |
-secmod_IsInternalKeySlot(SECMODModule *mod) |
-{ |
- char flags = (char) mod->internal; |
- |
- return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE; |
-} |
- |
-void |
-secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val) |
-{ |
- char flags = (char) mod->internal; |
- |
- if (val) { |
- flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; |
- } else { |
- flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT; |
- } |
- mod->internal = flags; |
-} |
- |
-/* |
- * copy desc and value into target. Target is known to be big enough to |
- * hold desc +2 +value, which is good because the result of this will be |
- * *desc"*value". We may, however, have to add some escapes for special |
- * characters imbedded into value (rare). This string potentially comes from |
- * a user, so we don't want the user overflowing the target buffer by using |
- * excessive escapes. To prevent this we count the escapes we need to add and |
- * try to expand the buffer with Realloc. |
- */ |
-static char * |
-secmod_doDescCopy(char *target, int *targetLen, const char *desc, |
- int descLen, char *value) |
-{ |
- int diff, esc_len; |
- |
- esc_len = NSSUTIL_EscapeSize(value, '\"') - 1; |
- diff = esc_len - strlen(value); |
- if (diff > 0) { |
- /* we need to escape... expand newSpecPtr as well to make sure |
- * we don't overflow it */ |
- char *newPtr = PORT_Realloc(target, *targetLen * diff); |
- if (!newPtr) { |
- return target; /* not enough space, just drop the whole copy */ |
- } |
- *targetLen += diff; |
- target = newPtr; |
- value = NSSUTIL_Escape(value, '\"'); |
- if (value == NULL) { |
- return target; /* couldn't escape value, just drop the copy */ |
- } |
- } |
- PORT_Memcpy(target, desc, descLen); |
- target += descLen; |
- *target++='\"'; |
- PORT_Memcpy(target, value, esc_len); |
- target += esc_len; |
- *target++='\"'; |
- if (diff > 0) { |
- PORT_Free(value); |
- } |
- return target; |
-} |
- |
-#define SECMOD_SPEC_COPY(new, start, end) \ |
- if (end > start) { \ |
- int _cnt = end - start; \ |
- PORT_Memcpy(new, start, _cnt); \ |
- new += _cnt; \ |
- } |
-#define SECMOD_TOKEN_DESCRIPTION "tokenDescription=" |
-#define SECMOD_SLOT_DESCRIPTION "slotDescription=" |
- |
- |
-/* |
- * Find any tokens= values in the module spec. |
- * Always return a new spec which does not have any tokens= arguments. |
- * If tokens= arguments are found, Split the the various tokens defined into |
- * an array of child specs to return. |
- * |
- * Caller is responsible for freeing the child spec and the new token |
- * spec. |
- */ |
-char * |
-secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS, |
- char *moduleSpec, char ***children, |
- CK_SLOT_ID **ids) |
-{ |
- int newSpecLen = PORT_Strlen(moduleSpec)+2; |
- char *newSpec = PORT_Alloc(newSpecLen); |
- char *newSpecPtr = newSpec; |
- char *modulePrev = moduleSpec; |
- char *target = NULL; |
- char *tmp = NULL; |
- char **childArray = NULL; |
- char *tokenIndex; |
- CK_SLOT_ID *idArray = NULL; |
- int tokenCount = 0; |
- int i; |
- |
- if (newSpec == NULL) { |
- return NULL; |
- } |
- |
- *children = NULL; |
- if (ids) { |
- *ids = NULL; |
- } |
- moduleSpec = NSSUTIL_ArgStrip(moduleSpec); |
- SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); |
- |
- /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening |
- * a new softoken module takes the following parameters to name the |
- * various tokens: |
- * |
- * cryptoTokenDescription: name of the non-fips crypto token. |
- * cryptoSlotDescription: name of the non-fips crypto slot. |
- * dbTokenDescription: name of the non-fips db token. |
- * dbSlotDescription: name of the non-fips db slot. |
- * FIPSTokenDescription: name of the fips db/crypto token. |
- * FIPSSlotDescription: name of the fips db/crypto slot. |
- * |
- * if we are opening a new slot, we need to have the following |
- * parameters: |
- * tokenDescription: name of the token. |
- * slotDescription: name of the slot. |
- * |
- * |
- * The convert flag tells us to drop the unnecessary *TokenDescription |
- * and *SlotDescription arguments and convert the appropriate pair |
- * (either db or FIPS based on the isFIPS flag) to tokenDescription and |
- * slotDescription). |
- */ |
- /* |
- * walk down the list. if we find a tokens= argument, save it, |
- * otherise copy the argument. |
- */ |
- while (*moduleSpec) { |
- int next; |
- modulePrev = moduleSpec; |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=", |
- modulePrev = moduleSpec; /* skip copying */ ) |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoTokenDescription=", |
- if (convert) { modulePrev = moduleSpec; } ); |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoSlotDescription=", |
- if (convert) { modulePrev = moduleSpec; } ); |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbTokenDescription=", |
- if (convert) { |
- modulePrev = moduleSpec; |
- if (!isFIPS) { |
- newSpecPtr = secmod_doDescCopy(newSpecPtr, |
- &newSpecLen, SECMOD_TOKEN_DESCRIPTION, |
- sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); |
- } |
- }); |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbSlotDescription=", |
- if (convert) { |
- modulePrev = moduleSpec; /* skip copying */ |
- if (!isFIPS) { |
- newSpecPtr = secmod_doDescCopy(newSpecPtr, |
- &newSpecLen, SECMOD_SLOT_DESCRIPTION, |
- sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); |
- } |
- } ); |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSTokenDescription=", |
- if (convert) { |
- modulePrev = moduleSpec; /* skip copying */ |
- if (isFIPS) { |
- newSpecPtr = secmod_doDescCopy(newSpecPtr, |
- &newSpecLen, SECMOD_TOKEN_DESCRIPTION, |
- sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp); |
- } |
- } ); |
- NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSSlotDescription=", |
- if (convert) { |
- modulePrev = moduleSpec; /* skip copying */ |
- if (isFIPS) { |
- newSpecPtr = secmod_doDescCopy(newSpecPtr, |
- &newSpecLen, SECMOD_SLOT_DESCRIPTION, |
- sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp); |
- } |
- } ); |
- NSSUTIL_HANDLE_FINAL_ARG(moduleSpec) |
- SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); |
- } |
- if (tmp) { |
- PORT_Free(tmp); |
- tmp = NULL; |
- } |
- *newSpecPtr = 0; |
- |
- /* no target found, return the newSpec */ |
- if (target == NULL) { |
- return newSpec; |
- } |
- |
- /* now build the child array from target */ |
- /*first count them */ |
- for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex; |
- tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) { |
- tokenCount++; |
- } |
- |
- childArray = PORT_NewArray(char *, tokenCount+1); |
- if (childArray == NULL) { |
- /* just return the spec as is then */ |
- PORT_Free(target); |
- return newSpec; |
- } |
- if (ids) { |
- idArray = PORT_NewArray(CK_SLOT_ID, tokenCount+1); |
- if (idArray == NULL) { |
- PORT_Free(childArray); |
- PORT_Free(target); |
- return newSpec; |
- } |
- } |
- |
- /* now fill them in */ |
- for (tokenIndex = NSSUTIL_ArgStrip(target), i=0 ; |
- *tokenIndex && (i < tokenCount); |
- tokenIndex=NSSUTIL_ArgStrip(tokenIndex)) { |
- int next; |
- char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next); |
- tokenIndex += next; |
- |
- if (idArray) { |
- idArray[i] = NSSUTIL_ArgDecodeNumber(name); |
- } |
- |
- PORT_Free(name); /* drop the explicit number */ |
- |
- /* if anything is left, copy the args to the child array */ |
- if (!NSSUTIL_ArgIsBlank(*tokenIndex)) { |
- childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next); |
- tokenIndex += next; |
- } |
- } |
- |
- PORT_Free(target); |
- childArray[i] = 0; |
- if (idArray) { |
- idArray[i] = 0; |
- } |
- |
- /* return it */ |
- *children = childArray; |
- if (ids) { |
- *ids = idArray; |
- } |
- return newSpec; |
-} |
- |
-/* get the database and flags from the spec */ |
-static char * |
-secmod_getConfigDir(char *spec, char **certPrefix, char **keyPrefix, |
- PRBool *readOnly) |
-{ |
- char * config = NULL; |
- |
- *certPrefix = NULL; |
- *keyPrefix = NULL; |
- *readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",spec); |
- |
- spec = NSSUTIL_ArgStrip(spec); |
- while (*spec) { |
- int next; |
- NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;) |
- NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;) |
- NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;) |
- NSSUTIL_HANDLE_FINAL_ARG(spec) |
- } |
- return config; |
-} |
- |
-struct SECMODConfigListStr { |
- char *config; |
- char *certPrefix; |
- char *keyPrefix; |
- PRBool isReadOnly; |
-}; |
- |
-/* |
- * return an array of already openned databases from a spec list. |
- */ |
-SECMODConfigList * |
-secmod_GetConfigList(PRBool isFIPS, char *spec, int *count) |
-{ |
- char **children; |
- CK_SLOT_ID *ids; |
- char *strippedSpec; |
- int childCount; |
- SECMODConfigList *conflist = NULL; |
- int i; |
- |
- strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS, |
- spec,&children,&ids); |
- if (strippedSpec == NULL) { |
- return NULL; |
- } |
- |
- for (childCount=0; children && children[childCount]; childCount++) ; |
- *count = childCount+1; /* include strippedSpec */ |
- conflist = PORT_NewArray(SECMODConfigList,*count); |
- if (conflist == NULL) { |
- *count = 0; |
- goto loser; |
- } |
- |
- conflist[0].config = secmod_getConfigDir(strippedSpec, |
- &conflist[0].certPrefix, |
- &conflist[0].keyPrefix, |
- &conflist[0].isReadOnly); |
- for (i=0; i < childCount; i++) { |
- conflist[i+1].config = secmod_getConfigDir(children[i], |
- &conflist[i+1].certPrefix, |
- &conflist[i+1].keyPrefix, |
- &conflist[i+1].isReadOnly); |
- } |
- |
-loser: |
- secmod_FreeChildren(children, ids); |
- PORT_Free(strippedSpec); |
- return conflist; |
-} |
- |
-/* |
- * determine if we are trying to open an old dbm database. For this test |
- * RDB databases should return PR_FALSE. |
- */ |
-static PRBool |
-secmod_configIsDBM(char *configDir) |
-{ |
- char *env; |
- |
- /* explicit dbm open */ |
- if (strncmp(configDir, "dbm:", 4) == 0) { |
- return PR_TRUE; |
- } |
- /* explicit open of a non-dbm database */ |
- if ((strncmp(configDir, "sql:",4) == 0) |
- || (strncmp(configDir, "rdb:", 4) == 0) |
- || (strncmp(configDir, "extern:", 7) == 0)) { |
- return PR_FALSE; |
- } |
- env = PR_GetEnv("NSS_DEFAULT_DB_TYPE"); |
- /* implicit dbm open */ |
- if ((env == NULL) || (strcmp(env,"dbm") == 0)) { |
- return PR_TRUE; |
- } |
- /* implicit non-dbm open */ |
- return PR_FALSE; |
-} |
- |
-/* |
- * match two prefixes. prefix may be NULL. NULL patches '\0' |
- */ |
-static PRBool |
-secmod_matchPrefix(char *prefix1, char *prefix2) |
-{ |
- if ((prefix1 == NULL) || (*prefix1 == 0)) { |
- if ((prefix2 == NULL) || (*prefix2 == 0)) { |
- return PR_TRUE; |
- } |
- return PR_FALSE; |
- } |
- if (strcmp(prefix1, prefix2) == 0) { |
- return PR_TRUE; |
- } |
- return PR_FALSE; |
-} |
- |
-/* |
- * return true if we are requesting a database that is already openned. |
- */ |
-PRBool |
-secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count) |
-{ |
- char *config; |
- char *certPrefix; |
- char *keyPrefix; |
- PRBool isReadOnly; |
- PRBool ret=PR_FALSE; |
- int i; |
- |
- config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly); |
- if (!config) { |
- ret=PR_TRUE; |
- goto done; |
- } |
- |
- /* NOTE: we dbm isn't multiple open safe. If we open the same database |
- * twice from two different locations, then we can corrupt our database |
- * (the cache will be inconsistent). Protect against this by claiming |
- * for comparison only that we are always openning dbm databases read only. |
- */ |
- if (secmod_configIsDBM(config)) { |
- isReadOnly = 1; |
- } |
- for (i=0; i < count; i++) { |
- if ((strcmp(config,conflist[i].config) == 0) && |
- secmod_matchPrefix(certPrefix, conflist[i].certPrefix) && |
- secmod_matchPrefix(keyPrefix, conflist[i].keyPrefix) && |
- /* this last test -- if we just need the DB open read only, |
- * than any open will suffice, but if we requested it read/write |
- * and it's only open read only, we need to open it again */ |
- (isReadOnly || !conflist[i].isReadOnly)) { |
- ret = PR_TRUE; |
- goto done; |
- } |
- } |
- |
- ret = PR_FALSE; |
-done: |
- PORT_Free(config); |
- PORT_Free(certPrefix); |
- PORT_Free(keyPrefix); |
- return ret; |
-} |
- |
-void |
-secmod_FreeConfigList(SECMODConfigList *conflist, int count) |
-{ |
- int i; |
- for (i=0; i < count; i++) { |
- PORT_Free(conflist[i].config); |
- PORT_Free(conflist[i].certPrefix); |
- PORT_Free(conflist[i].keyPrefix); |
- } |
- PORT_Free(conflist); |
-} |
- |
-void |
-secmod_FreeChildren(char **children, CK_SLOT_ID *ids) |
-{ |
- char **thisChild; |
- |
- if (!children) { |
- return; |
- } |
- |
- for (thisChild = children; thisChild && *thisChild; thisChild++ ) { |
- PORT_Free(*thisChild); |
- } |
- PORT_Free(children); |
- if (ids) { |
- PORT_Free(ids); |
- } |
- return; |
-} |
- |
-/* |
- * caclulate the length of each child record: |
- * " 0x{id}=<{escaped_child}>" |
- */ |
-static int |
-secmod_getChildLength(char *child, CK_SLOT_ID id) |
-{ |
- int length = NSSUTIL_DoubleEscapeSize(child, '>', ']'); |
- if (id == 0) { |
- length++; |
- } |
- while (id) { |
- length++; |
- id = id >> 4; |
- } |
- length += 6; /* {sp}0x[id]=<{child}> */ |
- return length; |
-} |
- |
-/* |
- * Build a child record: |
- * " 0x{id}=<{escaped_child}>" |
- */ |
-static SECStatus |
-secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id) |
-{ |
- int len; |
- char *escSpec; |
- |
- len = PR_snprintf(*next, *length, " 0x%x=<",id); |
- if (len < 0) { |
- return SECFailure; |
- } |
- *next += len; |
- *length -= len; |
- escSpec = NSSUTIL_DoubleEscape(child, '>', ']'); |
- if (escSpec == NULL) { |
- return SECFailure; |
- } |
- if (*child && (*escSpec == 0)) { |
- PORT_Free(escSpec); |
- return SECFailure; |
- } |
- len = strlen(escSpec); |
- if (len+1 > *length) { |
- PORT_Free(escSpec); |
- return SECFailure; |
- } |
- PORT_Memcpy(*next,escSpec, len); |
- *next += len; |
- *length -= len; |
- PORT_Free(escSpec); |
- **next = '>'; |
- (*next)++; |
- (*length)--; |
- return SECSuccess; |
-} |
- |
-#define TOKEN_STRING " tokens=[" |
- |
-char * |
-secmod_MkAppendTokensList(PRArenaPool *arena, char *oldParam, char *newToken, |
- CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids) |
-{ |
- char *rawParam = NULL; /* oldParam with tokens stripped off */ |
- char *newParam = NULL; /* space for the return parameter */ |
- char *nextParam = NULL; /* current end of the new parameter */ |
- char **oldChildren = NULL; |
- CK_SLOT_ID *oldIds = NULL; |
- void *mark = NULL; /* mark the arena pool in case we need |
- * to release it */ |
- int length, i, tmpLen; |
- SECStatus rv; |
- |
- /* first strip out and save the old tokenlist */ |
- rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE,PR_FALSE, |
- oldParam,&oldChildren,&oldIds); |
- if (!rawParam) { |
- goto loser; |
- } |
- |
- /* now calculate the total length of the new buffer */ |
- /* First the 'fixed stuff', length of rawparam (does not include a NULL), |
- * length of the token string (does include the NULL), closing bracket */ |
- length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1; |
- /* now add then length of all the old children */ |
- for (i=0; oldChildren && oldChildren[i]; i++) { |
- length += secmod_getChildLength(oldChildren[i], oldIds[i]); |
- } |
- |
- /* add the new token */ |
- length += secmod_getChildLength(newToken, newID); |
- |
- /* and it's new children */ |
- for (i=0; children && children[i]; i++) { |
- if (ids[i] == -1) { |
- continue; |
- } |
- length += secmod_getChildLength(children[i], ids[i]); |
- } |
- |
- /* now allocate and build the string */ |
- mark = PORT_ArenaMark(arena); |
- if (!mark) { |
- goto loser; |
- } |
- newParam = PORT_ArenaAlloc(arena,length); |
- if (!newParam) { |
- goto loser; |
- } |
- |
- PORT_Strcpy(newParam, oldParam); |
- tmpLen = strlen(oldParam); |
- nextParam = newParam + tmpLen; |
- length -= tmpLen; |
- PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING)-1); |
- nextParam += sizeof(TOKEN_STRING)-1; |
- length -= sizeof(TOKEN_STRING)-1; |
- |
- for (i=0; oldChildren && oldChildren[i]; i++) { |
- rv = secmod_mkTokenChild(&nextParam,&length,oldChildren[i],oldIds[i]); |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- } |
- |
- rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID); |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- |
- for (i=0; children && children[i]; i++) { |
- if (ids[i] == -1) { |
- continue; |
- } |
- rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]); |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- } |
- |
- if (length < 2) { |
- goto loser; |
- } |
- |
- *nextParam++ = ']'; |
- *nextParam++ = 0; |
- |
- /* we are going to return newParam now, don't release the mark */ |
- PORT_ArenaUnmark(arena, mark); |
- mark = NULL; |
- |
-loser: |
- if (mark) { |
- PORT_ArenaRelease(arena, mark); |
- newParam = NULL; /* if the mark is still active, |
- * don't return the param */ |
- } |
- if (rawParam) { |
- PORT_Free(rawParam); |
- } |
- if (oldChildren) { |
- secmod_FreeChildren(oldChildren, oldIds); |
- } |
- return newParam; |
-} |
- |
-static char * |
-secmod_mkModuleSpec(SECMODModule * module) |
-{ |
- char *nss = NULL, *modSpec = NULL, **slotStrings = NULL; |
- int slotCount, i, si; |
- SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); |
- |
- /* allocate target slot info strings */ |
- slotCount = 0; |
- |
- SECMOD_GetReadLock(moduleLock); |
- if (module->slotCount) { |
- for (i=0; i < module->slotCount; i++) { |
- if (module->slots[i]->defaultFlags !=0) { |
- slotCount++; |
- } |
- } |
- } else { |
- slotCount = module->slotInfoCount; |
- } |
- |
- slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *)); |
- if (slotStrings == NULL) { |
- SECMOD_ReleaseReadLock(moduleLock); |
- goto loser; |
- } |
- |
- |
- /* build the slot info strings */ |
- if (module->slotCount) { |
- for (i=0, si= 0; i < module->slotCount; i++) { |
- if (module->slots[i]->defaultFlags) { |
- PORT_Assert(si < slotCount); |
- if (si >= slotCount) break; |
- slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID, |
- module->slots[i]->defaultFlags, |
- module->slots[i]->timeout, |
- module->slots[i]->askpw, |
- module->slots[i]->hasRootCerts, |
- module->slots[i]->hasRootTrust); |
- si++; |
- } |
- } |
- } else { |
- for (i=0; i < slotCount; i++) { |
- slotStrings[i] = NSSUTIL_MkSlotString( |
- module->slotInfo[i].slotID, |
- module->slotInfo[i].defaultFlags, |
- module->slotInfo[i].timeout, |
- module->slotInfo[i].askpw, |
- module->slotInfo[i].hasRootCerts, |
- module->slotInfo[i].hasRootTrust); |
- } |
- } |
- |
- SECMOD_ReleaseReadLock(moduleLock); |
- nss = NSSUTIL_MkNSSString(slotStrings,slotCount,module->internal, |
- module->isFIPS, module->isModuleDB, |
- module->moduleDBOnly, module->isCritical, |
- module->trustOrder, module->cipherOrder, |
- module->ssl[0],module->ssl[1]); |
- modSpec= NSSUTIL_MkModuleSpec(module->dllName,module->commonName, |
- module->libraryParams,nss); |
- PORT_Free(slotStrings); |
- PR_smprintf_free(nss); |
-loser: |
- return (modSpec); |
-} |
- |
- |
-char ** |
-SECMOD_GetModuleSpecList(SECMODModule *module) |
-{ |
- SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; |
- if (func) { |
- return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, |
- module->libraryParams,NULL); |
- } |
- return NULL; |
-} |
- |
-SECStatus |
-SECMOD_AddPermDB(SECMODModule *module) |
-{ |
- SECMODModuleDBFunc func; |
- char *moduleSpec; |
- char **retString; |
- |
- if (module->parent == NULL) return SECFailure; |
- |
- func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; |
- if (func) { |
- moduleSpec = secmod_mkModuleSpec(module); |
- retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD, |
- module->parent->libraryParams,moduleSpec); |
- PORT_Free(moduleSpec); |
- if (retString != NULL) return SECSuccess; |
- } |
- return SECFailure; |
-} |
- |
-SECStatus |
-SECMOD_DeletePermDB(SECMODModule *module) |
-{ |
- SECMODModuleDBFunc func; |
- char *moduleSpec; |
- char **retString; |
- |
- if (module->parent == NULL) return SECFailure; |
- |
- func = (SECMODModuleDBFunc) module->parent->moduleDBFunc; |
- if (func) { |
- moduleSpec = secmod_mkModuleSpec(module); |
- retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL, |
- module->parent->libraryParams,moduleSpec); |
- PORT_Free(moduleSpec); |
- if (retString != NULL) return SECSuccess; |
- } |
- return SECFailure; |
-} |
- |
-SECStatus |
-SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList) |
-{ |
- SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; |
- char **retString; |
- if (func) { |
- retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE, |
- module->libraryParams,moduleSpecList); |
- if (retString != NULL) return SECSuccess; |
- } |
- return SECFailure; |
-} |
- |
-/* |
- * load a PKCS#11 module but do not add it to the default NSS trust domain |
- */ |
-SECMODModule * |
-SECMOD_LoadModule(char *modulespec,SECMODModule *parent, PRBool recurse) |
-{ |
- char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL; |
- SECStatus status; |
- SECMODModule *module = NULL; |
- SECMODModule *oldModule = NULL; |
- SECStatus rv; |
- |
- /* initialize the underlying module structures */ |
- SECMOD_Init(); |
- |
- status = NSSUTIL_ArgParseModuleSpec(modulespec, &library, &moduleName, |
- ¶meters, &nss); |
- if (status != SECSuccess) { |
- goto loser; |
- } |
- |
- module = SECMOD_CreateModule(library, moduleName, parameters, nss); |
- if (library) PORT_Free(library); |
- if (moduleName) PORT_Free(moduleName); |
- if (parameters) PORT_Free(parameters); |
- if (nss) PORT_Free(nss); |
- if (!module) { |
- goto loser; |
- } |
- if (parent) { |
- module->parent = SECMOD_ReferenceModule(parent); |
- if (module->internal && secmod_IsInternalKeySlot(parent)) { |
- module->internal = parent->internal; |
- } |
- } |
- |
- /* load it */ |
- rv = secmod_LoadPKCS11Module(module, &oldModule); |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- |
- /* if we just reload an old module, no need to add it to any lists. |
- * we simple release all our references */ |
- if (oldModule) { |
- /* This module already exists, don't link it anywhere. This |
- * will probably destroy this module */ |
- SECMOD_DestroyModule(module); |
- return oldModule; |
- } |
- |
- if (recurse && module->isModuleDB) { |
- char ** moduleSpecList; |
- PORT_SetError(0); |
- |
- moduleSpecList = SECMOD_GetModuleSpecList(module); |
- if (moduleSpecList) { |
- char **index; |
- |
- index = moduleSpecList; |
- if (*index && SECMOD_GetSkipFirstFlag(module)) { |
- index++; |
- } |
- |
- for (; *index; index++) { |
- SECMODModule *child; |
- if (0 == PORT_Strcmp(*index, modulespec)) { |
- /* avoid trivial infinite recursion */ |
- PORT_SetError(SEC_ERROR_NO_MODULE); |
- rv = SECFailure; |
- break; |
- } |
- child = SECMOD_LoadModule(*index,module,PR_TRUE); |
- if (!child) break; |
- if (child->isCritical && !child->loaded) { |
- int err = PORT_GetError(); |
- if (!err) |
- err = SEC_ERROR_NO_MODULE; |
- SECMOD_DestroyModule(child); |
- PORT_SetError(err); |
- rv = SECFailure; |
- break; |
- } |
- SECMOD_DestroyModule(child); |
- } |
- SECMOD_FreeModuleSpecList(module,moduleSpecList); |
- } else { |
- if (!PORT_GetError()) |
- PORT_SetError(SEC_ERROR_NO_MODULE); |
- rv = SECFailure; |
- } |
- } |
- |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- |
- |
- /* inherit the reference */ |
- if (!module->moduleDBOnly) { |
- SECMOD_AddModuleToList(module); |
- } else { |
- SECMOD_AddModuleToDBOnlyList(module); |
- } |
- |
- /* handle any additional work here */ |
- return module; |
- |
-loser: |
- if (module) { |
- if (module->loaded) { |
- SECMOD_UnloadModule(module); |
- } |
- SECMOD_AddModuleToUnloadList(module); |
- } |
- return module; |
-} |
- |
-/* |
- * load a PKCS#11 module and add it to the default NSS trust domain |
- */ |
-SECMODModule * |
-SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse) |
-{ |
- SECStatus rv = SECSuccess; |
- SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse); |
- SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); |
- |
- if (newmod) { |
- SECMOD_GetReadLock(moduleLock); |
- rv = STAN_AddModuleToDefaultTrustDomain(newmod); |
- SECMOD_ReleaseReadLock(moduleLock); |
- if (SECSuccess != rv) { |
- SECMOD_DestroyModule(newmod); |
- return NULL; |
- } |
- } |
- return newmod; |
-} |
- |
-/* |
- * remove the PKCS#11 module from the default NSS trust domain, call |
- * C_Finalize, and destroy the module structure |
- */ |
-SECStatus SECMOD_UnloadUserModule(SECMODModule *mod) |
-{ |
- SECStatus rv = SECSuccess; |
- int atype = 0; |
- SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); |
- if (!mod) { |
- return SECFailure; |
- } |
- |
- SECMOD_GetReadLock(moduleLock); |
- rv = STAN_RemoveModuleFromDefaultTrustDomain(mod); |
- SECMOD_ReleaseReadLock(moduleLock); |
- if (SECSuccess != rv) { |
- return SECFailure; |
- } |
- return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE); |
-} |
- |