--- ./lib/nss/config.mk.check_policy_file 2016-07-12 09:11:01.198867052 -0700 +++ ./lib/nss/config.mk 2016-07-12 09:15:58.739946540 -0700 @@ -99,8 +99,15 @@ ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) ifndef NS_USE_GCC # Export 'mktemp' to be backward compatible with NSS 3.2.x and 3.3.x # but do not put it in the import library. See bug 142575. DEFINES += -DWIN32_NSS3_DLL_COMPAT DLLFLAGS += -EXPORT:mktemp=nss_mktemp,PRIVATE endif endif + +ifdef POLICY_FILE +ifndef POLICY_PATH +$(error You must define POLICY_PATH if you set POLICY_FILE) +endif +DEFINES += -DPOLICY_FILE=\"$(POLICY_FILE)\" -DPOLICY_PATH=\"$(POLICY_PATH)\" +endif --- ./lib/nss/nssinit.c.check_policy_file 2016-06-20 10:11:28.000000000 -0700 +++ ./lib/nss/nssinit.c 2016-07-12 09:18:14.821671331 -0700 @@ -330,47 +330,47 @@ /* * see nss_Init for definitions of the various options. * * this function builds a moduleSpec string from the options and previously * set statics (from PKCS11_Configure, for instance), and uses it to kick off * the loading of the various PKCS #11 modules. */ -static SECStatus +static SECMODModule * nss_InitModules(const char *configdir, const char *certPrefix, const char *keyPrefix, const char *secmodName, const char *updateDir, const char *updCertPrefix, const char *updKeyPrefix, const char *updateID, const char *updateName, char *configName, char *configStrings, PRBool pwRequired, PRBool readOnly, PRBool noCertDB, PRBool noModDB, PRBool forceOpen, PRBool optimizeSpace, PRBool isContextInit) { - SECStatus rv = SECFailure; + SECMODModule *module = NULL; char *moduleSpec = NULL; char *flags = NULL; char *lconfigdir = NULL; char *lcertPrefix = NULL; char *lkeyPrefix = NULL; char *lsecmodName = NULL; char *lupdateDir = NULL; char *lupdCertPrefix = NULL; char *lupdKeyPrefix = NULL; char *lupdateID = NULL; char *lupdateName = NULL; if (NSS_InitializePRErrorTable() != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); - return rv; + return NULL; } flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen, pwRequired, optimizeSpace); - if (flags == NULL) return rv; + if (flags == NULL) return NULL; /* * configdir is double nested, and Windows uses the same character * for file seps as we use for escapes! (sigh). */ lconfigdir = NSSUTIL_DoubleEscape(configdir, '\'', '\"'); if (lconfigdir == NULL) { goto loser; @@ -427,24 +427,24 @@ if (lsecmodName) PORT_Free(lsecmodName); if (lupdateDir) PORT_Free(lupdateDir); if (lupdCertPrefix) PORT_Free(lupdCertPrefix); if (lupdKeyPrefix) PORT_Free(lupdKeyPrefix); if (lupdateID) PORT_Free(lupdateID); if (lupdateName) PORT_Free(lupdateName); if (moduleSpec) { - SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE); + module = SECMOD_LoadModule(moduleSpec, NULL, PR_TRUE); PR_smprintf_free(moduleSpec); - if (module) { - if (module->loaded) rv=SECSuccess; + if (module && !module->loaded) { SECMOD_DestroyModule(module); + return NULL; } } - return rv; + return module; } /* * OK there are now lots of options here, lets go through them all: * * configdir - base directory where all the cert, key, and module datbases live. * certPrefix - prefix added to the beginning of the cert database example: " * "https-server1-" @@ -509,41 +509,44 @@ return PR_FAILURE; } return PR_SUCCESS; } static SECStatus nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, - const char *secmodName, const char *updateDir, + const char *secmodName, const char *updateDir, const char *updCertPrefix, const char *updKeyPrefix, const char *updateID, const char *updateName, NSSInitContext ** initContextPtr, NSSInitParameters *initParams, - PRBool readOnly, PRBool noCertDB, + PRBool readOnly, PRBool noCertDB, PRBool noModDB, PRBool forceOpen, PRBool noRootInit, PRBool optimizeSpace, PRBool noSingleThreadedModules, PRBool allowAlreadyInitializedModules, PRBool dontFinalizeModules) { - SECStatus rv = SECFailure; + SECMODModule *parent = NULL; PKIX_UInt32 actualMinorVersion = 0; PKIX_Error *pkixError = NULL; PRBool isReallyInitted; char *configStrings = NULL; char *configName = NULL; PRBool passwordRequired = PR_FALSE; +#ifdef POLICY_FILE + char *ignoreVar; +#endif /* if we are trying to init with a traditional NSS_Init call, maintain * the traditional idempotent behavior. */ if (!initContextPtr && nssIsInitted) { return SECSuccess; } - + /* make sure our lock and condition variable are initialized one and only * one time */ if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) { return SECFailure; } /* * if we haven't done basic initialization, single thread the @@ -630,23 +633,23 @@ configStrings = pk11_config_strings; configName = pk11_config_name; passwordRequired = pk11_password_required; } /* Skip the module init if we are already initted and we are trying * to init with noCertDB and noModDB */ if (!(isReallyInitted && noCertDB && noModDB)) { - rv = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName, - updateDir, updCertPrefix, updKeyPrefix, updateID, + parent = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName, + updateDir, updCertPrefix, updKeyPrefix, updateID, updateName, configName, configStrings, passwordRequired, - readOnly, noCertDB, noModDB, forceOpen, optimizeSpace, + readOnly, noCertDB, noModDB, forceOpen, optimizeSpace, (initContextPtr != NULL)); - if (rv != SECSuccess) { + if (parent == NULL) { goto loser; } } /* finish up initialization */ if (!isReallyInitted) { if (SECOID_Init() != SECSuccess) { @@ -675,17 +678,40 @@ * path. Skip it */ dbpath = NULL; } if (dbpath) { nss_FindExternalRoot(dbpath, secmodName); } } } - +#ifdef POLICY_FILE + /* Load the system crypto policy file if it exists, + * unless the NSS_IGNORE_SYSTEM_POLICY environment + * variable has been set to 1. */ + ignoreVar = PR_GetEnvSecure("NSS_IGNORE_SYSTEM_POLICY"); + if (ignoreVar == NULL || strncmp(ignoreVar, "1", sizeof("1")) != 0) { + if (PR_Access(POLICY_PATH "/" POLICY_FILE, PR_ACCESS_READ_OK) == PR_SUCCESS) { + SECMODModule *module = SECMOD_LoadModule( + "name=\"Policy File\" " + "parameters=\"configdir='sql:" POLICY_PATH "' " + "secmod='" POLICY_FILE "' " + "flags=readOnly,noCertDB,forceSecmodChoice,forceOpen\" " + "NSS=\"flags=internal,moduleDB,skipFirst,moduleDBOnly,critical\"", + parent, PR_TRUE); + if (module) { + PRBool isLoaded = module->loaded; + SECMOD_DestroyModule(module); + if (!isLoaded) { + goto loser; + } + } + } + } +#endif pk11sdr_Init(); cert_CreateSubjectKeyIDHashTable(); pkixError = PKIX_Initialize (PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION, PKIX_MINOR_VERSION, &actualMinorVersion, &plContext); if (pkixError != NULL) { @@ -716,32 +742,38 @@ nssIsInInit--; /* now that we are inited, all waiters can move forward */ PZ_NotifyAllCondVar(nssInitCondition); PZ_Unlock(nssInitLock); if (initContextPtr && configStrings) { PR_smprintf_free(configStrings); } + if (parent) { + SECMOD_DestroyModule(parent); + } return SECSuccess; loser: if (initContextPtr && *initContextPtr) { PORT_Free(*initContextPtr); *initContextPtr = NULL; if (configStrings) { PR_smprintf_free(configStrings); } } PZ_Lock(nssInitLock); nssIsInInit--; /* We failed to init, allow one to move forward */ PZ_NotifyCondVar(nssInitCondition); PZ_Unlock(nssInitLock); + if (parent) { + SECMOD_DestroyModule(parent); + } return SECFailure; } SECStatus NSS_Init(const char *configdir) { return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL, diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c --- a/lib/pk11wrap/pk11pars.c +++ b/lib/pk11wrap/pk11pars.c @@ -105,16 +105,17 @@ secmod_NewModule(void) * 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 +#define SECMOD_FLAG_MODULE_DB_POLICY_ONLY 0x08 /* 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 @@ -699,16 +700,19 @@ SECMOD_CreateModuleEx(const char *librar 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; } + if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nssc)) { + flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY; + } /* 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)) { @@ -738,16 +742,24 @@ PRBool SECMOD_GetDefaultModDBFlag(SECMODModule *mod) { char flags = (char) mod->isModuleDB; return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; } PRBool +secmod_PolicyOnly(SECMODModule *mod) +{ + char flags = (char) mod->isModuleDB; + + return (flags & SECMOD_FLAG_MODULE_DB_POLICY_ONLY) ? 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 @@ -1521,16 +1533,22 @@ SECMOD_LoadModule(char *modulespec,SECMO if (library) PORT_Free(library); if (moduleName) PORT_Free(moduleName); if (parameters) PORT_Free(parameters); if (nss) PORT_Free(nss); if (config) PORT_Free(config); if (!module) { goto loser; } + + /* a policy only stanza doesn't actually get 'loaded'. policy has already + * been parsed as a side effect of the CreateModuleEx call */ + if (secmod_PolicyOnly(module)) { + return module; + } if (parent) { module->parent = SECMOD_ReferenceModule(parent); if (module->internal && secmod_IsInternalKeySlot(parent)) { module->internal = parent->internal; } } /* load it */ diff --git a/lib/util/utilpars.c b/lib/util/utilpars.c --- a/lib/util/utilpars.c +++ b/lib/util/utilpars.c @@ -1139,17 +1139,18 @@ char * *dbType = NSS_DB_TYPE_SQL; PORT_Free(*filename); *filename = NULL; *rw = PR_FALSE; } /* only use the renamed secmod for legacy databases */ if ((*dbType != NSS_DB_TYPE_LEGACY) && - (*dbType != NSS_DB_TYPE_MULTIACCESS)) { + (*dbType != NSS_DB_TYPE_MULTIACCESS) && + !NSSUTIL_ArgHasFlag("flags", "forceSecmodChoice", save_params)) { secmodName="pkcs11.txt"; } if (noModDB) { value = NULL; } else if (lconfigdir && lconfigdir[0] != '\0') { value = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s", lconfigdir,secmodName);