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, ¶m, &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 }