summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/util/utilpars.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/util/utilpars.c')
-rw-r--r--security/nss/lib/util/utilpars.c1314
1 files changed, 1314 insertions, 0 deletions
diff --git a/security/nss/lib/util/utilpars.c b/security/nss/lib/util/utilpars.c
new file mode 100644
index 0000000000..dd3d2326a9
--- /dev/null
+++ b/security/nss/lib/util/utilpars.c
@@ -0,0 +1,1314 @@
+/* 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 code handles the storage of PKCS 11 modules used by the
+ * NSS. This file is written to abstract away how the modules are
+ * stored so we can decide that later.
+ */
+#include "secport.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "utilpars.h"
+#include "utilmodt.h"
+
+/*
+ * return the expected matching quote value for the one specified
+ */
+PRBool
+NSSUTIL_ArgGetPair(char c)
+{
+ switch (c) {
+ case '\'':
+ return c;
+ case '\"':
+ return c;
+ case '<':
+ return '>';
+ case '{':
+ return '}';
+ case '[':
+ return ']';
+ case '(':
+ return ')';
+ default:
+ break;
+ }
+ return ' ';
+}
+
+PRBool
+NSSUTIL_ArgIsBlank(char c)
+{
+ return isspace((unsigned char)c);
+}
+
+PRBool
+NSSUTIL_ArgIsEscape(char c)
+{
+ return c == '\\';
+}
+
+PRBool
+NSSUTIL_ArgIsQuote(char c)
+{
+ switch (c) {
+ case '\'':
+ case '\"':
+ case '<':
+ case '{': /* } end curly to keep vi bracket matching working */
+ case '(': /* ) */
+ case '[': /* ] */
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+const char *
+NSSUTIL_ArgStrip(const char *c)
+{
+ while (*c && NSSUTIL_ArgIsBlank(*c))
+ c++;
+ return c;
+}
+
+/*
+ * find the end of the current tag/value pair. string should be pointing just
+ * after the equal sign. Handles quoted characters.
+ */
+const char *
+NSSUTIL_ArgFindEnd(const char *string)
+{
+ char endChar = ' ';
+ PRBool lastEscape = PR_FALSE;
+
+ if (NSSUTIL_ArgIsQuote(*string)) {
+ endChar = NSSUTIL_ArgGetPair(*string);
+ string++;
+ }
+
+ for (; *string; string++) {
+ if (lastEscape) {
+ lastEscape = PR_FALSE;
+ continue;
+ }
+ if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ if ((endChar == ' ') && NSSUTIL_ArgIsBlank(*string))
+ break;
+ if (*string == endChar) {
+ break;
+ }
+ }
+
+ return string;
+}
+
+/*
+ * get the value pointed to by string. string should be pointing just beyond
+ * the equal sign.
+ */
+char *
+NSSUTIL_ArgFetchValue(const char *string, int *pcount)
+{
+ const char *end = NSSUTIL_ArgFindEnd(string);
+ char *retString, *copyString;
+ PRBool lastEscape = PR_FALSE;
+ int len;
+
+ len = end - string;
+ if (len == 0) {
+ *pcount = 0;
+ return NULL;
+ }
+
+ copyString = retString = (char *)PORT_Alloc(len + 1);
+
+ if (*end)
+ len++;
+ *pcount = len;
+ if (retString == NULL)
+ return NULL;
+
+ if (NSSUTIL_ArgIsQuote(*string))
+ string++;
+ for (; string < end; string++) {
+ if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ lastEscape = PR_FALSE;
+ *copyString++ = *string;
+ }
+ *copyString = 0;
+ return retString;
+}
+
+/*
+ * point to the next parameter in string
+ */
+const char *
+NSSUTIL_ArgSkipParameter(const char *string)
+{
+ const char *end;
+ /* look for the end of the <name>= */
+ for (; *string; string++) {
+ if (*string == '=') {
+ string++;
+ break;
+ }
+ if (NSSUTIL_ArgIsBlank(*string))
+ return (string);
+ }
+
+ end = NSSUTIL_ArgFindEnd(string);
+ if (*end)
+ end++;
+ return end;
+}
+
+/*
+ * get the value from that tag value pair.
+ */
+char *
+NSSUTIL_ArgGetParamValue(const char *paramName, const char *parameters)
+{
+ char searchValue[256];
+ size_t paramLen = strlen(paramName);
+ char *returnValue = NULL;
+ int next;
+
+ if ((parameters == NULL) || (*parameters == 0))
+ return NULL;
+
+ PORT_Assert(paramLen + 2 < sizeof(searchValue));
+
+ PORT_Strcpy(searchValue, paramName);
+ PORT_Strcat(searchValue, "=");
+ while (*parameters) {
+ if (PORT_Strncasecmp(parameters, searchValue, paramLen + 1) == 0) {
+ parameters += paramLen + 1;
+ returnValue = NSSUTIL_ArgFetchValue(parameters, &next);
+ break;
+ } else {
+ parameters = NSSUTIL_ArgSkipParameter(parameters);
+ }
+ parameters = NSSUTIL_ArgStrip(parameters);
+ }
+ return returnValue;
+}
+
+/*
+ * find the next flag in the parameter list
+ */
+const char *
+NSSUTIL_ArgNextFlag(const char *flags)
+{
+ for (; *flags; flags++) {
+ if (*flags == ',') {
+ flags++;
+ break;
+ }
+ }
+ return flags;
+}
+
+/*
+ * return true if the flag is set in the label parameter.
+ */
+PRBool
+NSSUTIL_ArgHasFlag(const char *label, const char *flag, const char *parameters)
+{
+ char *flags;
+ const char *index;
+ int len = strlen(flag);
+ PRBool found = PR_FALSE;
+
+ flags = NSSUTIL_ArgGetParamValue(label, parameters);
+ if (flags == NULL)
+ return PR_FALSE;
+
+ for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
+ if (PORT_Strncasecmp(index, flag, len) == 0) {
+ found = PR_TRUE;
+ break;
+ }
+ }
+ PORT_Free(flags);
+ return found;
+}
+
+/*
+ * decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
+ */
+long
+NSSUTIL_ArgDecodeNumber(const char *num)
+{
+ int radix = 10;
+ unsigned long value = 0;
+ long retValue = 0;
+ int sign = 1;
+ int digit;
+
+ if (num == NULL)
+ return retValue;
+
+ num = NSSUTIL_ArgStrip(num);
+
+ if (*num == '-') {
+ sign = -1;
+ num++;
+ }
+
+ if (*num == '0') {
+ radix = 8;
+ num++;
+ if ((*num == 'x') || (*num == 'X')) {
+ radix = 16;
+ num++;
+ }
+ }
+
+ for (; *num; num++) {
+ if (isdigit(*num)) {
+ digit = *num - '0';
+ } else if ((*num >= 'a') && (*num <= 'f')) {
+ digit = *num - 'a' + 10;
+ } else if ((*num >= 'A') && (*num <= 'F')) {
+ digit = *num - 'A' + 10;
+ } else {
+ break;
+ }
+ if (digit >= radix)
+ break;
+ value = value * radix + digit;
+ }
+
+ retValue = ((int)value) * sign;
+ return retValue;
+}
+
+/*
+ * parameters are tag value pairs. This function returns the tag or label (the
+ * value before the equal size.
+ */
+char *
+NSSUTIL_ArgGetLabel(const char *inString, int *next)
+{
+ char *name = NULL;
+ const char *string;
+ int len;
+
+ /* look for the end of the <label>= */
+ for (string = inString; *string; string++) {
+ if (*string == '=') {
+ break;
+ }
+ if (NSSUTIL_ArgIsBlank(*string))
+ break;
+ }
+
+ len = string - inString;
+
+ *next = len;
+ if (*string == '=')
+ (*next) += 1;
+ if (len > 0) {
+ name = PORT_Alloc(len + 1);
+ PORT_Strncpy(name, inString, len);
+ name[len] = 0;
+ }
+ return name;
+}
+
+/*
+ * read an argument at a Long integer
+ */
+long
+NSSUTIL_ArgReadLong(const char *label, const char *params,
+ long defValue, PRBool *isdefault)
+{
+ char *value;
+ long retValue;
+ if (isdefault)
+ *isdefault = PR_FALSE;
+
+ value = NSSUTIL_ArgGetParamValue(label, params);
+ if (value == NULL) {
+ if (isdefault)
+ *isdefault = PR_TRUE;
+ return defValue;
+ }
+ retValue = NSSUTIL_ArgDecodeNumber(value);
+ if (value)
+ PORT_Free(value);
+
+ return retValue;
+}
+
+/*
+ * prepare a string to be quoted with 'quote' marks. We do that by adding
+ * appropriate escapes.
+ */
+static int
+nssutil_escapeQuotesSize(const char *string, char quote, PRBool addquotes)
+{
+ int escapes = 0, size = 0;
+ const char *src;
+
+ size = addquotes ? 2 : 0;
+ for (src = string; *src; src++) {
+ if ((*src == quote) || (*src == '\\'))
+ escapes++;
+ size++;
+ }
+ return size + escapes + 1;
+}
+
+static char *
+nssutil_escapeQuotes(const char *string, char quote, PRBool addquotes)
+{
+ char *newString = 0;
+ int size = 0;
+ const char *src;
+ char *dest;
+
+ size = nssutil_escapeQuotesSize(string, quote, addquotes);
+
+ dest = newString = PORT_ZAlloc(size);
+ if (newString == NULL) {
+ return NULL;
+ }
+
+ if (addquotes)
+ *dest++ = quote;
+ for (src = string; *src; src++, dest++) {
+ if ((*src == '\\') || (*src == quote)) {
+ *dest++ = '\\';
+ }
+ *dest = *src;
+ }
+ if (addquotes)
+ *dest = quote;
+
+ return newString;
+}
+
+int
+NSSUTIL_EscapeSize(const char *string, char quote)
+{
+ return nssutil_escapeQuotesSize(string, quote, PR_FALSE);
+}
+
+char *
+NSSUTIL_Escape(const char *string, char quote)
+{
+ return nssutil_escapeQuotes(string, quote, PR_FALSE);
+}
+
+int
+NSSUTIL_QuoteSize(const char *string, char quote)
+{
+ return nssutil_escapeQuotesSize(string, quote, PR_TRUE);
+}
+
+char *
+NSSUTIL_Quote(const char *string, char quote)
+{
+ return nssutil_escapeQuotes(string, quote, PR_TRUE);
+}
+
+int
+NSSUTIL_DoubleEscapeSize(const char *string, char quote1, char quote2)
+{
+ int escapes = 0, size = 0;
+ const char *src;
+ for (src = string; *src; src++) {
+ if (*src == '\\')
+ escapes += 3; /* \\\\ */
+ if (*src == quote1)
+ escapes += 2; /* \\quote1 */
+ if (*src == quote2)
+ escapes++; /* \quote2 */
+ size++;
+ }
+
+ return escapes + size + 1;
+}
+
+char *
+NSSUTIL_DoubleEscape(const char *string, char quote1, char quote2)
+{
+ char *round1 = NULL;
+ char *retValue = NULL;
+ if (string == NULL) {
+ goto done;
+ }
+ round1 = nssutil_escapeQuotes(string, quote1, PR_FALSE);
+ if (round1) {
+ retValue = nssutil_escapeQuotes(round1, quote2, PR_FALSE);
+ PORT_Free(round1);
+ }
+
+done:
+ if (retValue == NULL) {
+ retValue = PORT_Strdup("");
+ }
+ return retValue;
+}
+
+/************************************************************************
+ * These functions are used in contructing strings.
+ * NOTE: they will always return a string, but sometimes it will return
+ * a specific NULL string. These strings must be freed with util_freePair.
+ */
+
+/* string to return on error... */
+static char *nssutil_nullString = "";
+
+static char *
+nssutil_formatValue(PLArenaPool *arena, char *value, char quote)
+{
+ char *vp, *vp2, *retval;
+ int size = 0, escapes = 0;
+
+ for (vp = value; *vp; vp++) {
+ if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
+ escapes++;
+ size++;
+ }
+ if (arena) {
+ retval = PORT_ArenaZAlloc(arena, size + escapes + 1);
+ } else {
+ retval = PORT_ZAlloc(size + escapes + 1);
+ }
+ if (retval == NULL)
+ return NULL;
+ vp2 = retval;
+ for (vp = value; *vp; vp++) {
+ if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
+ *vp2++ = NSSUTIL_ARG_ESCAPE;
+ *vp2++ = *vp;
+ }
+ return retval;
+}
+
+static PRBool
+nssutil_argHasChar(char *v, char c)
+{
+ for (; *v; v++) {
+ if (*v == c)
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static PRBool
+nssutil_argHasBlanks(char *v)
+{
+ for (; *v; v++) {
+ if (NSSUTIL_ArgIsBlank(*v))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static char *
+nssutil_formatPair(char *name, char *value, char quote)
+{
+ char openQuote = quote;
+ char closeQuote = NSSUTIL_ArgGetPair(quote);
+ char *newValue = NULL;
+ char *returnValue;
+ PRBool need_quote = PR_FALSE;
+
+ if (!value || (*value == 0))
+ return nssutil_nullString;
+
+ if (nssutil_argHasBlanks(value) || NSSUTIL_ArgIsQuote(value[0]))
+ need_quote = PR_TRUE;
+
+ if ((need_quote && nssutil_argHasChar(value, closeQuote)) || nssutil_argHasChar(value, NSSUTIL_ARG_ESCAPE)) {
+ value = newValue = nssutil_formatValue(NULL, value, quote);
+ if (newValue == NULL)
+ return nssutil_nullString;
+ }
+ if (need_quote) {
+ returnValue = PR_smprintf("%s=%c%s%c", name, openQuote, value, closeQuote);
+ } else {
+ returnValue = PR_smprintf("%s=%s", name, value);
+ }
+ if (returnValue == NULL)
+ returnValue = nssutil_nullString;
+
+ if (newValue)
+ PORT_Free(newValue);
+
+ return returnValue;
+}
+
+static char *
+nssutil_formatIntPair(char *name, unsigned long value,
+ unsigned long def)
+{
+ char *returnValue;
+
+ if (value == def)
+ return nssutil_nullString;
+
+ returnValue = PR_smprintf("%s=%d", name, value);
+
+ return returnValue;
+}
+
+static void
+nssutil_freePair(char *pair)
+{
+ if (pair && pair != nssutil_nullString) {
+ PR_smprintf_free(pair);
+ }
+}
+
+/************************************************************************
+ * Parse the Slot specific parameters in the NSS params.
+ */
+
+struct nssutilArgSlotFlagTable {
+ char *name;
+ int len;
+ unsigned long value;
+};
+
+#define NSSUTIL_ARG_ENTRY(arg, flag) \
+ { \
+#arg, sizeof(#arg) - 1, flag \
+ }
+static struct nssutilArgSlotFlagTable nssutil_argSlotFlagTable[] = {
+ NSSUTIL_ARG_ENTRY(RSA, SECMOD_RSA_FLAG),
+ NSSUTIL_ARG_ENTRY(ECC, SECMOD_ECC_FLAG),
+ NSSUTIL_ARG_ENTRY(DSA, SECMOD_RSA_FLAG),
+ NSSUTIL_ARG_ENTRY(RC2, SECMOD_RC4_FLAG),
+ NSSUTIL_ARG_ENTRY(RC4, SECMOD_RC2_FLAG),
+ NSSUTIL_ARG_ENTRY(DES, SECMOD_DES_FLAG),
+ NSSUTIL_ARG_ENTRY(DH, SECMOD_DH_FLAG),
+ NSSUTIL_ARG_ENTRY(FORTEZZA, SECMOD_FORTEZZA_FLAG),
+ NSSUTIL_ARG_ENTRY(RC5, SECMOD_RC5_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA1, SECMOD_SHA1_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA256, SECMOD_SHA256_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA512, SECMOD_SHA512_FLAG),
+ NSSUTIL_ARG_ENTRY(MD5, SECMOD_MD5_FLAG),
+ NSSUTIL_ARG_ENTRY(MD2, SECMOD_MD2_FLAG),
+ NSSUTIL_ARG_ENTRY(SSL, SECMOD_SSL_FLAG),
+ NSSUTIL_ARG_ENTRY(TLS, SECMOD_TLS_FLAG),
+ NSSUTIL_ARG_ENTRY(AES, SECMOD_AES_FLAG),
+ NSSUTIL_ARG_ENTRY(Camellia, SECMOD_CAMELLIA_FLAG),
+ NSSUTIL_ARG_ENTRY(SEED, SECMOD_SEED_FLAG),
+ NSSUTIL_ARG_ENTRY(PublicCerts, SECMOD_FRIENDLY_FLAG),
+ NSSUTIL_ARG_ENTRY(RANDOM, SECMOD_RANDOM_FLAG),
+ NSSUTIL_ARG_ENTRY(Disable, SECMOD_DISABLE_FLAG),
+};
+
+static int nssutil_argSlotFlagTableSize =
+ sizeof(nssutil_argSlotFlagTable) / sizeof(nssutil_argSlotFlagTable[0]);
+
+/* turn the slot flags into a bit mask */
+unsigned long
+NSSUTIL_ArgParseSlotFlags(const char *label, const char *params)
+{
+ char *flags;
+ const char *index;
+ unsigned long retValue = 0;
+ int i;
+ PRBool all = PR_FALSE;
+
+ flags = NSSUTIL_ArgGetParamValue(label, params);
+ if (flags == NULL)
+ return 0;
+
+ if (PORT_Strcasecmp(flags, "all") == 0)
+ all = PR_TRUE;
+
+ for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
+ for (i = 0; i < nssutil_argSlotFlagTableSize; i++) {
+ if (all ||
+ (PORT_Strncasecmp(index, nssutil_argSlotFlagTable[i].name,
+ nssutil_argSlotFlagTable[i].len) == 0)) {
+ retValue |= nssutil_argSlotFlagTable[i].value;
+ }
+ }
+ }
+ PORT_Free(flags);
+ return retValue;
+}
+
+/* parse a single slot specific parameter */
+static void
+nssutil_argDecodeSingleSlotInfo(char *name, char *params,
+ struct NSSUTILPreSlotInfoStr *slotInfo)
+{
+ char *askpw;
+
+ slotInfo->slotID = NSSUTIL_ArgDecodeNumber(name);
+ slotInfo->defaultFlags = NSSUTIL_ArgParseSlotFlags("slotFlags", params);
+ slotInfo->timeout = NSSUTIL_ArgReadLong("timeout", params, 0, NULL);
+
+ askpw = NSSUTIL_ArgGetParamValue("askpw", params);
+ slotInfo->askpw = 0;
+
+ if (askpw) {
+ if (PORT_Strcasecmp(askpw, "every") == 0) {
+ slotInfo->askpw = -1;
+ } else if (PORT_Strcasecmp(askpw, "timeout") == 0) {
+ slotInfo->askpw = 1;
+ }
+ PORT_Free(askpw);
+ slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS;
+ }
+ slotInfo->hasRootCerts = NSSUTIL_ArgHasFlag("rootFlags", "hasRootCerts",
+ params);
+ slotInfo->hasRootTrust = NSSUTIL_ArgHasFlag("rootFlags", "hasRootTrust",
+ params);
+}
+
+/* parse all the slot specific parameters. */
+struct NSSUTILPreSlotInfoStr *
+NSSUTIL_ArgParseSlotInfo(PLArenaPool *arena, const char *slotParams,
+ int *retCount)
+{
+ const char *slotIndex;
+ struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
+ int i = 0, count = 0, next;
+
+ *retCount = 0;
+ if ((slotParams == NULL) || (*slotParams == 0))
+ return NULL;
+
+ /* first count the number of slots */
+ for (slotIndex = NSSUTIL_ArgStrip(slotParams); *slotIndex;
+ slotIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(slotIndex))) {
+ count++;
+ }
+
+ /* get the data structures */
+ if (arena) {
+ slotInfo = PORT_ArenaZNewArray(arena,
+ struct NSSUTILPreSlotInfoStr, count);
+ } else {
+ slotInfo = PORT_ZNewArray(struct NSSUTILPreSlotInfoStr, count);
+ }
+ if (slotInfo == NULL)
+ return NULL;
+
+ for (slotIndex = NSSUTIL_ArgStrip(slotParams), i = 0;
+ *slotIndex && i < count;) {
+ char *name;
+ name = NSSUTIL_ArgGetLabel(slotIndex, &next);
+ slotIndex += next;
+
+ if (!NSSUTIL_ArgIsBlank(*slotIndex)) {
+ char *args = NSSUTIL_ArgFetchValue(slotIndex, &next);
+ slotIndex += next;
+ if (args) {
+ nssutil_argDecodeSingleSlotInfo(name, args, &slotInfo[i]);
+ i++;
+ PORT_Free(args);
+ }
+ }
+ if (name)
+ PORT_Free(name);
+ slotIndex = NSSUTIL_ArgStrip(slotIndex);
+ }
+ *retCount = i;
+ return slotInfo;
+}
+
+/************************************************************************
+ * make a new slot specific parameter
+ */
+/* first make the slot flags */
+static char *
+nssutil_mkSlotFlags(unsigned long defaultFlags)
+{
+ char *flags = NULL;
+ unsigned int i;
+ int j;
+
+ for (i = 0; i < sizeof(defaultFlags) * 8; i++) {
+ if (defaultFlags & (1UL << i)) {
+ char *string = NULL;
+
+ for (j = 0; j < nssutil_argSlotFlagTableSize; j++) {
+ if (nssutil_argSlotFlagTable[j].value == (1UL << i)) {
+ string = nssutil_argSlotFlagTable[j].name;
+ break;
+ }
+ }
+ if (string) {
+ if (flags) {
+ char *tmp;
+ tmp = PR_smprintf("%s,%s", flags, string);
+ PR_smprintf_free(flags);
+ flags = tmp;
+ } else {
+ flags = PR_smprintf("%s", string);
+ }
+ }
+ }
+ }
+
+ return flags;
+}
+
+/* now make the root flags */
+#define NSSUTIL_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts") + sizeof("hasRootTrust")
+static char *
+nssutil_mkRootFlags(PRBool hasRootCerts, PRBool hasRootTrust)
+{
+ char *flags = (char *)PORT_ZAlloc(NSSUTIL_MAX_ROOT_FLAG_SIZE);
+ PRBool first = PR_TRUE;
+
+ PORT_Memset(flags, 0, NSSUTIL_MAX_ROOT_FLAG_SIZE);
+ if (hasRootCerts) {
+ PORT_Strcat(flags, "hasRootCerts");
+ first = PR_FALSE;
+ }
+ if (hasRootTrust) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "hasRootTrust");
+ }
+ return flags;
+}
+
+/* now make a full slot string */
+char *
+NSSUTIL_MkSlotString(unsigned long slotID, unsigned long defaultFlags,
+ unsigned long timeout, unsigned char askpw_in,
+ PRBool hasRootCerts, PRBool hasRootTrust)
+{
+ char *askpw, *flags, *rootFlags, *slotString;
+ char *flagPair, *rootFlagsPair;
+
+ switch (askpw_in) {
+ case 0xff:
+ askpw = "every";
+ break;
+ case 1:
+ askpw = "timeout";
+ break;
+ default:
+ askpw = "any";
+ break;
+ }
+ flags = nssutil_mkSlotFlags(defaultFlags);
+ rootFlags = nssutil_mkRootFlags(hasRootCerts, hasRootTrust);
+ flagPair = nssutil_formatPair("slotFlags", flags, '\'');
+ rootFlagsPair = nssutil_formatPair("rootFlags", rootFlags, '\'');
+ if (flags)
+ PR_smprintf_free(flags);
+ if (rootFlags)
+ PORT_Free(rootFlags);
+ if (defaultFlags & PK11_OWN_PW_DEFAULTS) {
+ slotString = PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
+ (PRUint32)slotID, flagPair, askpw, timeout,
+ rootFlagsPair);
+ } else {
+ slotString = PR_smprintf("0x%08lx=[%s %s]",
+ (PRUint32)slotID, flagPair, rootFlagsPair);
+ }
+ nssutil_freePair(flagPair);
+ nssutil_freePair(rootFlagsPair);
+ return slotString;
+}
+
+/************************************************************************
+ * Parse Full module specs into: library, commonName, module parameters,
+ * and NSS specifi parameters.
+ */
+SECStatus
+NSSUTIL_ArgParseModuleSpecEx(const char *modulespec, char **lib, char **mod,
+ char **parameters, char **nss,
+ char **config)
+{
+ int next;
+ modulespec = NSSUTIL_ArgStrip(modulespec);
+
+ *lib = *mod = *parameters = *nss = *config = 0;
+
+ while (*modulespec) {
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *config, "config=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(modulespec)
+ }
+ return SECSuccess;
+}
+
+/************************************************************************
+ * Parse Full module specs into: library, commonName, module parameters,
+ * and NSS specifi parameters.
+ */
+SECStatus
+NSSUTIL_ArgParseModuleSpec(const char *modulespec, char **lib, char **mod,
+ char **parameters, char **nss)
+{
+ int next;
+ modulespec = NSSUTIL_ArgStrip(modulespec);
+
+ *lib = *mod = *parameters = *nss = 0;
+
+ while (*modulespec) {
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(modulespec)
+ }
+ return SECSuccess;
+}
+
+/************************************************************************
+ * make a new module spec from it's components */
+char *
+NSSUTIL_MkModuleSpecEx(char *dllName, char *commonName, char *parameters,
+ char *NSS,
+ char *config)
+{
+ char *moduleSpec;
+ char *lib, *name, *param, *nss, *conf;
+
+ /*
+ * now the final spec
+ */
+ lib = nssutil_formatPair("library", dllName, '\"');
+ name = nssutil_formatPair("name", commonName, '\"');
+ param = nssutil_formatPair("parameters", parameters, '\"');
+ nss = nssutil_formatPair("NSS", NSS, '\"');
+ if (config) {
+ conf = nssutil_formatPair("config", config, '\"');
+ moduleSpec = PR_smprintf("%s %s %s %s %s", lib, name, param, nss, conf);
+ nssutil_freePair(conf);
+ } else {
+ moduleSpec = PR_smprintf("%s %s %s %s", lib, name, param, nss);
+ }
+ nssutil_freePair(lib);
+ nssutil_freePair(name);
+ nssutil_freePair(param);
+ nssutil_freePair(nss);
+ return (moduleSpec);
+}
+
+/************************************************************************
+ * make a new module spec from it's components */
+char *
+NSSUTIL_MkModuleSpec(char *dllName, char *commonName, char *parameters,
+ char *NSS)
+{
+ return NSSUTIL_MkModuleSpecEx(dllName, commonName, parameters, NSS, NULL);
+}
+
+/************************************************************************
+ * add a single flag to the Flags= section inside the spec's NSS= section */
+char *
+NSSUTIL_AddNSSFlagToModuleSpec(char *spec, char *addFlag)
+{
+ const char *prefix = "flags=";
+ const size_t prefixLen = strlen(prefix);
+ char *lib = NULL, *name = NULL, *param = NULL, *nss = NULL, *conf = NULL;
+ char *nss2 = NULL, *result = NULL;
+ SECStatus rv;
+
+ rv = NSSUTIL_ArgParseModuleSpecEx(spec, &lib, &name, &param, &nss, &conf);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+
+ if (nss && NSSUTIL_ArgHasFlag("flags", addFlag, nss)) {
+ /* It's already there, nothing to do! */
+ PORT_Free(lib);
+ PORT_Free(name);
+ PORT_Free(param);
+ PORT_Free(nss);
+ PORT_Free(conf);
+ return PORT_Strdup(spec);
+ }
+
+ if (!nss || !strlen(nss)) {
+ nss2 = PORT_Alloc(prefixLen + strlen(addFlag) + 1);
+ PORT_Strcpy(nss2, prefix);
+ PORT_Strcat(nss2, addFlag);
+ } else {
+ const char *iNss = nss;
+ PRBool alreadyAdded = PR_FALSE;
+ size_t maxSize = strlen(nss) + strlen(addFlag) + prefixLen + 2; /* space and null terminator */
+ nss2 = PORT_Alloc(maxSize);
+ *nss2 = 0;
+ while (*iNss) {
+ iNss = NSSUTIL_ArgStrip(iNss);
+ if (PORT_Strncasecmp(iNss, prefix, prefixLen) == 0) {
+ /* We found an existing Flags= section. */
+ char *oldFlags;
+ const char *valPtr;
+ int valSize;
+ valPtr = iNss + prefixLen;
+ oldFlags = NSSUTIL_ArgFetchValue(valPtr, &valSize);
+ iNss = valPtr + valSize;
+ PORT_Strcat(nss2, prefix);
+ PORT_Strcat(nss2, oldFlags);
+ PORT_Strcat(nss2, ",");
+ PORT_Strcat(nss2, addFlag);
+ PORT_Strcat(nss2, " ");
+ PORT_Free(oldFlags);
+ alreadyAdded = PR_TRUE;
+ iNss = NSSUTIL_ArgStrip(iNss);
+ PORT_Strcat(nss2, iNss); /* remainder of input */
+ break;
+ } else {
+ /* Append this other name=value pair and continue. */
+ const char *startOfNext = NSSUTIL_ArgSkipParameter(iNss);
+ PORT_Strncat(nss2, iNss, (startOfNext - iNss));
+ if (nss2[strlen(nss2) - 1] != ' ') {
+ PORT_Strcat(nss2, " ");
+ }
+ iNss = startOfNext;
+ }
+ iNss = NSSUTIL_ArgStrip(iNss);
+ }
+ if (!alreadyAdded) {
+ /* nss wasn't empty, and it didn't contain a Flags section. We can
+ * assume that other content from nss has already been added to
+ * nss2, which means we already have a trailing space separator. */
+ PORT_Strcat(nss2, prefix);
+ PORT_Strcat(nss2, addFlag);
+ }
+ }
+
+ result = NSSUTIL_MkModuleSpecEx(lib, name, param, nss2, conf);
+ PORT_Free(lib);
+ PORT_Free(name);
+ PORT_Free(param);
+ PORT_Free(nss);
+ PORT_Free(nss2);
+ PORT_Free(conf);
+ return result;
+}
+
+#define NSSUTIL_ARG_FORTEZZA_FLAG "FORTEZZA"
+/******************************************************************************
+ * Parse the cipher flags from the NSS parameter
+ */
+void
+NSSUTIL_ArgParseCipherFlags(unsigned long *newCiphers, const char *cipherList)
+{
+ newCiphers[0] = newCiphers[1] = 0;
+ if ((cipherList == NULL) || (*cipherList == 0))
+ return;
+
+ for (; *cipherList; cipherList = NSSUTIL_ArgNextFlag(cipherList)) {
+ if (PORT_Strncasecmp(cipherList, NSSUTIL_ARG_FORTEZZA_FLAG,
+ sizeof(NSSUTIL_ARG_FORTEZZA_FLAG) - 1) == 0) {
+ newCiphers[0] |= SECMOD_FORTEZZA_FLAG;
+ }
+
+ /* add additional flags here as necessary */
+ /* direct bit mapping escape */
+ if (*cipherList == 0) {
+ if (cipherList[1] == 'l') {
+ newCiphers[1] |= atoi(&cipherList[2]);
+ } else {
+ newCiphers[0] |= atoi(&cipherList[2]);
+ }
+ }
+ }
+}
+
+/*********************************************************************
+ * make NSS parameter...
+ */
+/* First make NSS specific flags */
+#define MAX_FLAG_SIZE sizeof("internal") + sizeof("FIPS") + sizeof("moduleDB") + \
+ sizeof("moduleDBOnly") + sizeof("critical")
+static char *
+nssutil_mkNSSFlags(PRBool internal, PRBool isFIPS,
+ PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical)
+{
+ char *flags = (char *)PORT_ZAlloc(MAX_FLAG_SIZE);
+ PRBool first = PR_TRUE;
+
+ PORT_Memset(flags, 0, MAX_FLAG_SIZE);
+ if (internal) {
+ PORT_Strcat(flags, "internal");
+ first = PR_FALSE;
+ }
+ if (isFIPS) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "FIPS");
+ first = PR_FALSE;
+ }
+ if (isModuleDB) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "moduleDB");
+ first = PR_FALSE;
+ }
+ if (isModuleDBOnly) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "moduleDBOnly");
+ first = PR_FALSE;
+ }
+ if (isCritical) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "critical");
+ }
+ return flags;
+}
+
+/* construct the NSS cipher flags */
+static char *
+nssutil_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
+{
+ char *cipher = NULL;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(ssl0) * 8; i++) {
+ if (ssl0 & (1UL << i)) {
+ char *string;
+ if ((1UL << i) == SECMOD_FORTEZZA_FLAG) {
+ string = PR_smprintf("%s", NSSUTIL_ARG_FORTEZZA_FLAG);
+ } else {
+ string = PR_smprintf("0h0x%08lx", 1UL << i);
+ }
+ if (cipher) {
+ char *tmp;
+ tmp = PR_smprintf("%s,%s", cipher, string);
+ PR_smprintf_free(cipher);
+ PR_smprintf_free(string);
+ cipher = tmp;
+ } else {
+ cipher = string;
+ }
+ }
+ }
+ for (i = 0; i < sizeof(ssl0) * 8; i++) {
+ if (ssl1 & (1UL << i)) {
+ if (cipher) {
+ char *tmp;
+ tmp = PR_smprintf("%s,0l0x%08lx", cipher, 1UL << i);
+ PR_smprintf_free(cipher);
+ cipher = tmp;
+ } else {
+ cipher = PR_smprintf("0l0x%08lx", 1UL << i);
+ }
+ }
+ }
+
+ return cipher;
+}
+
+/* Assemble a full NSS string. */
+char *
+NSSUTIL_MkNSSString(char **slotStrings, int slotCount, PRBool internal,
+ PRBool isFIPS, PRBool isModuleDB, PRBool isModuleDBOnly,
+ PRBool isCritical, unsigned long trustOrder,
+ unsigned long cipherOrder, unsigned long ssl0, unsigned long ssl1)
+{
+ int slotLen, i;
+ char *slotParams, *ciphers, *nss, *nssFlags;
+ const char *tmp;
+ char *trustOrderPair, *cipherOrderPair, *slotPair, *cipherPair, *flagPair;
+
+ /* now let's build up the string
+ * first the slot infos
+ */
+ slotLen = 0;
+ for (i = 0; i < (int)slotCount; i++) {
+ slotLen += PORT_Strlen(slotStrings[i]) + 1;
+ }
+ slotLen += 1; /* space for the final NULL */
+
+ slotParams = (char *)PORT_ZAlloc(slotLen);
+ PORT_Memset(slotParams, 0, slotLen);
+ for (i = 0; i < (int)slotCount; i++) {
+ PORT_Strcat(slotParams, slotStrings[i]);
+ PORT_Strcat(slotParams, " ");
+ PR_smprintf_free(slotStrings[i]);
+ slotStrings[i] = NULL;
+ }
+
+ /*
+ * now the NSS structure
+ */
+ nssFlags = nssutil_mkNSSFlags(internal, isFIPS, isModuleDB, isModuleDBOnly,
+ isCritical);
+ /* for now only the internal module is critical */
+ ciphers = nssutil_mkCipherFlags(ssl0, ssl1);
+
+ trustOrderPair = nssutil_formatIntPair("trustOrder", trustOrder,
+ NSSUTIL_DEFAULT_TRUST_ORDER);
+ cipherOrderPair = nssutil_formatIntPair("cipherOrder", cipherOrder,
+ NSSUTIL_DEFAULT_CIPHER_ORDER);
+ slotPair = nssutil_formatPair("slotParams", slotParams, '{'); /* } */
+ if (slotParams)
+ PORT_Free(slotParams);
+ cipherPair = nssutil_formatPair("ciphers", ciphers, '\'');
+ if (ciphers)
+ PR_smprintf_free(ciphers);
+ flagPair = nssutil_formatPair("Flags", nssFlags, '\'');
+ if (nssFlags)
+ PORT_Free(nssFlags);
+ nss = PR_smprintf("%s %s %s %s %s", trustOrderPair,
+ cipherOrderPair, slotPair, cipherPair, flagPair);
+ nssutil_freePair(trustOrderPair);
+ nssutil_freePair(cipherOrderPair);
+ nssutil_freePair(slotPair);
+ nssutil_freePair(cipherPair);
+ nssutil_freePair(flagPair);
+ tmp = NSSUTIL_ArgStrip(nss);
+ if (*tmp == '\0') {
+ PR_smprintf_free(nss);
+ nss = NULL;
+ }
+ return nss;
+}
+
+/*****************************************************************************
+ *
+ * Private calls for use by softoken and utilmod.c
+ */
+
+#define SQLDB "sql:"
+#define EXTERNDB "extern:"
+#define LEGACY "dbm:"
+#define MULTIACCESS "multiaccess:"
+#define SECMOD_DB "secmod.db"
+const char *
+_NSSUTIL_EvaluateConfigDir(const char *configdir,
+ NSSDBType *pdbType, char **appName)
+{
+ NSSDBType dbType;
+ PRBool checkEnvDefaultDB = PR_FALSE;
+ *appName = NULL;
+ /* force the default */
+ dbType = NSS_DB_TYPE_SQL;
+ if (configdir == NULL) {
+ checkEnvDefaultDB = PR_TRUE;
+ } else if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS) - 1) == 0) {
+ char *cdir;
+ dbType = NSS_DB_TYPE_MULTIACCESS;
+
+ *appName = PORT_Strdup(configdir + sizeof(MULTIACCESS) - 1);
+ if (*appName == NULL) {
+ return configdir;
+ }
+ cdir = *appName;
+ while (*cdir && *cdir != ':') {
+ cdir++;
+ }
+ if (*cdir == ':') {
+ *cdir = 0;
+ cdir++;
+ }
+ configdir = cdir;
+ } else if (PORT_Strncmp(configdir, SQLDB, sizeof(SQLDB) - 1) == 0) {
+ dbType = NSS_DB_TYPE_SQL;
+ configdir = configdir + sizeof(SQLDB) - 1;
+ } else if (PORT_Strncmp(configdir, EXTERNDB, sizeof(EXTERNDB) - 1) == 0) {
+ dbType = NSS_DB_TYPE_EXTERN;
+ configdir = configdir + sizeof(EXTERNDB) - 1;
+ } else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY) - 1) == 0) {
+ dbType = NSS_DB_TYPE_LEGACY;
+ configdir = configdir + sizeof(LEGACY) - 1;
+ } else {
+ checkEnvDefaultDB = PR_TRUE;
+ }
+
+ /* look up the default from the environment */
+ if (checkEnvDefaultDB) {
+ char *defaultType = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE");
+ if (defaultType != NULL) {
+ if (PORT_Strncmp(defaultType, SQLDB, sizeof(SQLDB) - 2) == 0) {
+ dbType = NSS_DB_TYPE_SQL;
+ } else if (PORT_Strncmp(defaultType, EXTERNDB, sizeof(EXTERNDB) - 2) == 0) {
+ dbType = NSS_DB_TYPE_EXTERN;
+ } else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY) - 2) == 0) {
+ dbType = NSS_DB_TYPE_LEGACY;
+ }
+ }
+ }
+ /* if the caller has already set a type, don't change it */
+ if (*pdbType == NSS_DB_TYPE_NONE) {
+ *pdbType = dbType;
+ }
+ return configdir;
+}
+
+char *
+_NSSUTIL_GetSecmodName(const char *param, NSSDBType *dbType, char **appName,
+ char **filename, PRBool *rw)
+{
+ int next;
+ char *configdir = NULL;
+ char *secmodName = NULL;
+ char *value = NULL;
+ const char *save_params = param;
+ const char *lconfigdir;
+ PRBool noModDB = PR_FALSE;
+ param = NSSUTIL_ArgStrip(param);
+
+ while (*param) {
+ NSSUTIL_HANDLE_STRING_ARG(param, configdir, "configDir=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(param, secmodName, "secmod=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(param)
+ }
+
+ *rw = PR_TRUE;
+ if (NSSUTIL_ArgHasFlag("flags", "readOnly", save_params)) {
+ *rw = PR_FALSE;
+ }
+
+ if (!secmodName || *secmodName == '\0') {
+ if (secmodName)
+ PORT_Free(secmodName);
+ secmodName = PORT_Strdup(SECMOD_DB);
+ }
+
+ *filename = secmodName;
+ lconfigdir = _NSSUTIL_EvaluateConfigDir(configdir, dbType, appName);
+
+ if (NSSUTIL_ArgHasFlag("flags", "noModDB", save_params)) {
+ /* there isn't a module db, don't load the legacy support */
+ noModDB = PR_TRUE;
+ *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) &&
+ !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);
+ } else {
+ value = PR_smprintf("%s", secmodName);
+ }
+ if (configdir)
+ PORT_Free(configdir);
+ return value;
+}