multinit.c (24887B)
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 #include <stdio.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include "nss.h" 9 #include "secutil.h" 10 #include "pk11pub.h" 11 #include "cert.h" 12 13 typedef struct commandDescriptStr { 14 int required; 15 char *arg; 16 char *des; 17 } commandDescript; 18 19 enum optionNames { 20 opt_liborder = 0, 21 opt_mainDB, 22 opt_lib1DB, 23 opt_lib2DB, 24 opt_mainRO, 25 opt_lib1RO, 26 opt_lib2RO, 27 opt_mainCMD, 28 opt_lib1CMD, 29 opt_lib2CMD, 30 opt_mainTokNam, 31 opt_lib1TokNam, 32 opt_lib2TokNam, 33 opt_oldStyle, 34 opt_verbose, 35 opt_summary, 36 opt_help, 37 opt_last 38 }; 39 40 static const secuCommandFlag options_init[] = { 41 { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" }, 42 { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" }, 43 { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" }, 44 { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" }, 45 { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" }, 46 { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" }, 47 { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" }, 48 { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" }, 49 { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" }, 50 { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" }, 51 { /* opt_mainTokNam */ 't', PR_TRUE, 0, PR_FALSE, "main_token_name" }, 52 { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" }, 53 { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" }, 54 { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" }, 55 { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" }, 56 { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" }, 57 { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" } 58 }; 59 60 static const commandDescript options_des[] = { 61 { /* opt_liborder */ PR_FALSE, "initOrder", 62 " Specifies the order of NSS initialization and shutdown. Order is\n" 63 " given as a string where each character represents either an init or\n" 64 " a shutdown of the main program or one of the 2 test libraries\n" 65 " (library 1 and library 2). The valid characters are as follows:\n" 66 " M Init the main program\n 1 Init library 1\n" 67 " 2 Init library 2\n" 68 " m Shutdown the main program\n i Shutdown library 1\n" 69 " z Shutdown library 2\n" }, 70 { /* opt_mainDB */ PR_TRUE, "nss_db", 71 " Specified the directory to open the nss database for the main\n" 72 " program. Must be specified if \"M\" is given in the order string\n" }, 73 { /* opt_lib1DB */ PR_FALSE, "nss_db", 74 " Specified the directory to open the nss database for library 1.\n" 75 " Must be specified if \"1\" is given in the order string\n" }, 76 { /* opt_lib2DB */ PR_FALSE, "nss_db", 77 " Specified the directory to open the nss database for library 2.\n" 78 " Must be specified if \"2\" is given in the order string\n" }, 79 { /* opt_mainRO */ PR_FALSE, NULL, 80 " Open the main program's database read only.\n" }, 81 { /* opt_lib1RO */ PR_FALSE, NULL, 82 " Open library 1's database read only.\n" }, 83 { /* opt_lib2RO */ PR_FALSE, NULL, 84 " Open library 2's database read only.\n" }, 85 { /* opt_mainCMD */ PR_FALSE, "nss_command", 86 " Specifies the NSS command to execute in the main program.\n" 87 " Valid commands are: \n" 88 " key_slot, list_slots, list_certs, add_cert, none.\n" 89 " Default is \"none\".\n" }, 90 { /* opt_lib1CMD */ PR_FALSE, "nss_command", 91 " Specifies the NSS command to execute in library 1.\n" }, 92 { /* opt_lib2CMD */ PR_FALSE, "nss_command", 93 " Specifies the NSS command to execute in library 2.\n" }, 94 { /* opt_mainTokNam */ PR_FALSE, "token_name", 95 " Specifies the name of PKCS11 token for the main program's " 96 "database.\n" }, 97 { /* opt_lib1TokNam */ PR_FALSE, "token_name", 98 " Specifies the name of PKCS11 token for library 1's database.\n" }, 99 { /* opt_lib2TokNam */ PR_FALSE, "token_name", 100 " Specifies the name of PKCS11 token for library 2's database.\n" }, 101 { /* opt_oldStype */ PR_FALSE, NULL, 102 " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n" 103 " program.\n" }, 104 { /* opt_verbose */ PR_FALSE, NULL, 105 " Noisily output status to standard error\n" }, 106 { /* opt_summarize */ PR_FALSE, NULL, 107 "report a summary of the test results\n" }, 108 { /* opt_help */ PR_FALSE, NULL, " give this message\n" } 109 }; 110 111 /* 112 * output our short help (table driven). (does not exit). 113 */ 114 static void 115 short_help(const char *prog) 116 { 117 int count = opt_last; 118 int i, words_found; 119 120 /* make sure all the tables are up to date before we allow compiles to 121 * succeed */ 122 PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) == opt_last); 123 PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) == 124 sizeof(options_des) / sizeof(commandDescript)); 125 126 /* print the base usage */ 127 fprintf(stderr, "usage: %s ", prog); 128 for (i = 0, words_found = 0; i < count; i++) { 129 if (!options_des[i].required) { 130 fprintf(stderr, "["); 131 } 132 if (options_init[i].longform) { 133 fprintf(stderr, "--%s", options_init[i].longform); 134 words_found++; 135 } else { 136 fprintf(stderr, "-%c", options_init[i].flag); 137 } 138 if (options_init[i].needsArg) { 139 if (options_des[i].arg) { 140 fprintf(stderr, " %s", options_des[i].arg); 141 } else { 142 fprintf(stderr, " arg"); 143 } 144 words_found++; 145 } 146 if (!options_des[i].required) { 147 fprintf(stderr, "]"); 148 } 149 if (i < count - 1) { 150 if (words_found >= 5) { 151 fprintf(stderr, "\n "); 152 words_found = 0; 153 } else { 154 fprintf(stderr, " "); 155 } 156 } 157 } 158 fprintf(stderr, "\n"); 159 } 160 161 /* 162 * print out long help. like short_help, this does not exit 163 */ 164 static void 165 long_help(const char *prog) 166 { 167 int i; 168 int count = opt_last; 169 170 short_help(prog); 171 /* print the option descriptions */ 172 fprintf(stderr, "\n"); 173 for (i = 0; i < count; i++) { 174 fprintf(stderr, " "); 175 if (options_init[i].flag) { 176 fprintf(stderr, "-%c", options_init[i].flag); 177 if (options_init[i].longform) { 178 fprintf(stderr, ","); 179 } 180 } 181 if (options_init[i].longform) { 182 fprintf(stderr, "--%s", options_init[i].longform); 183 } 184 if (options_init[i].needsArg) { 185 if (options_des[i].arg) { 186 fprintf(stderr, " %s", options_des[i].arg); 187 } else { 188 fprintf(stderr, " arg"); 189 } 190 if (options_init[i].arg) { 191 fprintf(stderr, " (default = \"%s\")", options_init[i].arg); 192 } 193 } 194 fprintf(stderr, "\n%s", options_des[i].des); 195 } 196 } 197 198 /* 199 * record summary data 200 */ 201 struct bufferData { 202 char *data; /* lowest address of the buffer */ 203 char *next; /* pointer to the next element on the buffer */ 204 int len; /* length of the buffer */ 205 }; 206 207 /* our actual buffer. If data is NULL, then all append ops 208 * except are noops */ 209 static struct bufferData buffer = { NULL, NULL, 0 }; 210 211 #define CHUNK_SIZE 1000 212 213 /* 214 * get our initial data. and set the buffer variables up. on failure, 215 * just don't initialize the buffer. 216 */ 217 static void 218 initBuffer(void) 219 { 220 buffer.data = PORT_Alloc(CHUNK_SIZE); 221 if (!buffer.data) { 222 return; 223 } 224 buffer.next = buffer.data; 225 buffer.len = CHUNK_SIZE; 226 } 227 228 /* 229 * grow the buffer. If we can't get more data, record a 'D' in the second 230 * to last record and allow the rest of the data to overwrite the last 231 * element. 232 */ 233 static void 234 growBuffer(void) 235 { 236 char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE); 237 if (!new) { 238 buffer.data[buffer.len - 2] = 'D'; /* signal malloc failure in summary */ 239 /* buffer must always point to good memory if it exists */ 240 buffer.next = buffer.data + (buffer.len - 1); 241 return; 242 } 243 buffer.next = new + (buffer.next - buffer.data); 244 buffer.data = new; 245 buffer.len += CHUNK_SIZE; 246 } 247 248 /* 249 * append a label, doubles as appending a single character. 250 */ 251 static void 252 appendLabel(char label) 253 { 254 if (!buffer.data) { 255 return; 256 } 257 258 *buffer.next++ = label; 259 if (buffer.data + buffer.len >= buffer.next) { 260 growBuffer(); 261 } 262 } 263 264 /* 265 * append a string onto the buffer. The result will be <string> 266 */ 267 static void 268 appendString(char *string) 269 { 270 if (!buffer.data) { 271 return; 272 } 273 274 appendLabel('<'); 275 while (*string) { 276 appendLabel(*string++); 277 } 278 appendLabel('>'); 279 } 280 281 /* 282 * append a bool, T= true, F=false 283 */ 284 static void 285 appendBool(PRBool bool) 286 { 287 if (!buffer.data) { 288 return; 289 } 290 291 if (bool) { 292 appendLabel('t'); 293 } else { 294 appendLabel('f'); 295 } 296 } 297 298 /* 299 * append a single hex nibble. 300 */ 301 static void 302 appendHex(unsigned char nibble) 303 { 304 if (nibble <= 9) { 305 appendLabel('0' + nibble); 306 } else { 307 appendLabel('a' + nibble - 10); 308 } 309 } 310 311 /* 312 * append a 32 bit integer (even on a 64 bit platform). 313 * for simplicity append it as a hex value, full extension with 0x prefix. 314 */ 315 static void 316 appendInt(unsigned int value) 317 { 318 int i; 319 320 if (!buffer.data) { 321 return; 322 } 323 324 appendLabel('0'); 325 appendLabel('x'); 326 value = value & 0xffffffff; /* only look at the buttom 8 bytes */ 327 for (i = 0; i < 8; i++) { 328 appendHex(value >> 28); 329 value = value << 4; 330 } 331 } 332 333 /* append a trust flag */ 334 static void 335 appendFlags(unsigned int flag) 336 { 337 char trust[10]; 338 char *cp = trust; 339 340 trust[0] = 0; 341 printflags(trust, flag); 342 while (*cp) { 343 appendLabel(*cp++); 344 } 345 } 346 347 /* 348 * dump our buffer out with a result= flag so we can find it easily. 349 * free the buffer as a side effect. 350 */ 351 static void 352 dumpBuffer(void) 353 { 354 if (!buffer.data) { 355 return; 356 } 357 358 appendLabel(0); /* terminate */ 359 printf("\nresult=%s\n", buffer.data); 360 PORT_Free(buffer.data); 361 buffer.data = buffer.next = NULL; 362 buffer.len = 0; 363 } 364 365 /* 366 * usage, like traditional usage, automatically exit 367 */ 368 static void 369 usage(const char *prog) 370 { 371 short_help(prog); 372 dumpBuffer(); 373 exit(1); 374 } 375 376 /* 377 * like usage, except prints the long version of help 378 */ 379 static void 380 usage_long(const char *prog) 381 { 382 long_help(prog); 383 dumpBuffer(); 384 exit(1); 385 } 386 387 static const char * 388 bool2String(PRBool bool) 389 { 390 return bool ? "true" : "false"; 391 } 392 393 /* 394 * print out interesting info about the given slot 395 */ 396 void 397 print_slot(PK11SlotInfo *slot, int log) 398 { 399 if (log) { 400 fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n", 401 PK11_GetSlotName(slot), PK11_GetTokenName(slot), 402 bool2String(PK11_IsPresent(slot)), 403 bool2String(PK11_IsReadOnly(slot))); 404 } 405 appendLabel('S'); 406 appendString(PK11_GetTokenName(slot)); 407 appendBool(PK11_IsPresent(slot)); 408 appendBool(PK11_IsReadOnly(slot)); 409 } 410 411 /* 412 * list all our slots 413 */ 414 void 415 do_list_slots(const char *progName, int log) 416 { 417 PK11SlotList *list; 418 PK11SlotListElement *le; 419 420 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); 421 if (list == NULL) { 422 fprintf(stderr, "ERROR: no tokens found %s\n", 423 SECU_Strerror(PORT_GetError())); 424 appendLabel('S'); 425 appendString("none"); 426 return; 427 } 428 429 for (le = PK11_GetFirstSafe(list); le; 430 le = PK11_GetNextSafe(list, le, PR_TRUE)) { 431 print_slot(le->slot, log); 432 } 433 PK11_FreeSlotList(list); 434 } 435 436 static PRBool 437 sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg) 438 { 439 char *commonNameA, *commonNameB; 440 int ret; 441 442 commonNameA = CERT_GetCommonName(&certa->subject); 443 commonNameB = CERT_GetCommonName(&certb->subject); 444 445 if (commonNameA == NULL) { 446 PORT_Free(commonNameB); 447 return PR_TRUE; 448 } 449 if (commonNameB == NULL) { 450 PORT_Free(commonNameA); 451 return PR_FALSE; 452 } 453 ret = PORT_Strcmp(commonNameA, commonNameB); 454 PORT_Free(commonNameA); 455 PORT_Free(commonNameB); 456 return (ret < 0) ? PR_TRUE : PR_FALSE; 457 } 458 459 /* 460 * list all the certs 461 */ 462 void 463 do_list_certs(const char *progName, int log) 464 { 465 CERTCertList *list; 466 CERTCertList *sorted; 467 CERTCertListNode *node; 468 CERTCertTrust trust; 469 unsigned int i; 470 471 list = PK11_ListCerts(PK11CertListUnique, NULL); 472 if (list == NULL) { 473 fprintf(stderr, "ERROR: no certs found %s\n", 474 SECU_Strerror(PORT_GetError())); 475 appendLabel('C'); 476 appendString("none"); 477 return; 478 } 479 480 sorted = CERT_NewCertList(); 481 if (sorted == NULL) { 482 fprintf(stderr, "ERROR: no certs found %s\n", 483 SECU_Strerror(PORT_GetError())); 484 appendLabel('C'); 485 appendLabel('E'); 486 appendInt(PORT_GetError()); 487 return; 488 } 489 490 /* sort the list */ 491 for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); 492 node = CERT_LIST_NEXT(node)) { 493 CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL); 494 } 495 496 for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node, sorted); 497 node = CERT_LIST_NEXT(node)) { 498 CERTCertificate *cert = node->cert; 499 char *commonName; 500 501 SECU_PrintCertNickname(node, stderr); 502 if (log) { 503 fprintf(stderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot) : "none"); 504 fprintf(stderr, "* Nickname=%s*\n", cert->nickname); 505 fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName); 506 fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName); 507 fprintf(stderr, "* SN="); 508 for (i = 0; i < cert->serialNumber.len; i++) { 509 if (i != 0) 510 fprintf(stderr, ":"); 511 fprintf(stderr, "%02x", cert->serialNumber.data[0]); 512 } 513 fprintf(stderr, " *\n"); 514 } 515 appendLabel('C'); 516 commonName = CERT_GetCommonName(&cert->subject); 517 appendString(commonName ? commonName : "*NoName*"); 518 PORT_Free(commonName); 519 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) { 520 appendFlags(trust.sslFlags); 521 appendFlags(trust.emailFlags); 522 appendFlags(trust.objectSigningFlags); 523 } 524 } 525 CERT_DestroyCertList(list); 526 } 527 528 /* 529 * need to implement yet... try to add a new certificate 530 */ 531 void 532 do_add_cert(const char *progName, int log) 533 { 534 PORT_Assert(/* do_add_cert not implemented */ 0); 535 } 536 537 /* 538 * display the current key slot 539 */ 540 void 541 do_key_slot(const char *progName, int log) 542 { 543 PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 544 if (!slot) { 545 fprintf(stderr, "ERROR: no internal key slot found %s\n", 546 SECU_Strerror(PORT_GetError())); 547 appendLabel('K'); 548 appendLabel('S'); 549 appendString("none"); 550 } 551 print_slot(slot, log); 552 PK11_FreeSlot(slot); 553 } 554 555 /* 556 * execute some NSS command. 557 */ 558 void 559 do_command(const char *label, int initialized, secuCommandFlag *command, 560 const char *progName, int log) 561 { 562 char *command_string; 563 if (!initialized) { 564 return; 565 } 566 567 if (command->activated) { 568 command_string = command->arg; 569 } else { 570 command_string = "none"; 571 } 572 573 if (log) { 574 fprintf(stderr, "*Executing nss command \"%s\" for %s*\n", 575 command_string, label); 576 } 577 578 /* do something */ 579 if (PORT_Strcasecmp(command_string, "list_slots") == 0) { 580 do_list_slots(progName, log); 581 } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) { 582 do_list_certs(progName, log); 583 } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) { 584 do_add_cert(progName, log); 585 } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) { 586 do_key_slot(progName, log); 587 } else if (PORT_Strcasecmp(command_string, "none") != 0) { 588 fprintf(stderr, ">> Unknown command (%s)\n", command_string); 589 appendLabel('E'); 590 appendString("bc"); 591 usage_long(progName); 592 } 593 } 594 595 /* 596 * functions do handle 597 * different library initializations. 598 */ 599 static int main_initialized; 600 static int lib1_initialized; 601 static int lib2_initialized; 602 603 void 604 main_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 605 int readOnly, const char *progName, int log) 606 { 607 SECStatus rv; 608 if (log) { 609 fprintf(stderr, "*NSS_Init for the main program*\n"); 610 } 611 appendLabel('M'); 612 if (!db->activated) { 613 fprintf(stderr, ">> No main_db has been specified\n"); 614 usage(progName); 615 } 616 if (main_initialized) { 617 fprintf(stderr, "Warning: Second initialization of Main\n"); 618 appendLabel('E'); 619 appendString("2M"); 620 } 621 if (tokNam->activated) { 622 PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg, 623 NULL, NULL, NULL, NULL, 0, 0); 624 } 625 rv = NSS_Initialize(db->arg, "", "", "", 626 NSS_INIT_NOROOTINIT | 627 (readOnly ? NSS_INIT_READONLY : 0)); 628 if (rv != SECSuccess) { 629 appendLabel('E'); 630 appendInt(PORT_GetError()); 631 fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError())); 632 dumpBuffer(); 633 exit(1); 634 } 635 main_initialized = 1; 636 } 637 638 void 639 main_Do(secuCommandFlag *command, const char *progName, int log) 640 { 641 do_command("main", main_initialized, command, progName, log); 642 } 643 644 void 645 main_Shutdown(int old_style, const char *progName, int log) 646 { 647 SECStatus rv; 648 appendLabel('N'); 649 if (log) { 650 fprintf(stderr, "*NSS_Shutdown for the main program*\n"); 651 } 652 if (!main_initialized) { 653 fprintf(stderr, "Warning: Main shutdown without corresponding init\n"); 654 } 655 if (old_style) { 656 rv = NSS_Shutdown(); 657 } else { 658 rv = NSS_ShutdownContext(NULL); 659 } 660 fprintf(stderr, "Shutdown main state = %d\n", rv); 661 if (rv != SECSuccess) { 662 appendLabel('E'); 663 appendInt(PORT_GetError()); 664 fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError())); 665 } 666 main_initialized = 0; 667 } 668 669 /* common library init */ 670 NSSInitContext * 671 lib_Init(const char *lableString, char label, int initialized, 672 secuCommandFlag *db, secuCommandFlag *tokNam, int readonly, 673 const char *progName, int log) 674 { 675 NSSInitContext *ctxt; 676 NSSInitParameters initStrings; 677 NSSInitParameters *initStringPtr = NULL; 678 679 appendLabel(label); 680 if (log) { 681 fprintf(stderr, "*NSS_Init for %s*\n", lableString); 682 } 683 684 if (!db->activated) { 685 fprintf(stderr, ">> No %s_db has been specified\n", lableString); 686 usage(progName); 687 } 688 if (initialized) { 689 fprintf(stderr, "Warning: Second initialization of %s\n", lableString); 690 } 691 if (tokNam->activated) { 692 PORT_Memset(&initStrings, 0, sizeof(initStrings)); 693 initStrings.length = sizeof(initStrings); 694 initStrings.dbTokenDescription = tokNam->arg; 695 initStringPtr = &initStrings; 696 } 697 ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr, 698 NSS_INIT_NOROOTINIT | 699 (readonly ? NSS_INIT_READONLY : 0)); 700 if (ctxt == NULL) { 701 appendLabel('E'); 702 appendInt(PORT_GetError()); 703 fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError())); 704 dumpBuffer(); 705 exit(1); 706 } 707 return ctxt; 708 } 709 710 /* common library shutdown */ 711 void 712 lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx, 713 int initialize, const char *progName, int log) 714 { 715 SECStatus rv; 716 appendLabel(label); 717 if (log) { 718 fprintf(stderr, "*NSS_Shutdown for %s\n*", labelString); 719 } 720 if (!initialize) { 721 fprintf(stderr, "Warning: %s shutdown without corresponding init\n", 722 labelString); 723 } 724 rv = NSS_ShutdownContext(ctx); 725 fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv); 726 if (rv != SECSuccess) { 727 appendLabel('E'); 728 appendInt(PORT_GetError()); 729 fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError())); 730 } 731 } 732 733 static NSSInitContext *lib1_context; 734 static NSSInitContext *lib2_context; 735 void 736 lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 737 int readOnly, const char *progName, int log) 738 { 739 lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam, 740 readOnly, progName, log); 741 lib1_initialized = 1; 742 } 743 744 void 745 lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 746 int readOnly, const char *progName, int log) 747 { 748 lib2_context = lib_Init("lib2", '2', lib2_initialized, 749 db, tokNam, readOnly, progName, log); 750 lib2_initialized = 1; 751 } 752 753 void 754 lib1_Do(secuCommandFlag *command, const char *progName, int log) 755 { 756 do_command("lib1", lib1_initialized, command, progName, log); 757 } 758 759 void 760 lib2_Do(secuCommandFlag *command, const char *progName, int log) 761 { 762 do_command("lib2", lib2_initialized, command, progName, log); 763 } 764 765 void 766 lib1_Shutdown(const char *progName, int log) 767 { 768 lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log); 769 lib1_initialized = 0; 770 /* don't clear lib1_Context, so we can test multiple attempts to close 771 * the same context produces correct errors*/ 772 } 773 774 void 775 lib2_Shutdown(const char *progName, int log) 776 { 777 lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log); 778 lib2_initialized = 0; 779 /* don't clear lib2_Context, so we can test multiple attempts to close 780 * the same context produces correct errors*/ 781 } 782 783 int 784 main(int argc, char **argv) 785 { 786 SECStatus rv; 787 secuCommand libinit; 788 char *progName; 789 char *order; 790 secuCommandFlag *options; 791 int log = 0; 792 793 progName = strrchr(argv[0], '/'); 794 progName = progName ? progName + 1 : argv[0]; 795 796 libinit.numCommands = 0; 797 libinit.commands = 0; 798 libinit.numOptions = opt_last; 799 options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init)); 800 if (options == NULL) { 801 fprintf(stderr, ">> %s:Not enough free memory to run command\n", 802 progName); 803 exit(1); 804 } 805 PORT_Memcpy(options, options_init, sizeof(options_init)); 806 libinit.options = options; 807 808 rv = SECU_ParseCommandLine(argc, argv, progName, &libinit); 809 if (rv != SECSuccess) { 810 usage(progName); 811 } 812 813 if (libinit.options[opt_help].activated) { 814 long_help(progName); 815 exit(0); 816 } 817 818 log = libinit.options[opt_verbose].activated; 819 if (libinit.options[opt_summary].activated) { 820 initBuffer(); 821 } 822 823 order = libinit.options[opt_liborder].arg; 824 if (!order) { 825 usage(progName); 826 } 827 828 if (log) { 829 fprintf(stderr, "* initializing with order \"%s\"*\n", order); 830 } 831 832 for (; *order; order++) { 833 switch (*order) { 834 case 'M': 835 main_Init(&libinit.options[opt_mainDB], 836 &libinit.options[opt_mainTokNam], 837 libinit.options[opt_mainRO].activated, 838 progName, log); 839 break; 840 case '1': 841 lib1_Init(&libinit.options[opt_lib1DB], 842 &libinit.options[opt_lib1TokNam], 843 libinit.options[opt_lib1RO].activated, 844 progName, log); 845 break; 846 case '2': 847 lib2_Init(&libinit.options[opt_lib2DB], 848 &libinit.options[opt_lib2TokNam], 849 libinit.options[opt_lib2RO].activated, 850 progName, log); 851 break; 852 case 'm': 853 main_Shutdown(libinit.options[opt_oldStyle].activated, 854 progName, log); 855 break; 856 case 'i': 857 lib1_Shutdown(progName, log); 858 break; 859 case 'z': 860 lib2_Shutdown(progName, log); 861 break; 862 default: 863 fprintf(stderr, ">> Unknown init/shutdown command \"%c\"", *order); 864 usage_long(progName); 865 } 866 main_Do(&libinit.options[opt_mainCMD], progName, log); 867 lib1_Do(&libinit.options[opt_lib1CMD], progName, log); 868 lib2_Do(&libinit.options[opt_lib2CMD], progName, log); 869 } 870 871 if (NSS_IsInitialized()) { 872 appendLabel('X'); 873 fprintf(stderr, "Warning: NSS is initialized\n"); 874 } 875 dumpBuffer(); 876 877 exit(0); 878 }