tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

utilpars.c (37074B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * The following code handles the storage of PKCS 11 modules used by the
      6 * NSS. This file is written to abstract away how the modules are
      7 * stored so we can decide that later.
      8 */
      9 #include "secport.h"
     10 #include "prprf.h"
     11 #include "prenv.h"
     12 #include "utilpars.h"
     13 #include "utilmodt.h"
     14 
     15 /*
     16 * return the expected matching quote value for the one specified
     17 */
     18 PRBool
     19 NSSUTIL_ArgGetPair(char c)
     20 {
     21    switch (c) {
     22        case '\'':
     23            return c;
     24        case '\"':
     25            return c;
     26        case '<':
     27            return '>';
     28        case '{':
     29            return '}';
     30        case '[':
     31            return ']';
     32        case '(':
     33            return ')';
     34        default:
     35            break;
     36    }
     37    return ' ';
     38 }
     39 
     40 PRBool
     41 NSSUTIL_ArgIsBlank(char c)
     42 {
     43    return isspace((unsigned char)c);
     44 }
     45 
     46 PRBool
     47 NSSUTIL_ArgIsEscape(char c)
     48 {
     49    return c == '\\';
     50 }
     51 
     52 PRBool
     53 NSSUTIL_ArgIsQuote(char c)
     54 {
     55    switch (c) {
     56        case '\'':
     57        case '\"':
     58        case '<':
     59        case '{': /* } end curly to keep vi bracket matching working */
     60        case '(': /* ) */
     61        case '[': /* ] */
     62            return PR_TRUE;
     63        default:
     64            break;
     65    }
     66    return PR_FALSE;
     67 }
     68 
     69 const char *
     70 NSSUTIL_ArgStrip(const char *c)
     71 {
     72    while (*c && NSSUTIL_ArgIsBlank(*c))
     73        c++;
     74    return c;
     75 }
     76 
     77 /*
     78 * find the end of the current tag/value pair. string should be pointing just
     79 * after the equal sign. Handles quoted characters.
     80 */
     81 const char *
     82 NSSUTIL_ArgFindEnd(const char *string)
     83 {
     84    char endChar = ' ';
     85    PRBool lastEscape = PR_FALSE;
     86 
     87    if (NSSUTIL_ArgIsQuote(*string)) {
     88        endChar = NSSUTIL_ArgGetPair(*string);
     89        string++;
     90    }
     91 
     92    for (; *string; string++) {
     93        if (lastEscape) {
     94            lastEscape = PR_FALSE;
     95            continue;
     96        }
     97        if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
     98            lastEscape = PR_TRUE;
     99            continue;
    100        }
    101        if ((endChar == ' ') && NSSUTIL_ArgIsBlank(*string))
    102            break;
    103        if (*string == endChar) {
    104            break;
    105        }
    106    }
    107 
    108    return string;
    109 }
    110 
    111 /*
    112 * get the value pointed to by string. string should be pointing just beyond
    113 * the equal sign.
    114 */
    115 char *
    116 NSSUTIL_ArgFetchValue(const char *string, int *pcount)
    117 {
    118    const char *end = NSSUTIL_ArgFindEnd(string);
    119    char *retString, *copyString;
    120    PRBool lastEscape = PR_FALSE;
    121    int len;
    122 
    123    len = end - string;
    124    if (len == 0) {
    125        *pcount = 0;
    126        return NULL;
    127    }
    128 
    129    copyString = retString = (char *)PORT_Alloc(len + 1);
    130 
    131    if (*end)
    132        len++;
    133    *pcount = len;
    134    if (retString == NULL)
    135        return NULL;
    136 
    137    if (NSSUTIL_ArgIsQuote(*string))
    138        string++;
    139    for (; string < end; string++) {
    140        if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
    141            lastEscape = PR_TRUE;
    142            continue;
    143        }
    144        lastEscape = PR_FALSE;
    145        *copyString++ = *string;
    146    }
    147    *copyString = 0;
    148    return retString;
    149 }
    150 
    151 /*
    152 * point to the next parameter in string
    153 */
    154 const char *
    155 NSSUTIL_ArgSkipParameter(const char *string)
    156 {
    157    const char *end;
    158    /* look for the end of the <name>= */
    159    for (; *string; string++) {
    160        if (*string == '=') {
    161            string++;
    162            break;
    163        }
    164        if (NSSUTIL_ArgIsBlank(*string))
    165            return (string);
    166    }
    167 
    168    end = NSSUTIL_ArgFindEnd(string);
    169    if (*end)
    170        end++;
    171    return end;
    172 }
    173 
    174 /*
    175 * get the value from that tag value pair.
    176 */
    177 char *
    178 NSSUTIL_ArgGetParamValue(const char *paramName, const char *parameters)
    179 {
    180    char searchValue[256];
    181    size_t paramLen = strlen(paramName);
    182    char *returnValue = NULL;
    183    int next;
    184 
    185    if ((parameters == NULL) || (*parameters == 0))
    186        return NULL;
    187 
    188    PORT_Assert(paramLen + 2 < sizeof(searchValue));
    189 
    190    PORT_Strcpy(searchValue, paramName);
    191    PORT_Strcat(searchValue, "=");
    192    while (*parameters) {
    193        if (PORT_Strncasecmp(parameters, searchValue, paramLen + 1) == 0) {
    194            parameters += paramLen + 1;
    195            returnValue = NSSUTIL_ArgFetchValue(parameters, &next);
    196            break;
    197        } else {
    198            parameters = NSSUTIL_ArgSkipParameter(parameters);
    199        }
    200        parameters = NSSUTIL_ArgStrip(parameters);
    201    }
    202    return returnValue;
    203 }
    204 
    205 /*
    206 * find the next flag in the parameter list
    207 */
    208 const char *
    209 NSSUTIL_ArgNextFlag(const char *flags)
    210 {
    211    for (; *flags; flags++) {
    212        if (*flags == ',') {
    213            flags++;
    214            break;
    215        }
    216    }
    217    return flags;
    218 }
    219 
    220 /*
    221 * return true if the flag is set in the label parameter.
    222 */
    223 PRBool
    224 NSSUTIL_ArgHasFlag(const char *label, const char *flag, const char *parameters)
    225 {
    226    char *flags;
    227    const char *index;
    228    int len = strlen(flag);
    229    PRBool found = PR_FALSE;
    230 
    231    flags = NSSUTIL_ArgGetParamValue(label, parameters);
    232    if (flags == NULL)
    233        return PR_FALSE;
    234 
    235    for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
    236        if (PORT_Strncasecmp(index, flag, len) == 0) {
    237            found = PR_TRUE;
    238            break;
    239        }
    240    }
    241    PORT_Free(flags);
    242    return found;
    243 }
    244 
    245 /*
    246 * decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
    247 */
    248 long
    249 NSSUTIL_ArgDecodeNumber(const char *num)
    250 {
    251    int radix = 10;
    252    unsigned long value = 0;
    253    long retValue = 0;
    254    int sign = 1;
    255    int digit;
    256 
    257    if (num == NULL)
    258        return retValue;
    259 
    260    num = NSSUTIL_ArgStrip(num);
    261 
    262    if (*num == '-') {
    263        sign = -1;
    264        num++;
    265    }
    266 
    267    if (*num == '0') {
    268        radix = 8;
    269        num++;
    270        if ((*num == 'x') || (*num == 'X')) {
    271            radix = 16;
    272            num++;
    273        }
    274    }
    275 
    276    for (; *num; num++) {
    277        if (isdigit((unsigned char)*num)) {
    278            digit = *num - '0';
    279        } else if ((*num >= 'a') && (*num <= 'f')) {
    280            digit = *num - 'a' + 10;
    281        } else if ((*num >= 'A') && (*num <= 'F')) {
    282            digit = *num - 'A' + 10;
    283        } else {
    284            break;
    285        }
    286        if (digit >= radix)
    287            break;
    288        value = value * radix + digit;
    289    }
    290 
    291    retValue = ((int)value) * sign;
    292    return retValue;
    293 }
    294 
    295 /*
    296 * parameters are tag value pairs. This function returns the tag or label (the
    297 * value before the equal size.
    298 */
    299 char *
    300 NSSUTIL_ArgGetLabel(const char *inString, int *next)
    301 {
    302    char *name = NULL;
    303    const char *string;
    304    int len;
    305 
    306    /* look for the end of the <label>= */
    307    for (string = inString; *string; string++) {
    308        if (*string == '=') {
    309            break;
    310        }
    311        if (NSSUTIL_ArgIsBlank(*string))
    312            break;
    313    }
    314 
    315    len = string - inString;
    316 
    317    *next = len;
    318    if (*string == '=')
    319        (*next) += 1;
    320    if (len > 0) {
    321        name = PORT_Alloc(len + 1);
    322        PORT_Strncpy(name, inString, len);
    323        name[len] = 0;
    324    }
    325    return name;
    326 }
    327 
    328 /*
    329 * read an argument at a Long integer
    330 */
    331 long
    332 NSSUTIL_ArgReadLong(const char *label, const char *params,
    333                    long defValue, PRBool *isdefault)
    334 {
    335    char *value;
    336    long retValue;
    337    if (isdefault)
    338        *isdefault = PR_FALSE;
    339 
    340    value = NSSUTIL_ArgGetParamValue(label, params);
    341    if (value == NULL) {
    342        if (isdefault)
    343            *isdefault = PR_TRUE;
    344        return defValue;
    345    }
    346    retValue = NSSUTIL_ArgDecodeNumber(value);
    347    if (value)
    348        PORT_Free(value);
    349 
    350    return retValue;
    351 }
    352 
    353 /*
    354 * prepare a string to be quoted with 'quote' marks. We do that by adding
    355 * appropriate escapes.
    356 */
    357 static int
    358 nssutil_escapeQuotesSize(const char *string, char quote, PRBool addquotes)
    359 {
    360    int escapes = 0, size = 0;
    361    const char *src;
    362 
    363    size = addquotes ? 2 : 0;
    364    for (src = string; *src; src++) {
    365        if ((*src == quote) || (*src == '\\'))
    366            escapes++;
    367        size++;
    368    }
    369    return size + escapes + 1;
    370 }
    371 
    372 static char *
    373 nssutil_escapeQuotes(const char *string, char quote, PRBool addquotes)
    374 {
    375    char *newString = 0;
    376    int size = 0;
    377    const char *src;
    378    char *dest;
    379 
    380    size = nssutil_escapeQuotesSize(string, quote, addquotes);
    381 
    382    dest = newString = PORT_ZAlloc(size);
    383    if (newString == NULL) {
    384        return NULL;
    385    }
    386 
    387    if (addquotes)
    388        *dest++ = quote;
    389    for (src = string; *src; src++, dest++) {
    390        if ((*src == '\\') || (*src == quote)) {
    391            *dest++ = '\\';
    392        }
    393        *dest = *src;
    394    }
    395    if (addquotes)
    396        *dest = quote;
    397 
    398    return newString;
    399 }
    400 
    401 int
    402 NSSUTIL_EscapeSize(const char *string, char quote)
    403 {
    404    return nssutil_escapeQuotesSize(string, quote, PR_FALSE);
    405 }
    406 
    407 char *
    408 NSSUTIL_Escape(const char *string, char quote)
    409 {
    410    return nssutil_escapeQuotes(string, quote, PR_FALSE);
    411 }
    412 
    413 int
    414 NSSUTIL_QuoteSize(const char *string, char quote)
    415 {
    416    return nssutil_escapeQuotesSize(string, quote, PR_TRUE);
    417 }
    418 
    419 char *
    420 NSSUTIL_Quote(const char *string, char quote)
    421 {
    422    return nssutil_escapeQuotes(string, quote, PR_TRUE);
    423 }
    424 
    425 int
    426 NSSUTIL_DoubleEscapeSize(const char *string, char quote1, char quote2)
    427 {
    428    int escapes = 0, size = 0;
    429    const char *src;
    430    for (src = string; *src; src++) {
    431        if (*src == '\\')
    432            escapes += 3; /* \\\\ */
    433        if (*src == quote1)
    434            escapes += 2; /* \\quote1 */
    435        if (*src == quote2)
    436            escapes++; /* \quote2 */
    437        size++;
    438    }
    439 
    440    return escapes + size + 1;
    441 }
    442 
    443 char *
    444 NSSUTIL_DoubleEscape(const char *string, char quote1, char quote2)
    445 {
    446    char *round1 = NULL;
    447    char *retValue = NULL;
    448    if (string == NULL) {
    449        goto done;
    450    }
    451    round1 = nssutil_escapeQuotes(string, quote1, PR_FALSE);
    452    if (round1) {
    453        retValue = nssutil_escapeQuotes(round1, quote2, PR_FALSE);
    454        PORT_Free(round1);
    455    }
    456 
    457 done:
    458    if (retValue == NULL) {
    459        retValue = PORT_Strdup("");
    460    }
    461    return retValue;
    462 }
    463 
    464 /************************************************************************
    465 * These functions are used in contructing strings.
    466 * NOTE: they will always return a string, but sometimes it will return
    467 * a specific NULL string. These strings must be freed with util_freePair.
    468 */
    469 
    470 /* string to return on error... */
    471 static char *nssutil_nullString = "";
    472 
    473 static char *
    474 nssutil_formatValue(PLArenaPool *arena, char *value, char quote)
    475 {
    476    char *vp, *vp2, *retval;
    477    int size = 0, escapes = 0;
    478 
    479    for (vp = value; *vp; vp++) {
    480        if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
    481            escapes++;
    482        size++;
    483    }
    484    if (arena) {
    485        retval = PORT_ArenaZAlloc(arena, size + escapes + 1);
    486    } else {
    487        retval = PORT_ZAlloc(size + escapes + 1);
    488    }
    489    if (retval == NULL)
    490        return NULL;
    491    vp2 = retval;
    492    for (vp = value; *vp; vp++) {
    493        if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
    494            *vp2++ = NSSUTIL_ARG_ESCAPE;
    495        *vp2++ = *vp;
    496    }
    497    return retval;
    498 }
    499 
    500 static PRBool
    501 nssutil_argHasChar(char *v, char c)
    502 {
    503    for (; *v; v++) {
    504        if (*v == c)
    505            return PR_TRUE;
    506    }
    507    return PR_FALSE;
    508 }
    509 
    510 static PRBool
    511 nssutil_argHasBlanks(char *v)
    512 {
    513    for (; *v; v++) {
    514        if (NSSUTIL_ArgIsBlank(*v))
    515            return PR_TRUE;
    516    }
    517    return PR_FALSE;
    518 }
    519 
    520 static char *
    521 nssutil_formatPair(char *name, char *value, char quote)
    522 {
    523    char openQuote = quote;
    524    char closeQuote = NSSUTIL_ArgGetPair(quote);
    525    char *newValue = NULL;
    526    char *returnValue;
    527    PRBool need_quote = PR_FALSE;
    528 
    529    if (!value || (*value == 0))
    530        return nssutil_nullString;
    531 
    532    if (nssutil_argHasBlanks(value) || NSSUTIL_ArgIsQuote(value[0]))
    533        need_quote = PR_TRUE;
    534 
    535    if ((need_quote && nssutil_argHasChar(value, closeQuote)) || nssutil_argHasChar(value, NSSUTIL_ARG_ESCAPE)) {
    536        value = newValue = nssutil_formatValue(NULL, value, quote);
    537        if (newValue == NULL)
    538            return nssutil_nullString;
    539    }
    540    if (need_quote) {
    541        returnValue = PR_smprintf("%s=%c%s%c", name, openQuote, value, closeQuote);
    542    } else {
    543        returnValue = PR_smprintf("%s=%s", name, value);
    544    }
    545    if (returnValue == NULL)
    546        returnValue = nssutil_nullString;
    547 
    548    if (newValue)
    549        PORT_Free(newValue);
    550 
    551    return returnValue;
    552 }
    553 
    554 static char *
    555 nssutil_formatIntPair(char *name, unsigned long value,
    556                      unsigned long def)
    557 {
    558    char *returnValue;
    559 
    560    if (value == def)
    561        return nssutil_nullString;
    562 
    563    returnValue = PR_smprintf("%s=%d", name, value);
    564 
    565    return returnValue;
    566 }
    567 
    568 static void
    569 nssutil_freePair(char *pair)
    570 {
    571    if (pair && pair != nssutil_nullString) {
    572        PR_smprintf_free(pair);
    573    }
    574 }
    575 
    576 /************************************************************************
    577 * Parse the Slot specific parameters in the NSS params.
    578 */
    579 
    580 struct nssutilArgSlotFlagTable {
    581    char *name;
    582    int len;
    583    unsigned long value;
    584 };
    585 
    586 #define NSSUTIL_ARG_ENTRY(arg, flag) \
    587    {                                \
    588 #arg, sizeof(#arg) - 1, flag \
    589    }
    590 static struct nssutilArgSlotFlagTable nssutil_argSlotFlagTable[] = {
    591    NSSUTIL_ARG_ENTRY(RSA, SECMOD_RSA_FLAG),
    592    NSSUTIL_ARG_ENTRY(ECC, SECMOD_ECC_FLAG),
    593    NSSUTIL_ARG_ENTRY(DSA, SECMOD_RSA_FLAG),
    594    NSSUTIL_ARG_ENTRY(RC2, SECMOD_RC4_FLAG),
    595    NSSUTIL_ARG_ENTRY(RC4, SECMOD_RC2_FLAG),
    596    NSSUTIL_ARG_ENTRY(DES, SECMOD_DES_FLAG),
    597    NSSUTIL_ARG_ENTRY(DH, SECMOD_DH_FLAG),
    598    NSSUTIL_ARG_ENTRY(FORTEZZA, SECMOD_FORTEZZA_FLAG),
    599    NSSUTIL_ARG_ENTRY(RC5, SECMOD_RC5_FLAG),
    600    NSSUTIL_ARG_ENTRY(SHA1, SECMOD_SHA1_FLAG),
    601    NSSUTIL_ARG_ENTRY(SHA256, SECMOD_SHA256_FLAG),
    602    NSSUTIL_ARG_ENTRY(SHA512, SECMOD_SHA512_FLAG),
    603    NSSUTIL_ARG_ENTRY(MD5, SECMOD_MD5_FLAG),
    604    NSSUTIL_ARG_ENTRY(MD2, SECMOD_MD2_FLAG),
    605    NSSUTIL_ARG_ENTRY(SSL, SECMOD_SSL_FLAG),
    606    NSSUTIL_ARG_ENTRY(TLS, SECMOD_TLS_FLAG),
    607    NSSUTIL_ARG_ENTRY(AES, SECMOD_AES_FLAG),
    608    NSSUTIL_ARG_ENTRY(Camellia, SECMOD_CAMELLIA_FLAG),
    609    NSSUTIL_ARG_ENTRY(SEED, SECMOD_SEED_FLAG),
    610    NSSUTIL_ARG_ENTRY(PublicCerts, SECMOD_FRIENDLY_FLAG),
    611    NSSUTIL_ARG_ENTRY(RANDOM, SECMOD_RANDOM_FLAG),
    612    NSSUTIL_ARG_ENTRY(Disable, SECMOD_DISABLE_FLAG),
    613 };
    614 
    615 static int nssutil_argSlotFlagTableSize =
    616    sizeof(nssutil_argSlotFlagTable) / sizeof(nssutil_argSlotFlagTable[0]);
    617 
    618 /* turn the slot flags into a bit mask */
    619 unsigned long
    620 NSSUTIL_ArgParseSlotFlags(const char *label, const char *params)
    621 {
    622    char *flags;
    623    const char *index;
    624    unsigned long retValue = 0;
    625    int i;
    626    PRBool all = PR_FALSE;
    627 
    628    flags = NSSUTIL_ArgGetParamValue(label, params);
    629    if (flags == NULL)
    630        return 0;
    631 
    632    if (PORT_Strcasecmp(flags, "all") == 0)
    633        all = PR_TRUE;
    634 
    635    for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
    636        for (i = 0; i < nssutil_argSlotFlagTableSize; i++) {
    637            if (all ||
    638                (PORT_Strncasecmp(index, nssutil_argSlotFlagTable[i].name,
    639                                  nssutil_argSlotFlagTable[i].len) == 0)) {
    640                retValue |= nssutil_argSlotFlagTable[i].value;
    641            }
    642        }
    643    }
    644    PORT_Free(flags);
    645    return retValue;
    646 }
    647 
    648 /* parse a single slot specific parameter */
    649 static void
    650 nssutil_argDecodeSingleSlotInfo(char *name, char *params,
    651                                struct NSSUTILPreSlotInfoStr *slotInfo)
    652 {
    653    char *askpw;
    654 
    655    slotInfo->slotID = NSSUTIL_ArgDecodeNumber(name);
    656    slotInfo->defaultFlags = NSSUTIL_ArgParseSlotFlags("slotFlags", params);
    657    slotInfo->timeout = NSSUTIL_ArgReadLong("timeout", params, 0, NULL);
    658 
    659    askpw = NSSUTIL_ArgGetParamValue("askpw", params);
    660    slotInfo->askpw = 0;
    661 
    662    if (askpw) {
    663        if (PORT_Strcasecmp(askpw, "every") == 0) {
    664            slotInfo->askpw = -1;
    665        } else if (PORT_Strcasecmp(askpw, "timeout") == 0) {
    666            slotInfo->askpw = 1;
    667        }
    668        PORT_Free(askpw);
    669        slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS;
    670    }
    671    slotInfo->hasRootCerts = NSSUTIL_ArgHasFlag("rootFlags", "hasRootCerts",
    672                                                params);
    673    slotInfo->hasRootTrust = NSSUTIL_ArgHasFlag("rootFlags", "hasRootTrust",
    674                                                params);
    675 }
    676 
    677 /* parse all the slot specific parameters. */
    678 struct NSSUTILPreSlotInfoStr *
    679 NSSUTIL_ArgParseSlotInfo(PLArenaPool *arena, const char *slotParams,
    680                         int *retCount)
    681 {
    682    const char *slotIndex;
    683    struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
    684    int i = 0, count = 0, next;
    685 
    686    *retCount = 0;
    687    if ((slotParams == NULL) || (*slotParams == 0))
    688        return NULL;
    689 
    690    /* first count the number of slots */
    691    for (slotIndex = NSSUTIL_ArgStrip(slotParams); *slotIndex;
    692         slotIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(slotIndex))) {
    693        count++;
    694    }
    695 
    696    /* get the data structures */
    697    if (arena) {
    698        slotInfo = PORT_ArenaZNewArray(arena,
    699                                       struct NSSUTILPreSlotInfoStr, count);
    700    } else {
    701        slotInfo = PORT_ZNewArray(struct NSSUTILPreSlotInfoStr, count);
    702    }
    703    if (slotInfo == NULL)
    704        return NULL;
    705 
    706    for (slotIndex = NSSUTIL_ArgStrip(slotParams), i = 0;
    707         *slotIndex && i < count;) {
    708        char *name;
    709        name = NSSUTIL_ArgGetLabel(slotIndex, &next);
    710        slotIndex += next;
    711 
    712        if (!NSSUTIL_ArgIsBlank(*slotIndex)) {
    713            char *args = NSSUTIL_ArgFetchValue(slotIndex, &next);
    714            slotIndex += next;
    715            if (args) {
    716                nssutil_argDecodeSingleSlotInfo(name, args, &slotInfo[i]);
    717                i++;
    718                PORT_Free(args);
    719            }
    720        }
    721        if (name)
    722            PORT_Free(name);
    723        slotIndex = NSSUTIL_ArgStrip(slotIndex);
    724    }
    725    *retCount = i;
    726    return slotInfo;
    727 }
    728 
    729 /************************************************************************
    730 * make a new slot specific parameter
    731 */
    732 /* first make the slot flags */
    733 static char *
    734 nssutil_mkSlotFlags(unsigned long defaultFlags)
    735 {
    736    char *flags = NULL;
    737    unsigned int i;
    738    int j;
    739 
    740    for (i = 0; i < sizeof(defaultFlags) * 8; i++) {
    741        if (defaultFlags & (1UL << i)) {
    742            char *string = NULL;
    743 
    744            for (j = 0; j < nssutil_argSlotFlagTableSize; j++) {
    745                if (nssutil_argSlotFlagTable[j].value == (1UL << i)) {
    746                    string = nssutil_argSlotFlagTable[j].name;
    747                    break;
    748                }
    749            }
    750            if (string) {
    751                if (flags) {
    752                    char *tmp;
    753                    tmp = PR_smprintf("%s,%s", flags, string);
    754                    PR_smprintf_free(flags);
    755                    flags = tmp;
    756                } else {
    757                    flags = PR_smprintf("%s", string);
    758                }
    759            }
    760        }
    761    }
    762 
    763    return flags;
    764 }
    765 
    766 /* now make the root flags */
    767 #define NSSUTIL_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts") + sizeof("hasRootTrust")
    768 static char *
    769 nssutil_mkRootFlags(PRBool hasRootCerts, PRBool hasRootTrust)
    770 {
    771    char *flags = (char *)PORT_ZAlloc(NSSUTIL_MAX_ROOT_FLAG_SIZE);
    772    PRBool first = PR_TRUE;
    773 
    774    PORT_Memset(flags, 0, NSSUTIL_MAX_ROOT_FLAG_SIZE);
    775    if (hasRootCerts) {
    776        PORT_Strcat(flags, "hasRootCerts");
    777        first = PR_FALSE;
    778    }
    779    if (hasRootTrust) {
    780        if (!first)
    781            PORT_Strcat(flags, ",");
    782        PORT_Strcat(flags, "hasRootTrust");
    783    }
    784    return flags;
    785 }
    786 
    787 /* now make a full slot string */
    788 char *
    789 NSSUTIL_MkSlotString(unsigned long slotID, unsigned long defaultFlags,
    790                     unsigned long timeout, unsigned char askpw_in,
    791                     PRBool hasRootCerts, PRBool hasRootTrust)
    792 {
    793    char *askpw, *flags, *rootFlags, *slotString;
    794    char *flagPair, *rootFlagsPair;
    795 
    796    switch (askpw_in) {
    797        case 0xff:
    798            askpw = "every";
    799            break;
    800        case 1:
    801            askpw = "timeout";
    802            break;
    803        default:
    804            askpw = "any";
    805            break;
    806    }
    807    flags = nssutil_mkSlotFlags(defaultFlags);
    808    rootFlags = nssutil_mkRootFlags(hasRootCerts, hasRootTrust);
    809    flagPair = nssutil_formatPair("slotFlags", flags, '\'');
    810    rootFlagsPair = nssutil_formatPair("rootFlags", rootFlags, '\'');
    811    if (flags)
    812        PR_smprintf_free(flags);
    813    if (rootFlags)
    814        PORT_Free(rootFlags);
    815    if (defaultFlags & PK11_OWN_PW_DEFAULTS) {
    816        slotString = PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
    817                                 (PRUint32)slotID, flagPair, askpw, timeout,
    818                                 rootFlagsPair);
    819    } else {
    820        slotString = PR_smprintf("0x%08lx=[%s %s]",
    821                                 (PRUint32)slotID, flagPair, rootFlagsPair);
    822    }
    823    nssutil_freePair(flagPair);
    824    nssutil_freePair(rootFlagsPair);
    825    return slotString;
    826 }
    827 
    828 /************************************************************************
    829 * Parse Full module specs into: library, commonName, module parameters,
    830 * and NSS specifi parameters.
    831 */
    832 SECStatus
    833 NSSUTIL_ArgParseModuleSpecEx(const char *modulespec, char **lib, char **mod,
    834                             char **parameters, char **nss,
    835                             char **config)
    836 {
    837    int next;
    838    modulespec = NSSUTIL_ArgStrip(modulespec);
    839 
    840    *lib = *mod = *parameters = *nss = *config = 0;
    841 
    842    while (*modulespec) {
    843        NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
    844        NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
    845        NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
    846        NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
    847        NSSUTIL_HANDLE_STRING_ARG(modulespec, *config, "config=", ;)
    848        NSSUTIL_HANDLE_FINAL_ARG(modulespec)
    849    }
    850    return SECSuccess;
    851 }
    852 
    853 /************************************************************************
    854 * Parse Full module specs into: library, commonName, module parameters,
    855 * and NSS specifi parameters.
    856 */
    857 SECStatus
    858 NSSUTIL_ArgParseModuleSpec(const char *modulespec, char **lib, char **mod,
    859                           char **parameters, char **nss)
    860 {
    861    int next;
    862    modulespec = NSSUTIL_ArgStrip(modulespec);
    863 
    864    *lib = *mod = *parameters = *nss = 0;
    865 
    866    while (*modulespec) {
    867        NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
    868        NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
    869        NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
    870        NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
    871        NSSUTIL_HANDLE_FINAL_ARG(modulespec)
    872    }
    873    return SECSuccess;
    874 }
    875 
    876 /************************************************************************
    877 * make a new module spec from it's components */
    878 char *
    879 NSSUTIL_MkModuleSpecEx(char *dllName, char *commonName, char *parameters,
    880                       char *NSS,
    881                       char *config)
    882 {
    883    char *moduleSpec;
    884    char *lib, *name, *param, *nss, *conf;
    885 
    886    /*
    887     * now the final spec
    888     */
    889    lib = nssutil_formatPair("library", dllName, '\"');
    890    name = nssutil_formatPair("name", commonName, '\"');
    891    param = nssutil_formatPair("parameters", parameters, '\"');
    892    nss = nssutil_formatPair("NSS", NSS, '\"');
    893    if (config) {
    894        conf = nssutil_formatPair("config", config, '\"');
    895        moduleSpec = PR_smprintf("%s %s %s %s %s", lib, name, param, nss, conf);
    896        nssutil_freePair(conf);
    897    } else {
    898        moduleSpec = PR_smprintf("%s %s %s %s", lib, name, param, nss);
    899    }
    900    nssutil_freePair(lib);
    901    nssutil_freePair(name);
    902    nssutil_freePair(param);
    903    nssutil_freePair(nss);
    904    return (moduleSpec);
    905 }
    906 
    907 /************************************************************************
    908 * make a new module spec from it's components */
    909 char *
    910 NSSUTIL_MkModuleSpec(char *dllName, char *commonName, char *parameters,
    911                     char *NSS)
    912 {
    913    return NSSUTIL_MkModuleSpecEx(dllName, commonName, parameters, NSS, NULL);
    914 }
    915 
    916 /************************************************************************
    917 * add a single flag to the Flags= section inside the spec's NSS= section */
    918 char *
    919 NSSUTIL_AddNSSFlagToModuleSpec(char *spec, char *addFlag)
    920 {
    921    const char *prefix = "flags=";
    922    const size_t prefixLen = strlen(prefix);
    923    char *lib = NULL, *name = NULL, *param = NULL, *nss = NULL, *conf = NULL;
    924    char *nss2 = NULL, *result = NULL;
    925    SECStatus rv;
    926 
    927    rv = NSSUTIL_ArgParseModuleSpecEx(spec, &lib, &name, &param, &nss, &conf);
    928    if (rv != SECSuccess) {
    929        return NULL;
    930    }
    931 
    932    if (nss && NSSUTIL_ArgHasFlag("flags", addFlag, nss)) {
    933        /* It's already there, nothing to do! */
    934        PORT_Free(lib);
    935        PORT_Free(name);
    936        PORT_Free(param);
    937        PORT_Free(nss);
    938        PORT_Free(conf);
    939        return PORT_Strdup(spec);
    940    }
    941 
    942    if (!nss || !strlen(nss)) {
    943        nss2 = PORT_Alloc(prefixLen + strlen(addFlag) + 1);
    944        PORT_Strcpy(nss2, prefix);
    945        PORT_Strcat(nss2, addFlag);
    946    } else {
    947        const char *iNss = nss;
    948        PRBool alreadyAdded = PR_FALSE;
    949        size_t maxSize = strlen(nss) + strlen(addFlag) + prefixLen + 2; /* space and null terminator */
    950        nss2 = PORT_Alloc(maxSize);
    951        *nss2 = 0;
    952        while (*iNss) {
    953            iNss = NSSUTIL_ArgStrip(iNss);
    954            if (PORT_Strncasecmp(iNss, prefix, prefixLen) == 0) {
    955                /* We found an existing Flags= section. */
    956                char *oldFlags;
    957                const char *valPtr;
    958                int valSize;
    959                valPtr = iNss + prefixLen;
    960                oldFlags = NSSUTIL_ArgFetchValue(valPtr, &valSize);
    961                iNss = valPtr + valSize;
    962                PORT_Strcat(nss2, prefix);
    963                PORT_Strcat(nss2, oldFlags);
    964                PORT_Strcat(nss2, ",");
    965                PORT_Strcat(nss2, addFlag);
    966                PORT_Strcat(nss2, " ");
    967                PORT_Free(oldFlags);
    968                alreadyAdded = PR_TRUE;
    969                iNss = NSSUTIL_ArgStrip(iNss);
    970                PORT_Strcat(nss2, iNss); /* remainder of input */
    971                break;
    972            } else {
    973                /* Append this other name=value pair and continue. */
    974                const char *startOfNext = NSSUTIL_ArgSkipParameter(iNss);
    975                PORT_Strncat(nss2, iNss, (startOfNext - iNss));
    976                if (nss2[strlen(nss2) - 1] != ' ') {
    977                    PORT_Strcat(nss2, " ");
    978                }
    979                iNss = startOfNext;
    980            }
    981            iNss = NSSUTIL_ArgStrip(iNss);
    982        }
    983        if (!alreadyAdded) {
    984            /* nss wasn't empty, and it didn't contain a Flags section. We can
    985             * assume that other content from nss has already been added to
    986             * nss2, which means we already have a trailing space separator. */
    987            PORT_Strcat(nss2, prefix);
    988            PORT_Strcat(nss2, addFlag);
    989        }
    990    }
    991 
    992    result = NSSUTIL_MkModuleSpecEx(lib, name, param, nss2, conf);
    993    PORT_Free(lib);
    994    PORT_Free(name);
    995    PORT_Free(param);
    996    PORT_Free(nss);
    997    PORT_Free(nss2);
    998    PORT_Free(conf);
    999    return result;
   1000 }
   1001 
   1002 #define NSSUTIL_ARG_FORTEZZA_FLAG "FORTEZZA"
   1003 /******************************************************************************
   1004 * Parse the cipher flags from the NSS parameter
   1005 */
   1006 void
   1007 NSSUTIL_ArgParseCipherFlags(unsigned long *newCiphers, const char *cipherList)
   1008 {
   1009    newCiphers[0] = newCiphers[1] = 0;
   1010    if ((cipherList == NULL) || (*cipherList == 0))
   1011        return;
   1012 
   1013    for (; *cipherList; cipherList = NSSUTIL_ArgNextFlag(cipherList)) {
   1014        if (PORT_Strncasecmp(cipherList, NSSUTIL_ARG_FORTEZZA_FLAG,
   1015                             sizeof(NSSUTIL_ARG_FORTEZZA_FLAG) - 1) == 0) {
   1016            newCiphers[0] |= SECMOD_FORTEZZA_FLAG;
   1017        }
   1018 
   1019        /* add additional flags here as necessary */
   1020        /* direct bit mapping escape */
   1021        if (*cipherList == 0) {
   1022            if (cipherList[1] == 'l') {
   1023                newCiphers[1] |= atoi(&cipherList[2]);
   1024            } else {
   1025                newCiphers[0] |= atoi(&cipherList[2]);
   1026            }
   1027        }
   1028    }
   1029 }
   1030 
   1031 /*********************************************************************
   1032 * make NSS parameter...
   1033 */
   1034 /* First make NSS specific flags */
   1035 #define MAX_FLAG_SIZE sizeof("internal") + sizeof("FIPS") + sizeof("moduleDB") + \
   1036                          sizeof("moduleDBOnly") + sizeof("critical")
   1037 static char *
   1038 nssutil_mkNSSFlags(PRBool internal, PRBool isFIPS,
   1039                   PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical)
   1040 {
   1041    char *flags = (char *)PORT_ZAlloc(MAX_FLAG_SIZE);
   1042    PRBool first = PR_TRUE;
   1043 
   1044    PORT_Memset(flags, 0, MAX_FLAG_SIZE);
   1045    if (internal) {
   1046        PORT_Strcat(flags, "internal");
   1047        first = PR_FALSE;
   1048    }
   1049    if (isFIPS) {
   1050        if (!first)
   1051            PORT_Strcat(flags, ",");
   1052        PORT_Strcat(flags, "FIPS");
   1053        first = PR_FALSE;
   1054    }
   1055    if (isModuleDB) {
   1056        if (!first)
   1057            PORT_Strcat(flags, ",");
   1058        PORT_Strcat(flags, "moduleDB");
   1059        first = PR_FALSE;
   1060    }
   1061    if (isModuleDBOnly) {
   1062        if (!first)
   1063            PORT_Strcat(flags, ",");
   1064        PORT_Strcat(flags, "moduleDBOnly");
   1065        first = PR_FALSE;
   1066    }
   1067    if (isCritical) {
   1068        if (!first)
   1069            PORT_Strcat(flags, ",");
   1070        PORT_Strcat(flags, "critical");
   1071    }
   1072    return flags;
   1073 }
   1074 
   1075 /* construct the NSS cipher flags */
   1076 static char *
   1077 nssutil_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
   1078 {
   1079    char *cipher = NULL;
   1080    unsigned int i;
   1081 
   1082    for (i = 0; i < sizeof(ssl0) * 8; i++) {
   1083        if (ssl0 & (1UL << i)) {
   1084            char *string;
   1085            if ((1UL << i) == SECMOD_FORTEZZA_FLAG) {
   1086                string = PR_smprintf("%s", NSSUTIL_ARG_FORTEZZA_FLAG);
   1087            } else {
   1088                string = PR_smprintf("0h0x%08lx", 1UL << i);
   1089            }
   1090            if (cipher) {
   1091                char *tmp;
   1092                tmp = PR_smprintf("%s,%s", cipher, string);
   1093                PR_smprintf_free(cipher);
   1094                PR_smprintf_free(string);
   1095                cipher = tmp;
   1096            } else {
   1097                cipher = string;
   1098            }
   1099        }
   1100    }
   1101    for (i = 0; i < sizeof(ssl0) * 8; i++) {
   1102        if (ssl1 & (1UL << i)) {
   1103            if (cipher) {
   1104                char *tmp;
   1105                tmp = PR_smprintf("%s,0l0x%08lx", cipher, 1UL << i);
   1106                PR_smprintf_free(cipher);
   1107                cipher = tmp;
   1108            } else {
   1109                cipher = PR_smprintf("0l0x%08lx", 1UL << i);
   1110            }
   1111        }
   1112    }
   1113 
   1114    return cipher;
   1115 }
   1116 
   1117 /* Assemble a full NSS string. */
   1118 char *
   1119 NSSUTIL_MkNSSString(char **slotStrings, int slotCount, PRBool internal,
   1120                    PRBool isFIPS, PRBool isModuleDB, PRBool isModuleDBOnly,
   1121                    PRBool isCritical, unsigned long trustOrder,
   1122                    unsigned long cipherOrder, unsigned long ssl0, unsigned long ssl1)
   1123 {
   1124    int slotLen, i;
   1125    char *slotParams, *ciphers, *nss, *nssFlags;
   1126    const char *tmp;
   1127    char *trustOrderPair, *cipherOrderPair, *slotPair, *cipherPair, *flagPair;
   1128 
   1129    /* now let's build up the string
   1130     * first the slot infos
   1131     */
   1132    slotLen = 0;
   1133    for (i = 0; i < (int)slotCount; i++) {
   1134        slotLen += PORT_Strlen(slotStrings[i]) + 1;
   1135    }
   1136    slotLen += 1; /* space for the final NULL */
   1137 
   1138    slotParams = (char *)PORT_ZAlloc(slotLen);
   1139    PORT_Memset(slotParams, 0, slotLen);
   1140    for (i = 0; i < (int)slotCount; i++) {
   1141        PORT_Strcat(slotParams, slotStrings[i]);
   1142        PORT_Strcat(slotParams, " ");
   1143        PR_smprintf_free(slotStrings[i]);
   1144        slotStrings[i] = NULL;
   1145    }
   1146 
   1147    /*
   1148     * now the NSS structure
   1149     */
   1150    nssFlags = nssutil_mkNSSFlags(internal, isFIPS, isModuleDB, isModuleDBOnly,
   1151                                  isCritical);
   1152    /* for now only the internal module is critical */
   1153    ciphers = nssutil_mkCipherFlags(ssl0, ssl1);
   1154 
   1155    trustOrderPair = nssutil_formatIntPair("trustOrder", trustOrder,
   1156                                           NSSUTIL_DEFAULT_TRUST_ORDER);
   1157    cipherOrderPair = nssutil_formatIntPair("cipherOrder", cipherOrder,
   1158                                            NSSUTIL_DEFAULT_CIPHER_ORDER);
   1159    slotPair = nssutil_formatPair("slotParams", slotParams, '{'); /* } */
   1160    if (slotParams)
   1161        PORT_Free(slotParams);
   1162    cipherPair = nssutil_formatPair("ciphers", ciphers, '\'');
   1163    if (ciphers)
   1164        PR_smprintf_free(ciphers);
   1165    flagPair = nssutil_formatPair("Flags", nssFlags, '\'');
   1166    if (nssFlags)
   1167        PORT_Free(nssFlags);
   1168    nss = PR_smprintf("%s %s %s %s %s", trustOrderPair,
   1169                      cipherOrderPair, slotPair, cipherPair, flagPair);
   1170    nssutil_freePair(trustOrderPair);
   1171    nssutil_freePair(cipherOrderPair);
   1172    nssutil_freePair(slotPair);
   1173    nssutil_freePair(cipherPair);
   1174    nssutil_freePair(flagPair);
   1175    tmp = NSSUTIL_ArgStrip(nss);
   1176    if (*tmp == '\0') {
   1177        PR_smprintf_free(nss);
   1178        nss = NULL;
   1179    }
   1180    return nss;
   1181 }
   1182 
   1183 /*****************************************************************************
   1184 *
   1185 * Private calls for use by softoken and utilmod.c
   1186 */
   1187 
   1188 #define SQLDB "sql:"
   1189 #define EXTERNDB "extern:"
   1190 #define LEGACY "dbm:"
   1191 #define MULTIACCESS "multiaccess:"
   1192 #define SECMOD_DB "secmod.db"
   1193 const char *
   1194 _NSSUTIL_EvaluateConfigDir(const char *configdir,
   1195                           NSSDBType *pdbType, char **appName)
   1196 {
   1197    NSSDBType dbType;
   1198    PRBool checkEnvDefaultDB = PR_FALSE;
   1199    *appName = NULL;
   1200    /* force the default */
   1201    dbType = NSS_DB_TYPE_SQL;
   1202    if (configdir == NULL) {
   1203        checkEnvDefaultDB = PR_TRUE;
   1204    } else if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS) - 1) == 0) {
   1205        char *cdir;
   1206        dbType = NSS_DB_TYPE_MULTIACCESS;
   1207 
   1208        *appName = PORT_Strdup(configdir + sizeof(MULTIACCESS) - 1);
   1209        if (*appName == NULL) {
   1210            return configdir;
   1211        }
   1212        cdir = *appName;
   1213        while (*cdir && *cdir != ':') {
   1214            cdir++;
   1215        }
   1216        if (*cdir == ':') {
   1217            *cdir = 0;
   1218            cdir++;
   1219        }
   1220        configdir = cdir;
   1221    } else if (PORT_Strncmp(configdir, SQLDB, sizeof(SQLDB) - 1) == 0) {
   1222        dbType = NSS_DB_TYPE_SQL;
   1223        configdir = configdir + sizeof(SQLDB) - 1;
   1224    } else if (PORT_Strncmp(configdir, EXTERNDB, sizeof(EXTERNDB) - 1) == 0) {
   1225        dbType = NSS_DB_TYPE_EXTERN;
   1226        configdir = configdir + sizeof(EXTERNDB) - 1;
   1227    } else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY) - 1) == 0) {
   1228        dbType = NSS_DB_TYPE_LEGACY;
   1229        configdir = configdir + sizeof(LEGACY) - 1;
   1230    } else {
   1231        checkEnvDefaultDB = PR_TRUE;
   1232    }
   1233 
   1234    /* look up the default from the environment */
   1235    if (checkEnvDefaultDB) {
   1236        char *defaultType = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE");
   1237        if (defaultType != NULL) {
   1238            if (PORT_Strncmp(defaultType, SQLDB, sizeof(SQLDB) - 2) == 0) {
   1239                dbType = NSS_DB_TYPE_SQL;
   1240            } else if (PORT_Strncmp(defaultType, EXTERNDB, sizeof(EXTERNDB) - 2) == 0) {
   1241                dbType = NSS_DB_TYPE_EXTERN;
   1242            } else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY) - 2) == 0) {
   1243                dbType = NSS_DB_TYPE_LEGACY;
   1244            }
   1245        }
   1246    }
   1247    /* if the caller has already set a type, don't change it */
   1248    if (*pdbType == NSS_DB_TYPE_NONE) {
   1249        *pdbType = dbType;
   1250    }
   1251    return configdir;
   1252 }
   1253 
   1254 char *
   1255 _NSSUTIL_GetSecmodName(const char *param, NSSDBType *dbType, char **appName,
   1256                       char **filename, PRBool *rw)
   1257 {
   1258    int next;
   1259    char *configdir = NULL;
   1260    char *secmodName = NULL;
   1261    char *value = NULL;
   1262    const char *save_params = param;
   1263    const char *lconfigdir;
   1264    PRBool noModDB = PR_FALSE;
   1265    param = NSSUTIL_ArgStrip(param);
   1266 
   1267    while (*param) {
   1268        NSSUTIL_HANDLE_STRING_ARG(param, configdir, "configDir=", ;)
   1269        NSSUTIL_HANDLE_STRING_ARG(param, secmodName, "secmod=", ;)
   1270        NSSUTIL_HANDLE_FINAL_ARG(param)
   1271    }
   1272 
   1273    *rw = PR_TRUE;
   1274    if (NSSUTIL_ArgHasFlag("flags", "readOnly", save_params)) {
   1275        *rw = PR_FALSE;
   1276    }
   1277 
   1278    if (!secmodName || *secmodName == '\0') {
   1279        if (secmodName)
   1280            PORT_Free(secmodName);
   1281        secmodName = PORT_Strdup(SECMOD_DB);
   1282    }
   1283 
   1284    *filename = secmodName;
   1285    lconfigdir = _NSSUTIL_EvaluateConfigDir(configdir, dbType, appName);
   1286 
   1287    if (NSSUTIL_ArgHasFlag("flags", "noModDB", save_params)) {
   1288        /* there isn't a module db, don't load the legacy support */
   1289        noModDB = PR_TRUE;
   1290        *dbType = NSS_DB_TYPE_SQL;
   1291        PORT_Free(*filename);
   1292        *filename = NULL;
   1293        *rw = PR_FALSE;
   1294    }
   1295 
   1296    /* only use the renamed secmod for legacy databases */
   1297    if ((*dbType != NSS_DB_TYPE_LEGACY) &&
   1298        (*dbType != NSS_DB_TYPE_MULTIACCESS) &&
   1299        !NSSUTIL_ArgHasFlag("flags", "forceSecmodChoice", save_params)) {
   1300        secmodName = "pkcs11.txt";
   1301    }
   1302 
   1303    if (noModDB) {
   1304        value = NULL;
   1305    } else if (lconfigdir && lconfigdir[0] != '\0') {
   1306        value = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s",
   1307                            lconfigdir, secmodName);
   1308    } else {
   1309        value = PR_smprintf("%s", secmodName);
   1310    }
   1311    if (configdir)
   1312        PORT_Free(configdir);
   1313    return value;
   1314 }