util.c (30205B)
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 "signtool.h" 6 #include "prio.h" 7 #include "prmem.h" 8 #include "prenv.h" 9 #include "nss.h" 10 11 static int is_dir(char *filename); 12 13 /*********************************************************** 14 * Nasty hackish function definitions 15 */ 16 17 long *mozilla_event_queue = 0; 18 19 #ifndef XP_WIN 20 char * 21 XP_GetString(int i) 22 { 23 /* nasty hackish cast to avoid changing the signature of 24 * JAR_init_callbacks() */ 25 return (char *)SECU_Strerror(i); 26 } 27 #endif 28 29 void 30 FE_SetPasswordEnabled() 31 { 32 } 33 34 void /*MWContext*/ * 35 FE_GetInitContext(void) 36 { 37 return 0; 38 } 39 40 void /*MWContext*/ * 41 XP_FindSomeContext() 42 { 43 /* No windows context in command tools */ 44 return NULL; 45 } 46 47 void 48 ET_moz_CallFunction() 49 { 50 } 51 52 /* 53 * R e m o v e A l l A r c 54 * 55 * Remove .arc directories that are lingering 56 * from a previous run of signtool. 57 * 58 */ 59 int 60 RemoveAllArc(char *tree) 61 { 62 PRDir *dir; 63 PRDirEntry *entry; 64 char *archive = NULL; 65 int retval = 0; 66 67 dir = PR_OpenDir(tree); 68 if (!dir) 69 return -1; 70 71 for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir, 72 0)) { 73 74 if (entry->name[0] == '.') { 75 continue; 76 } 77 78 if (archive) 79 PR_Free(archive); 80 archive = PR_smprintf("%s/%s", tree, entry->name); 81 82 if (PL_strcaserstr(entry->name, ".arc") == 83 (entry->name + strlen(entry->name) - 4)) { 84 85 if (verbosity >= 0) { 86 PR_fprintf(outputFD, "removing: %s\n", archive); 87 } 88 89 if (rm_dash_r(archive)) { 90 PR_fprintf(errorFD, "Error removing %s\n", archive); 91 errorCount++; 92 retval = -1; 93 goto finish; 94 } 95 } else if (is_dir(archive)) { 96 if (RemoveAllArc(archive)) { 97 retval = -1; 98 goto finish; 99 } 100 } 101 } 102 103 finish: 104 PR_CloseDir(dir); 105 if (archive) 106 PR_Free(archive); 107 108 return retval; 109 } 110 111 /* 112 * r m _ d a s h _ r 113 * 114 * Remove a file, or a directory recursively. 115 * 116 */ 117 int 118 rm_dash_r(char *path) 119 { 120 PRDir *dir; 121 PRDirEntry *entry; 122 PRFileInfo fileinfo; 123 char filename[FNSIZE]; 124 125 if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) { 126 /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/ 127 return -1; 128 } 129 if (fileinfo.type == PR_FILE_DIRECTORY) { 130 131 dir = PR_OpenDir(path); 132 if (!dir) { 133 PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path); 134 errorCount++; 135 return -1; 136 } 137 138 /* Recursively delete all entries in the directory */ 139 while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) { 140 snprintf(filename, sizeof(filename), "%s/%s", path, entry->name); 141 if (rm_dash_r(filename)) { 142 PR_CloseDir(dir); 143 return -1; 144 } 145 } 146 147 if (PR_CloseDir(dir) != PR_SUCCESS) { 148 PR_fprintf(errorFD, "Error: Could not close %s.\n", path); 149 errorCount++; 150 return -1; 151 } 152 153 /* Delete the directory itself */ 154 if (PR_RmDir(path) != PR_SUCCESS) { 155 PR_fprintf(errorFD, "Error: Unable to delete %s\n", path); 156 errorCount++; 157 return -1; 158 } 159 } else { 160 if (PR_Delete(path) != PR_SUCCESS) { 161 PR_fprintf(errorFD, "Error: Unable to delete %s\n", path); 162 errorCount++; 163 return -1; 164 } 165 } 166 return 0; 167 } 168 169 /* 170 * u s a g e 171 * 172 * Print some useful help information 173 * 174 */ 175 176 void 177 Usage(void) 178 { 179 #define FPS PR_fprintf(outputFD, 180 FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION); 181 FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME); 182 FPS "\nUsage: %s -k keyName [-b basename] [-c Compression Level]\n" 183 "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n" 184 "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n" 185 "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n" 186 "\t\t [-p password] directory-tree\n", PROGRAM_NAME); 187 FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n" 188 "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n" 189 "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n" 190 "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n" 191 "\t\t directory-tree\n", PROGRAM_NAME); 192 FPS "\t%s -h \n", PROGRAM_NAME); 193 FPS "\t%s -H \n", PROGRAM_NAME); 194 FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME); 195 FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME); 196 FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME); 197 FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME); 198 FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME); 199 FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n" 200 "\t\t [--outfile] [-O] \n", PROGRAM_NAME); 201 FPS "\t%s -f filename\n" , PROGRAM_NAME); 202 exit(ERRX); 203 } 204 205 void 206 LongUsage(void) 207 { 208 FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION); 209 FPS "\n%-20s Signs the directory-tree\n", 210 "signtool directory-tree"); 211 FPS "%-30s Nickname (key) of the certificate to sign with\n", 212 " -k keyname"); 213 FPS "%-30s Base filename for the .rsa and.sf files in the\n", 214 " -b basename"); 215 FPS "%-30s META-INF directory\n"," "); 216 FPS "%-30s Set the compression level. 0-9, 0=none\n", 217 " -c CompressionLevel"); 218 FPS "%-30s Certificate database directory containing cert*db\n", 219 " -d certificate directory"); 220 FPS "%-30s and key*db\n"," "); 221 FPS "%-30s Name of the installer script for SmartUpdate\n", 222 " -i installer script"); 223 FPS "%-30s Name of a metadata control file\n", 224 " -m metafile"); 225 FPS "%-30s For optimizing the archive for size.\n", 226 " -o"); 227 FPS "%-30s Omit Optional Headers\n"," "); 228 FPS "%-30s Excludes the specified directory or file from\n", 229 " -x directory or file name"); 230 FPS "%-30s signing\n"," "); 231 FPS "%-30s To not store the signing time in digital\n", 232 " -z directory or file name"); 233 FPS "%-30s signature\n"," "); 234 FPS "%-30s Create XPI Compatible Archive. It requires -Z\n", 235 " -X directory or file name"); 236 FPS "%-30s option\n"," "); 237 FPS "%-30s Sign only files with the given extension\n", 238 " -e"); 239 FPS "%-30s Causes the specified directory to be signed and\n", 240 " -j"); 241 FPS "%-30s tags its entries as inline JavaScript\n"," "); 242 FPS "%-30s Creates a JAR file with the specified name.\n", 243 " -Z"); 244 FPS "%-30s -Z option cannot be used with -J option\n"," "); 245 FPS "%-30s Specifies a password for the private-key database\n", 246 " -p"); 247 FPS "%-30s (insecure)\n"," "); 248 FPS "%-30s File to receive redirected output\n", 249 " --outfile filename"); 250 FPS "%-30s Sets the quantity of information generated in\n", 251 " --verbosity value"); 252 FPS "%-30s operation\n"," "); 253 FPS "%-30s Blocks recursion into subdirectories\n", 254 " --norecurse"); 255 FPS "%-30s Retains the temporary .arc (archive) directories\n", 256 " --leavearc"); 257 FPS "%-30s -J option creates\n"," "); 258 259 FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n", 260 "-J" ); 261 FPS "%-20s creates as many archive files as are in the HTML tags.\n"," "); 262 263 FPS "%-20s The options are same as without any command option given\n"," "); 264 FPS "%-20s above. -Z and -J options are not allowed together\n"," "); 265 266 FPS "\n%-20s Generates a new private-public key pair and corresponding\n", 267 "-G nickname"); 268 FPS "%-20s object-signing certificates with the given nickname\n"," "); 269 FPS "%-30s Specifies the size of the key for generated \n", 270 " --keysize|-s keysize"); 271 FPS "%-30s certificate\n"," "); 272 FPS "%-30s Specifies which available token should generate\n", 273 " --token|-t token name "); 274 FPS "%-30s the key and receive the certificate\n"," "); 275 FPS "%-30s Specifies a file to receive redirected output\n", 276 " --outfile filename "); 277 278 FPS "\n%-20s Display signtool help\n", 279 "-h "); 280 281 FPS "\n%-20s Display signtool help(Detailed)\n", 282 "-H "); 283 284 FPS "\n%-20s Lists signing certificates, including issuing CAs\n", 285 "-l "); 286 FPS "%-30s Certificate database directory containing cert*db\n", 287 " -d certificate directory"); 288 FPS "%-30s and key*db\n"," "); 289 290 FPS "%-30s Specifies a file to receive redirected output\n", 291 " --outfile filename "); 292 FPS "%-30s Specifies the nickname (key) of the certificate\n", 293 " -k keyname"); 294 295 FPS "\n%-20s Lists the certificates in your database\n", 296 "-L "); 297 FPS "%-30s Certificate database directory containing cert*db\n", 298 " -d certificate directory"); 299 FPS "%-30s and key*db\n"," "); 300 301 FPS "%-30s Specifies a file to receive redirected output\n", 302 " --outfile filename "); 303 FPS "%-30s Specifies the nickname (key) of the certificate\n", 304 " -k keyname"); 305 306 FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n", 307 "-M "); 308 309 FPS "\n%-20s Displays the contents of an archive and verifies\n", 310 "-v archive"); 311 FPS "%-20s cryptographic integrity\n"," "); 312 FPS "%-30s Certificate database directory containing cert*db\n", 313 " -d certificate directory"); 314 FPS "%-30s and key*db\n"," "); 315 FPS "%-30s Specifies a file to receive redirected output\n", 316 " --outfile filename "); 317 318 FPS "\n%-20s Displays the names of signers in the archive\n", 319 "-w archive"); 320 FPS "%-30s Specifies a file to receive redirected output\n", 321 " --outfile filename "); 322 323 FPS "\n%-30s Common option to all the above.\n", 324 " -O"); 325 FPS "%-30s Enable OCSP checking\n"," "); 326 327 FPS "\n%-20s Specifies a text file containing options and arguments in\n", 328 "-f command-file"); 329 FPS "%-20s keyword=value format. Commands are taken from this file\n"," "); 330 331 FPS "\n\n\n"); 332 FPS "Example:\n"); 333 FPS "%-10s -d \"certificate directory\" -k \"certnickname\" \\", 334 PROGRAM_NAME); 335 FPS "\n%-10s -p \"password\" -X -Z \"file.xpi\" directory-tree\n"," " ); 336 FPS "Common syntax to create an XPInstall compatible" 337 " signed archive\n\n"," "); 338 FPS "\nCommand File Keywords and Example:\n"); 339 FPS "\nKeyword\t\tValue\n"); 340 FPS "basename\tSame as -b option\n"); 341 FPS "compression\tSame as -c option\n"); 342 FPS "certdir\t\tSame as -d option\n"); 343 FPS "extension\tSame as -e option\n"); 344 FPS "generate\tSame as -G option\n"); 345 FPS "installscript\tSame as -i option\n"); 346 FPS "javascriptdir\tSame as -j option\n"); 347 FPS "htmldir\t\tSame as -J option\n"); 348 FPS "certname\tNickname of certificate, as with -k option\n"); 349 FPS "signdir\t\tThe directory to be signed, as with -k option\n"); 350 FPS "list\t\tSame as -l option. Value is ignored,\n" 351 " \t\tbut = sign must be present\n"); 352 FPS "listall\t\tSame as -L option. Value is ignored\n" 353 " \t\tbut = sign must be present\n"); 354 FPS "metafile\tSame as -m option\n"); 355 FPS "modules\t\tSame as -M option. Value is ignored,\n" 356 " \t\tbut = sign must be present\n"); 357 FPS "optimize\tSame as -o option. Value is ignored,\n" 358 " \tbut = sign must be present\n"); 359 FPS "ocsp\t\tSame as -O option\n"); 360 FPS "password\tSame as -p option\n"); 361 FPS "verify\t\tSame as -v option\n"); 362 FPS "who\t\tSame as -w option\n"); 363 FPS "exclude\t\tSame as -x option\n"); 364 FPS "notime\t\tSame as -z option. Value is ignored,\n" 365 " \t\tbut = sign must be present\n"); 366 FPS "jarfile\t\tSame as -Z option\n"); 367 FPS "outfile\t\tSame as --outfile option. The argument\n"); 368 FPS " \t\tis the name of a file to which output\n"); 369 FPS " \t\tof a file and error messages will be \n"); 370 FPS " \t\tredirected\n"); 371 FPS "leavearc\tSame as --leavearc option\n"); 372 FPS "verbosity\tSame as --verbosity option\n"); 373 FPS "keysize\t\tSame as -s option\n"); 374 FPS "token\t\tSame as -t option\n"); 375 FPS "xpi\t\tSame as -X option\n"); 376 FPS "\n\n"); 377 FPS "Here's an example of the use of the command file. The command\n\n"); 378 FPS " signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n" 379 " signdir > output.txt\n\n"); 380 FPS "becomes\n\n"); 381 FPS " signtool -f somefile\n\n"); 382 FPS "where somefile contains the following lines:\n\n"); 383 FPS " certdir=c:\\netscape\\users\\james\n"," "); 384 FPS " certname=mycert\n"," "); 385 FPS " jarfile=myjar.jar\n"," "); 386 FPS " signdir=signdir\n"," "); 387 FPS " outfile=output.txt\n"," "); 388 exit(ERRX); 389 #undef FPS 390 } 391 392 /* 393 * p r i n t _ e r r o r 394 * 395 * For the undocumented -E function. If an older version 396 * of communicator gives you a numeric error, we can see what 397 * really happened without doing hex math. 398 * 399 */ 400 401 void 402 print_error(int err) 403 { 404 PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error(err)); 405 errorCount++; 406 give_help(err); 407 } 408 409 /* 410 * o u t _ o f _ m e m o r y 411 * 412 * Out of memory, exit Signtool. 413 * 414 */ 415 void 416 out_of_memory(void) 417 { 418 PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME); 419 errorCount++; 420 exit(ERRX); 421 } 422 423 /* 424 * V e r i f y C e r t D i r 425 * 426 * Validate that the specified directory 427 * contains a certificate database 428 * 429 */ 430 void 431 VerifyCertDir(char *dir, char *keyName) 432 { 433 /* this function is truly evil. Tools and applications should not have 434 * any knowledge of actual cert databases! */ 435 return; 436 } 437 438 /* 439 * f o r e a c h 440 * 441 * A recursive function to loop through all names in 442 * the specified directory, as well as all subdirectories. 443 * 444 * FIX: Need to see if all platforms allow multiple 445 * opendir's to be called. 446 * 447 */ 448 449 int foreach (char *dirname, char *prefix, 450 int (*fn)(char *relpath, char *basedir, char *reldir, char *filename, 451 void *arg), 452 PRBool recurse, PRBool includeDirs, void *arg) 453 { 454 char newdir[FNSIZE]; 455 int retval = 0; 456 457 PRDir *dir; 458 PRDirEntry *entry; 459 460 strcpy(newdir, dirname); 461 if (*prefix) { 462 strcat(newdir, "/"); 463 strcat(newdir, prefix); 464 } 465 466 dir = PR_OpenDir(newdir); 467 if (!dir) 468 return -1; 469 470 for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir, 0)) { 471 if (strcmp(entry->name, ".") == 0 || 472 strcmp(entry->name, "..") == 0) { 473 /* no infinite recursion, please */ 474 continue; 475 } 476 477 /* can't sign self */ 478 if (!strcmp(entry->name, "META-INF")) 479 continue; 480 481 /* -x option */ 482 if (PL_HashTableLookup(excludeDirs, entry->name)) 483 continue; 484 485 strcpy(newdir, dirname); 486 if (*dirname) 487 strcat(newdir, "/"); 488 489 if (*prefix) { 490 strcat(newdir, prefix); 491 strcat(newdir, "/"); 492 } 493 strcat(newdir, entry->name); 494 495 if (!is_dir(newdir) || includeDirs) { 496 char newpath[FNSIZE]; 497 498 strcpy(newpath, prefix); 499 if (*newpath) 500 strcat(newpath, "/"); 501 strcat(newpath, entry->name); 502 503 if ((*fn)(newpath, dirname, prefix, (char *)entry->name, 504 arg)) { 505 retval = -1; 506 break; 507 } 508 } 509 510 if (is_dir(newdir)) { 511 if (recurse) { 512 char newprefix[FNSIZE]; 513 514 strcpy(newprefix, prefix); 515 if (*newprefix) { 516 strcat(newprefix, "/"); 517 } 518 strcat(newprefix, entry->name); 519 520 if (foreach (dirname, newprefix, fn, recurse, 521 includeDirs, arg)) { 522 retval = -1; 523 break; 524 } 525 } 526 } 527 } 528 529 PR_CloseDir(dir); 530 531 return retval; 532 } 533 534 /* 535 * i s _ d i r 536 * 537 * Return 1 if file is a directory. 538 * Wonder if this runs on a mac, trust not. 539 * 540 */ 541 static int 542 is_dir(char *filename) 543 { 544 PRFileInfo finfo; 545 546 if (PR_GetFileInfo(filename, &finfo) != PR_SUCCESS) { 547 printf("Unable to get information about %s\n", filename); 548 return 0; 549 } 550 551 return (finfo.type == PR_FILE_DIRECTORY); 552 } 553 554 /*************************************************************** 555 * 556 * s e c E r r o r S t r i n g 557 * 558 * Returns an error string corresponding to the given error code. 559 * Doesn't cover all errors; returns a default for many. 560 * Returned string is only valid until the next call of this function. 561 */ 562 const char * 563 secErrorString(long code) 564 { 565 static char errstring[80]; /* dynamically constructed error string */ 566 char *c; /* the returned string */ 567 568 switch (code) { 569 case SEC_ERROR_IO: 570 c = "io error"; 571 break; 572 case SEC_ERROR_LIBRARY_FAILURE: 573 c = "security library failure"; 574 break; 575 case SEC_ERROR_BAD_DATA: 576 c = "bad data"; 577 break; 578 case SEC_ERROR_OUTPUT_LEN: 579 c = "output length"; 580 break; 581 case SEC_ERROR_INPUT_LEN: 582 c = "input length"; 583 break; 584 case SEC_ERROR_INVALID_ARGS: 585 c = "invalid args"; 586 break; 587 case SEC_ERROR_EXPIRED_CERTIFICATE: 588 c = "expired certificate"; 589 break; 590 case SEC_ERROR_REVOKED_CERTIFICATE: 591 c = "revoked certificate"; 592 break; 593 case SEC_ERROR_INADEQUATE_KEY_USAGE: 594 c = "inadequate key usage"; 595 break; 596 case SEC_ERROR_INADEQUATE_CERT_TYPE: 597 c = "inadequate certificate type"; 598 break; 599 case SEC_ERROR_UNTRUSTED_CERT: 600 c = "untrusted cert"; 601 break; 602 case SEC_ERROR_NO_KRL: 603 c = "no key revocation list"; 604 break; 605 case SEC_ERROR_KRL_BAD_SIGNATURE: 606 c = "key revocation list: bad signature"; 607 break; 608 case SEC_ERROR_KRL_EXPIRED: 609 c = "key revocation list expired"; 610 break; 611 case SEC_ERROR_REVOKED_KEY: 612 c = "revoked key"; 613 break; 614 case SEC_ERROR_CRL_BAD_SIGNATURE: 615 c = "certificate revocation list: bad signature"; 616 break; 617 case SEC_ERROR_CRL_EXPIRED: 618 c = "certificate revocation list expired"; 619 break; 620 case SEC_ERROR_CRL_NOT_YET_VALID: 621 c = "certificate revocation list not yet valid"; 622 break; 623 case SEC_ERROR_UNKNOWN_ISSUER: 624 c = "unknown issuer"; 625 break; 626 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 627 c = "expired issuer certificate"; 628 break; 629 case SEC_ERROR_BAD_SIGNATURE: 630 c = "bad signature"; 631 break; 632 case SEC_ERROR_BAD_KEY: 633 c = "bad key"; 634 break; 635 case SEC_ERROR_NOT_FORTEZZA_ISSUER: 636 c = "not fortezza issuer"; 637 break; 638 case SEC_ERROR_CA_CERT_INVALID: 639 c = "Certificate Authority certificate invalid"; 640 break; 641 case SEC_ERROR_EXTENSION_NOT_FOUND: 642 c = "extension not found"; 643 break; 644 case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 645 c = "certificate not in name space"; 646 break; 647 case SEC_ERROR_UNTRUSTED_ISSUER: 648 c = "untrusted issuer"; 649 break; 650 default: 651 snprintf(errstring, sizeof(errstring), "security error %ld", code); 652 c = errstring; 653 break; 654 } 655 656 return c; 657 } 658 659 /*************************************************************** 660 * 661 * d i s p l a y V e r i f y L o g 662 * 663 * Prints the log of a cert verification. 664 */ 665 void 666 displayVerifyLog(CERTVerifyLog *log) 667 { 668 CERTVerifyLogNode *node; 669 CERTCertificate *cert; 670 char *name; 671 672 if (!log || (log->count <= 0)) { 673 return; 674 } 675 676 for (node = log->head; node != NULL; node = node->next) { 677 678 if (!(cert = node->cert)) { 679 continue; 680 } 681 682 /* Get a name for this cert */ 683 if (cert->nickname != NULL) { 684 name = cert->nickname; 685 } else if (cert->emailAddr && cert->emailAddr[0]) { 686 name = cert->emailAddr; 687 } else { 688 name = cert->subjectName; 689 } 690 691 printf("%s%s:\n", name, 692 (node->depth > 0) ? " [Certificate Authority]" : ""); 693 694 printf("\t%s\n", secErrorString(node->error)); 695 } 696 } 697 698 /* 699 * J a r L i s t M o d u l e s 700 * 701 * Print a list of the PKCS11 modules that are 702 * available. This is useful for smartcard people to 703 * make sure they have the drivers loaded. 704 * 705 */ 706 void 707 JarListModules(void) 708 { 709 int i; 710 int count = 0; 711 712 SECMODModuleList *modules = NULL; 713 static SECMODListLock *moduleLock = NULL; 714 715 SECMODModuleList *mlp; 716 717 if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) { 718 /* this is the wrong text */ 719 PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n", 720 PROGRAM_NAME); 721 errorCount++; 722 exit(ERRX); 723 } 724 725 SECMOD_GetReadLock(moduleLock); 726 727 modules = SECMOD_GetDefaultModuleList(); 728 729 if (modules == NULL) { 730 SECMOD_ReleaseReadLock(moduleLock); 731 PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME); 732 errorCount++; 733 exit(ERRX); 734 } 735 736 PR_fprintf(outputFD, "\nListing of PKCS11 modules\n"); 737 PR_fprintf(outputFD, "-----------------------------------------------\n"); 738 739 for (mlp = modules; mlp != NULL; mlp = mlp->next) { 740 count++; 741 PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName); 742 743 if (mlp->module->internal) 744 PR_fprintf(outputFD, " (this module is internally loaded)\n"); 745 else 746 PR_fprintf(outputFD, " (this is an external module)\n"); 747 748 if (mlp->module->dllName) 749 PR_fprintf(outputFD, " DLL name: %s\n", 750 mlp->module->dllName); 751 752 if (mlp->module->slotCount == 0) 753 PR_fprintf(outputFD, " slots: There are no slots attached to this module\n"); 754 else 755 PR_fprintf(outputFD, " slots: %d slots attached\n", 756 mlp->module->slotCount); 757 758 if (mlp->module->loaded == 0) 759 PR_fprintf(outputFD, " status: Not loaded\n"); 760 else 761 PR_fprintf(outputFD, " status: loaded\n"); 762 763 for (i = 0; i < mlp->module->slotCount; i++) { 764 PK11SlotInfo *slot = mlp->module->slots[i]; 765 766 PR_fprintf(outputFD, "\n"); 767 PR_fprintf(outputFD, " slot: %s\n", PK11_GetSlotName(slot)); 768 PR_fprintf(outputFD, " token: %s\n", PK11_GetTokenName(slot)); 769 } 770 } 771 772 PR_fprintf(outputFD, "-----------------------------------------------\n"); 773 774 if (count == 0) 775 PR_fprintf(outputFD, 776 "Warning: no modules were found (should have at least one)\n"); 777 778 SECMOD_ReleaseReadLock(moduleLock); 779 } 780 781 /********************************************************************** 782 * c h o p 783 * 784 * Eliminates leading and trailing whitespace. Returns a pointer to the 785 * beginning of non-whitespace, or an empty string if it's all whitespace. 786 */ 787 char * 788 chop(char *str) 789 { 790 char *start, *end; 791 792 if (str) { 793 start = str; 794 795 /* Nip leading whitespace */ 796 while (isspace((unsigned char)*start)) { 797 start++; 798 } 799 800 /* Nip trailing whitespace */ 801 if (*start) { 802 end = start + strlen(start) - 1; 803 while (isspace((unsigned char)*end) && end > start) { 804 end--; 805 } 806 *(end + 1) = '\0'; 807 } 808 809 return start; 810 } else { 811 return NULL; 812 } 813 } 814 815 /*********************************************************************** 816 * 817 * F a t a l E r r o r 818 * 819 * Outputs an error message and bails out of the program. 820 */ 821 void 822 FatalError(char *msg) 823 { 824 if (!msg) 825 msg = ""; 826 827 PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg); 828 errorCount++; 829 exit(ERRX); 830 } 831 832 /************************************************************************* 833 * 834 * I n i t C r y p t o 835 */ 836 int 837 InitCrypto(char *cert_dir, PRBool readOnly) 838 { 839 SECStatus rv; 840 static int prior = 0; 841 PK11SlotInfo *slotinfo; 842 843 if (prior == 0) { 844 /* some functions such as OpenKeyDB expect this path to be 845 * implicitly set prior to calling */ 846 if (readOnly) { 847 rv = NSS_Init(cert_dir); 848 } else { 849 rv = NSS_InitReadWrite(cert_dir); 850 } 851 if (rv != SECSuccess) { 852 SECU_PrintPRandOSError(PROGRAM_NAME); 853 exit(-1); 854 } 855 856 SECU_ConfigDirectory(cert_dir); 857 858 /* Been there done that */ 859 prior++; 860 861 PK11_SetPasswordFunc(SECU_GetModulePassword); 862 863 /* Must login to FIPS before you do anything else */ 864 if (PK11_IsFIPS()) { 865 slotinfo = PK11_GetInternalSlot(); 866 if (!slotinfo) { 867 fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot." 868 "\n", 869 PROGRAM_NAME); 870 return -1; 871 } 872 if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/, 873 &pwdata) != SECSuccess) { 874 fprintf(stderr, "%s: Unable to authenticate to %s.\n", 875 PROGRAM_NAME, PK11_GetSlotName(slotinfo)); 876 PK11_FreeSlot(slotinfo); 877 return -1; 878 } 879 PK11_FreeSlot(slotinfo); 880 } 881 882 /* Make sure there is a password set on the internal key slot */ 883 slotinfo = PK11_GetInternalKeySlot(); 884 if (!slotinfo) { 885 fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot." 886 "\n", 887 PROGRAM_NAME); 888 return -1; 889 } 890 if (PK11_NeedUserInit(slotinfo)) { 891 PR_fprintf(errorFD, 892 "\nWARNING: No password set on internal key database. Most operations will fail." 893 "\nYou must create a password.\n"); 894 warningCount++; 895 } 896 897 /* Make sure we can authenticate to the key slot in FIPS mode */ 898 if (PK11_IsFIPS()) { 899 if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/, 900 &pwdata) != SECSuccess) { 901 fprintf(stderr, "%s: Unable to authenticate to %s.\n", 902 PROGRAM_NAME, PK11_GetSlotName(slotinfo)); 903 PK11_FreeSlot(slotinfo); 904 return -1; 905 } 906 } 907 PK11_FreeSlot(slotinfo); 908 } 909 910 return 0; 911 } 912 913 /* Windows foolishness is now in the secutil lib */ 914 915 /***************************************************************** 916 * g e t _ d e f a u l t _ c e r t _ d i r 917 * 918 * Attempt to locate a certificate directory. 919 * Failing that, complain that the user needs to 920 * use the -d(irectory) parameter. 921 * 922 */ 923 char * 924 get_default_cert_dir(void) 925 { 926 char *home; 927 928 char *cd = NULL; 929 static char db[FNSIZE]; 930 931 #ifdef XP_UNIX 932 home = PR_GetEnvSecure("HOME"); 933 934 if (home && *home) { 935 snprintf(db, sizeof(db), "%s/.netscape", home); 936 cd = db; 937 } 938 #endif 939 940 #ifdef XP_PC 941 FILE *fp; 942 943 /* first check the environment override */ 944 945 home = PR_GetEnvSecure("JAR_HOME"); 946 947 if (home && *home) { 948 snprintf(db, sizeof(db), "%s/cert7.db", home); 949 950 if ((fp = fopen(db, "r")) != NULL) { 951 fclose(fp); 952 cd = home; 953 } 954 } 955 956 /* try the old navigator directory */ 957 958 if (cd == NULL) { 959 home = "c:/Program Files/Netscape/Navigator"; 960 961 snprintf(db, sizeof(db), "%s/cert7.db", home); 962 963 if ((fp = fopen(db, "r")) != NULL) { 964 fclose(fp); 965 cd = home; 966 } 967 } 968 969 /* Try the current directory, I wonder if this 970 is really a good idea. Remember, Windows only.. */ 971 972 if (cd == NULL) { 973 home = "."; 974 975 snprintf(db, sizeof(db), "%s/cert7.db", home); 976 977 if ((fp = fopen(db, "r")) != NULL) { 978 fclose(fp); 979 cd = home; 980 } 981 } 982 983 #endif 984 985 if (!cd) { 986 PR_fprintf(errorFD, 987 "You must specify the location of your certificate directory\n"); 988 PR_fprintf(errorFD, 989 "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n"); 990 errorCount++; 991 exit(ERRX); 992 } 993 994 return cd; 995 } 996 997 /************************************************************************ 998 * g i v e _ h e l p 999 */ 1000 void 1001 give_help(int status) 1002 { 1003 if (status == SEC_ERROR_UNKNOWN_ISSUER) { 1004 PR_fprintf(errorFD, 1005 "The Certificate Authority (CA) for this certificate\n"); 1006 PR_fprintf(errorFD, 1007 "does not appear to be in your database. You should contact\n"); 1008 PR_fprintf(errorFD, 1009 "the organization which issued this certificate to obtain\n"); 1010 PR_fprintf(errorFD, "a copy of its CA Certificate.\n"); 1011 } 1012 } 1013 1014 /************************************************************************** 1015 * 1016 * p r _ f g e t s 1017 * 1018 * fgets implemented with NSPR. 1019 */ 1020 char * 1021 pr_fgets(char *buf, int size, PRFileDesc *file) 1022 { 1023 int i; 1024 int status; 1025 char c; 1026 1027 i = 0; 1028 while (i < size - 1) { 1029 status = PR_Read(file, &c, 1); 1030 if (status == -1) { 1031 return NULL; 1032 } else if (status == 0) { 1033 if (i == 0) { 1034 return NULL; 1035 } 1036 break; 1037 } 1038 buf[i++] = c; 1039 if (c == '\n') { 1040 break; 1041 } 1042 } 1043 buf[i] = '\0'; 1044 1045 return buf; 1046 }