Index: mozilla/security/nss/lib/pk11wrap/pk11pars.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11pars.c,v retrieving revision 1.21 diff -u -p -r1.21 pk11pars.c --- ./mozilla/security/nss/lib/pk11wrap/pk11pars.c 12 Nov 2005 00:14:25 -0000 1.21 +++ ./mozilla/security/nss/lib/pk11wrap/pk11pars.c 1 Sep 2009 21:55:18 -0000 @@ -107,6 +107,41 @@ secmod_NewModule(void) } +/* private flags. */ +/* The meaing of these flags is as follows: + * + * SECMOD_FLAG_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 flags should be set if this + * flag isn't on. + * + * SECMOD_FLAG_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_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_IS_MODULE_DB 0x01 /* must be set if any of the other flags + * are set */ +#define SECMOD_FLAG_SKIP_FIRST 0x02 +#define SECMOD_FLAG_DEFAULT_MODDB 0x04 + /* * for 3.4 we continue to use the old SECMODModule structure */ @@ -137,15 +172,33 @@ SECMOD_CreateModule(const char *library, if (slotParams) PORT_Free(slotParams); /* new field */ mod->trustOrder = secmod_argReadLong("trustOrder",nssc, - SECMOD_DEFAULT_TRUST_ORDER,NULL); + SECMOD_DEFAULT_TRUST_ORDER,NULL); /* new field */ mod->cipherOrder = secmod_argReadLong("cipherOrder",nssc, - SECMOD_DEFAULT_CIPHER_ORDER,NULL); + SECMOD_DEFAULT_CIPHER_ORDER,NULL); /* new field */ mod->isModuleDB = secmod_argHasFlag("flags","moduleDB",nssc); mod->moduleDBOnly = secmod_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_IS_MODULE_DB; + if (secmod_argHasFlag("flags","skipFirst",nssc)) { + flags |= SECMOD_FLAG_SKIP_FIRST; + } + if (secmod_argHasFlag("flags","defaultModDB",nssc)) { + flags |= SECMOD_FLAG_DEFAULT_MODDB; + } + /* additional moduleDB flags could be added here in the future */ + mod->isModuleDB = (PRBool) flags; + } + ciphers = secmod_argGetParamValue("ciphers",nssc); secmod_argSetNewCipherFlags(&mod->ssl[0],ciphers); if (ciphers) PORT_Free(ciphers); @@ -155,6 +208,22 @@ SECMOD_CreateModule(const char *library, return mod; } +PRBool +SECMOD_GetSkipFirstFlag(SECMODModule *mod) +{ + char flags = (char) mod->isModuleDB; + + return (flags & SECMOD_FLAG_SKIP_FIRST) ? PR_TRUE : PR_FALSE; +} + +PRBool +SECMOD_GetDefaultModDBFlag(SECMODModule *mod) +{ + char flags = (char) mod->isModuleDB; + + return (flags & SECMOD_FLAG_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; +} + static char * secmod_mkModuleSpec(SECMODModule * module) { @@ -333,7 +402,12 @@ SECMOD_LoadModule(char *modulespec,SECMO if (moduleSpecList) { char **index; - for (index = moduleSpecList; *index; index++) { + index = moduleSpecList; + if (*index && SECMOD_GetSkipFirstFlag(module)) { + index++; + } + + for (; *index; index++) { SECMODModule *child; child = SECMOD_LoadModule(*index,module,PR_TRUE); if (!child) break; Index: mozilla/security/nss/lib/pk11wrap/pk11util.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11util.c,v retrieving revision 1.55 diff -u -p -r1.55 pk11util.c --- ./mozilla/security/nss/lib/pk11wrap/pk11util.c 30 Jul 2009 00:29:35 -0000 1.55 +++ ./mozilla/security/nss/lib/pk11wrap/pk11util.c 1 Sep 2009 21:55:18 -0000 @@ -179,7 +179,10 @@ SECMOD_AddModuleToList(SECMODModule *new SECStatus SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule) { - if (defaultDBModule == NULL) { + if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) { + SECMOD_DestroyModule(defaultDBModule); + defaultDBModule = SECMOD_ReferenceModule(newModule); + } else if (defaultDBModule == NULL) { defaultDBModule = SECMOD_ReferenceModule(newModule); } return secmod_AddModuleToList(&modulesDB,newModule); Index: mozilla/security/nss/lib/pk11wrap/secmod.h =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/secmod.h,v retrieving revision 1.26 diff -u -p -r1.26 secmod.h --- ./mozilla/security/nss/lib/pk11wrap/secmod.h 17 Dec 2008 06:09:16 -0000 1.26 +++ ./mozilla/security/nss/lib/pk11wrap/secmod.h 1 Sep 2009 21:55:18 -0000 @@ -151,6 +151,10 @@ extern PK11SlotInfo *SECMOD_FindSlot(SEC /* of modType has been installed */ PRBool SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags ); +/* accessors */ +PRBool SECMOD_GetSkipFirstFlag(SECMODModule *mod); +PRBool SECMOD_GetDefaultModDBFlag(SECMODModule *mod); + /* Functions used to convert between internal & public representation * of Mechanism Flags and Cipher Enable Flags */ extern unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags);