summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2022-06-15 11:31:44 +0000
committerDaiki Ueno <dueno@redhat.com>2022-06-15 11:31:44 +0000
commit275120fccb522a8c54d84d417e70fc061048df34 (patch)
tree60af7b162616928afd2850a1d1505c5b2ac4a597
parent1e910430010139a54808439998080804126a51b9 (diff)
downloadnss-hg-275120fccb522a8c54d84d417e70fc061048df34.tar.gz
Bug 1497537, nss-policy-check: make unknown keyword check optional, r=rrelyea
Differential Revision: https://phabricator.services.mozilla.com/D8088
-rw-r--r--cmd/nss-policy-check/nss-policy-check.c121
-rw-r--r--lib/pk11wrap/pk11pars.c100
-rwxr-xr-xtests/policy/policy.sh2
3 files changed, 182 insertions, 41 deletions
diff --git a/cmd/nss-policy-check/nss-policy-check.c b/cmd/nss-policy-check/nss-policy-check.c
index b83003874..acf2125b5 100644
--- a/cmd/nss-policy-check/nss-policy-check.c
+++ b/cmd/nss-policy-check/nss-policy-check.c
@@ -21,6 +21,7 @@
#include "secmod.h"
#include "ssl.h"
#include "prenv.h"
+#include "plgetopt.h"
const char *sWarn = "WARN";
const char *sInfo = "INFO";
@@ -68,6 +69,21 @@ get_tls_info(SSLProtocolVariant protocolVariant, const char *display)
#define PATH_MAX 1024
#endif
+/* private flags for policy check; should be in sync with pk11wrap/pk11pars.c */
+#define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01
+#define SECMOD_FLAG_POLICY_CHECK_VALUE 0x02
+
+static void
+printUsage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [options] <path-to-policy-file>\n"
+ "\tWhere options are:\n"
+ "\t-f flag\t Set policy check flag (can be specified multiple times)\n"
+ "\t \t Possible flags: \"identifier\" or \"value\"\n",
+ progName);
+}
+
int
main(int argc, char **argv)
{
@@ -80,18 +96,65 @@ main(int argc, char **argv)
char moduleSpec[1024 + PATH_MAX];
unsigned num_enabled = 0;
int result = 0;
+ char *flags = NULL;
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ char *fullPath = NULL;
int fullPathLen;
+ char *progName = NULL;
+ PRUint32 policyCheckFlags = 0;
- if (argc != 2) {
- fprintf(stderr, "Syntax: nss-policy-check <path-to-policy-file>\n");
+ progName = PORT_Strdup(argv[0]);
+ if (!progName) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ /* Use PL_CreateOptState as SECU_ParseCommandLine ignores
+ * positional parameters */
+ optstate = PL_CreateOptState(argc, argv, "f:");
+ if (!optstate) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 0: /* positional parameter */
+ fullPath = PL_strdup(optstate->value);
+ if (!fullPath) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ goto breakout;
+ case 'f':
+ if (!PORT_Strcmp(optstate->value, "identifier")) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER;
+ } else if (!PORT_Strcmp(optstate->value, "value")) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE;
+ } else {
+ fprintf(stderr, "not a valid flag: %s\n", optstate->value);
+ printUsage(progName);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ break;
+ default:
+ printUsage(progName);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ }
+breakout:
+ if (status != PL_OPT_OK || !fullPath) {
+ printUsage(progName);
result = 2;
goto loser_no_shutdown;
}
- fullPathLen = strlen(argv[1]);
+ fullPathLen = strlen(fullPath);
- if (!fullPathLen || PR_Access(argv[1], PR_ACCESS_READ_OK) != PR_SUCCESS) {
- fprintf(stderr, "Error: cannot read file %s\n", argv[1]);
+ if (!fullPathLen || PR_Access(fullPath, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ fprintf(stderr, "Error: cannot read file %s\n", fullPath);
result = 2;
goto loser_no_shutdown;
}
@@ -103,16 +166,16 @@ main(int argc, char **argv)
}
path[0] = 0;
- filename = argv[1] + fullPathLen - 1;
- while ((filename > argv[1]) && (*filename != NSSUTIL_PATH_SEPARATOR[0])) {
+ filename = fullPath + fullPathLen - 1;
+ while ((filename > fullPath) && (*filename != NSSUTIL_PATH_SEPARATOR[0])) {
filename--;
}
- if (filename == argv[1]) {
+ if (filename == fullPath) {
PORT_Strcpy(path, ".");
} else {
filename++; /* Go past the path separator. */
- PORT_Strncat(path, argv[1], (filename - argv[1]));
+ PORT_Strncat(path, fullPath, (filename - fullPath));
}
PR_SetEnv("NSS_IGNORE_SYSTEM_POLICY=1");
@@ -127,13 +190,43 @@ main(int argc, char **argv)
PR_SetEnv("NSS_POLICY_FAIL=0");
PR_SetEnv("NSS_POLICY_WARN=0");
+ flags = PORT_Strdup("internal,moduleDB,skipFirst,moduleDBOnly,critical,printPolicyFeedback");
+ if (!flags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ if (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) {
+ char *newflags;
+
+ newflags = PORT_Realloc(flags, strlen(flags) + strlen(",policyCheckIdentifier") + 1);
+ if (!newflags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ flags = newflags;
+ PORT_Strcat(flags, ",policyCheckIdentifier");
+ }
+
+ if (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) {
+ char *newflags;
+
+ newflags = PORT_Realloc(flags, strlen(flags) + strlen(",policyCheckValue") + 1);
+ if (!newflags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ flags = newflags;
+ PORT_Strcat(flags, ",policyCheckValue");
+ }
+
sprintf(moduleSpec,
"name=\"Policy File\" "
"parameters=\"configdir='sql:%s' "
"secmod='%s' "
"flags=readOnly,noCertDB,forceSecmodChoice,forceOpen\" "
- "NSS=\"flags=internal,moduleDB,skipFirst,moduleDBOnly,critical,printPolicyFeedback\"",
- path, filename);
+ "NSS=\"flags=%s\"",
+ path, filename, flags);
module = SECMOD_LoadModule(moduleSpec, NULL, PR_TRUE);
if (!module || !module->loaded || atoi(PR_GetEnvSecure("NSS_POLICY_LOADED")) != 1) {
@@ -197,6 +290,12 @@ loser:
result = 2;
}
loser_no_shutdown:
+ if (optstate) {
+ PL_DestroyOptState(optstate);
+ }
+ PORT_Free(flags);
+ PORT_Free(progName);
+ PORT_Free(fullPath);
if (result == 2) {
fprintf(stderr, "NSS-POLICY-FAIL\n");
} else if (result == 1) {
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
index 23e5af32f..63ad93a3b 100644
--- a/lib/pk11wrap/pk11pars.c
+++ b/lib/pk11wrap/pk11pars.c
@@ -127,6 +127,10 @@ secmod_NewModule(void)
*the other flags are set */
#define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02
+/* private flags for policy check. */
+#define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01
+#define SECMOD_FLAG_POLICY_CHECK_VALUE 0x02
+
/*
* for 3.4 we continue to use the old SECMODModule structure
*/
@@ -496,7 +500,7 @@ secmod_ArgGetSubValue(const char *cipher, char sep1, char sep2,
static PRUint32
secmod_parsePolicyValue(const char *policyFlags, int policyLength,
- PRBool printPolicyFeedback)
+ PRBool printPolicyFeedback, PRUint32 policyCheckFlags)
{
const char *flag, *currentString;
PRUint32 flags = 0;
@@ -521,7 +525,8 @@ secmod_parsePolicyValue(const char *policyFlags, int policyLength,
break;
}
}
- if (unknown && printPolicyFeedback) {
+ if (unknown && printPolicyFeedback &&
+ (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) {
PR_SetEnv("NSS_POLICY_FAIL=1");
fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
policyLength, policyFlags, length, flag);
@@ -630,7 +635,7 @@ secmod_getOperationString(NSSPolicyOperation operation)
static SECStatus
secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
- PRBool printPolicyFeedback)
+ PRBool printPolicyFeedback, PRUint32 policyCheckFlags)
{
const char *cipher, *currentString;
unsigned i, j;
@@ -658,7 +663,7 @@ secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
/* disable or enable all options by default */
PRUint32 value = 0;
if (newValue) {
- value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback);
+ value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback, policyCheckFlags);
}
for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
const algListsDef *algOptList = &algOptLists[i];
@@ -688,7 +693,8 @@ secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
if (newOption) {
value = secmod_parsePolicyValue(&cipher[name_size] + 1,
length - name_size - 1,
- printPolicyFeedback);
+ printPolicyFeedback,
+ policyCheckFlags);
}
rv = secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);
if (rv != SECSuccess) {
@@ -717,7 +723,8 @@ secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
rv = secmod_getPolicyOptValue(policyValue, policyValueLength,
&val);
if (rv != SECSuccess) {
- if (printPolicyFeedback) {
+ if (printPolicyFeedback &&
+ (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) {
PR_SetEnv("NSS_POLICY_FAIL=1");
fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
length, cipher, policyValueLength, policyValue);
@@ -737,7 +744,8 @@ secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
}
}
- if (unknown && printPolicyFeedback) {
+ if (unknown && printPolicyFeedback &&
+ (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER)) {
PR_SetEnv("NSS_POLICY_FAIL=1");
fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n",
secmod_getOperationString(operation), length, cipher);
@@ -813,7 +821,8 @@ secmod_sanityCheckCryptoPolicy(void)
}
static SECStatus
-secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback)
+secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback,
+ PRUint32 policyCheckFlags)
{
char *args;
SECStatus rv;
@@ -828,28 +837,32 @@ secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback)
return rv;
}
args = NSSUTIL_ArgGetParamValue("disallow", policyConfig);
- rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback);
+ rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback,
+ policyCheckFlags);
if (args)
PORT_Free(args);
if (rv != SECSuccess) {
return rv;
}
args = NSSUTIL_ArgGetParamValue("allow", policyConfig);
- rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback);
+ rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback,
+ policyCheckFlags);
if (args)
PORT_Free(args);
if (rv != SECSuccess) {
return rv;
}
args = NSSUTIL_ArgGetParamValue("disable", policyConfig);
- rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback);
+ rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback,
+ policyCheckFlags);
if (args)
PORT_Free(args);
if (rv != SECSuccess) {
return rv;
}
args = NSSUTIL_ArgGetParamValue("enable", policyConfig);
- rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback);
+ rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback,
+ policyCheckFlags);
if (args)
PORT_Free(args);
if (rv != SECSuccess) {
@@ -880,6 +893,22 @@ secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback)
return rv;
}
+static PRUint32
+secmod_parsePolicyCheckFlags(const char *nss)
+{
+ PRUint32 policyCheckFlags = 0;
+
+ if (NSSUTIL_ArgHasFlag("flags", "policyCheckIdentifier", nss)) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER;
+ }
+
+ if (NSSUTIL_ArgHasFlag("flags", "policyCheckValue", nss)) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE;
+ }
+
+ return policyCheckFlags;
+}
+
/*
* for 3.4 we continue to use the old SECMODModule structure
*/
@@ -891,11 +920,10 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName,
SECMODModule *mod;
SECStatus rv;
char *slotParams, *ciphers;
- /* pk11pars.h still does not have const char * interfaces */
- char *nssc = (char *)nss;
- PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nssc);
+ PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss);
+ PRUint32 policyCheckFlags = secmod_parsePolicyCheckFlags(nss);
- rv = secmod_parseCryptoPolicy(config, printPolicyFeedback);
+ rv = secmod_parseCryptoPolicy(config, printPolicyFeedback, policyCheckFlags);
/* do not load the module if policy parsing fails */
if (rv != SECSuccess) {
@@ -919,27 +947,27 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName,
mod->libraryParams = PORT_ArenaStrdup(mod->arena, parameters);
}
- mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc);
- mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc);
+ mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nss);
+ mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nss);
/* if the system FIPS mode is enabled, force FIPS to be on */
if (SECMOD_GetSystemFIPSEnabled()) {
mod->isFIPS = PR_TRUE;
}
- mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc);
- slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc);
+ mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nss);
+ slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss);
mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,
&mod->slotInfoCount);
if (slotParams)
PORT_Free(slotParams);
/* new field */
- mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nssc,
+ mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nss,
NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
/* new field */
- mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nssc,
+ mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nss,
NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
/* new field */
- mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nssc);
- mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nssc);
+ mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nss);
+ mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nss);
if (mod->moduleDBOnly)
mod->isModuleDB = PR_TRUE;
@@ -951,13 +979,13 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName,
* 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)) {
+ if (NSSUTIL_ArgHasFlag("flags", "skipFirst", nss)) {
flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST;
}
- if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nssc)) {
+ if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nss)) {
flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB;
}
- if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nssc)) {
+ if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nss)) {
flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY;
}
/* additional moduleDB flags could be added here in the future */
@@ -967,13 +995,13 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName,
if (mod->internal) {
char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL;
- if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) {
+ if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nss)) {
flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
}
mod->internal = (PRBool)flags;
}
- ciphers = NSSUTIL_ArgGetParamValue("ciphers", nssc);
+ ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss);
NSSUTIL_ArgParseCipherFlags(&mod->ssl[0], ciphers);
if (ciphers)
PORT_Free(ciphers);
@@ -1903,6 +1931,7 @@ SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)
SECMODModule *oldModule = NULL;
SECStatus rv;
PRBool forwardPolicyFeedback = PR_FALSE;
+ PRUint32 forwardPolicyCheckFlags;
/* initialize the underlying module structures */
SECMOD_Init();
@@ -1916,6 +1945,8 @@ SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)
module = SECMOD_CreateModuleEx(library, moduleName, parameters, nss, config);
forwardPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss);
+ forwardPolicyCheckFlags = secmod_parsePolicyCheckFlags(nss);
+
if (library)
PORT_Free(library);
if (moduleName)
@@ -1984,6 +2015,17 @@ SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)
/* Add printPolicyFeedback to the nss flags */
char *specWithForwards =
NSSUTIL_AddNSSFlagToModuleSpec(*index, "printPolicyFeedback");
+ char *tmp;
+ if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) {
+ tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckIdentifier");
+ PORT_Free(specWithForwards);
+ specWithForwards = tmp;
+ }
+ if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) {
+ tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckValue");
+ PORT_Free(specWithForwards);
+ specWithForwards = tmp;
+ }
child = SECMOD_LoadModule(specWithForwards, module, PR_TRUE);
PORT_Free(specWithForwards);
}
diff --git a/tests/policy/policy.sh b/tests/policy/policy.sh
index f3d16eb64..51f7cc901 100755
--- a/tests/policy/policy.sh
+++ b/tests/policy/policy.sh
@@ -63,7 +63,7 @@ NSS=flags=policyOnly,moduleDB
echo "config=\"${policy}\"" >> "$POLICY_FILE"
echo "" >> "$POLICY_FILE"
- nss-policy-check "$POLICY_FILE" >${TMP}/$HOST.tmp.$$ 2>&1
+ nss-policy-check -f identifier -f value "$POLICY_FILE" >${TMP}/$HOST.tmp.$$ 2>&1
ret=$?
cat ${TMP}/$HOST.tmp.$$