Bumping manifests a=b2g-bump
[gecko.git] / security / nss / cmd / signtool / util.c
blob74a208e5e591a0d2f1224414ffeeb98a45c010e3
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/. */
5 #include "signtool.h"
6 #include "prio.h"
7 #include "prmem.h"
8 #include "nss.h"
10 static int is_dir (char *filename);
12 /***********************************************************
13 * Nasty hackish function definitions
16 long *mozilla_event_queue = 0;
18 #ifndef XP_WIN
19 char *XP_GetString (int i)
21 return SECU_Strerror (i);
23 #endif
25 void FE_SetPasswordEnabled()
30 void /*MWContext*/ *FE_GetInitContext (void)
32 return 0;
36 void /*MWContext*/ *XP_FindSomeContext()
38 /* No windows context in command tools */
39 return NULL;
43 void ET_moz_CallFunction()
49 * R e m o v e A l l A r c
51 * Remove .arc directories that are lingering
52 * from a previous run of signtool.
55 int
56 RemoveAllArc(char *tree)
58 PRDir * dir;
59 PRDirEntry * entry;
60 char *archive = NULL;
61 int retval = 0;
63 dir = PR_OpenDir (tree);
64 if (!dir)
65 return - 1;
67 for (entry = PR_ReadDir (dir, 0); entry; entry = PR_ReadDir (dir,
68 0)) {
70 if (entry->name[0] == '.') {
71 continue;
74 if (archive)
75 PR_Free(archive);
76 archive = PR_smprintf("%s/%s", tree, entry->name);
78 if (PL_strcaserstr (entry->name, ".arc")
79 == (entry->name + strlen(entry->name) - 4) ) {
81 if (verbosity >= 0) {
82 PR_fprintf(outputFD, "removing: %s\n", archive);
85 if (rm_dash_r(archive)) {
86 PR_fprintf(errorFD, "Error removing %s\n", archive);
87 errorCount++;
88 retval = -1;
89 goto finish;
91 } else if (is_dir(archive)) {
92 if (RemoveAllArc(archive)) {
93 retval = -1;
94 goto finish;
99 finish:
100 PR_CloseDir (dir);
101 if (archive)
102 PR_Free(archive);
104 return retval;
109 * r m _ d a s h _ r
111 * Remove a file, or a directory recursively.
114 int rm_dash_r (char *path)
116 PRDir * dir;
117 PRDirEntry * entry;
118 PRFileInfo fileinfo;
119 char filename[FNSIZE];
121 if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
122 /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
123 return - 1;
125 if (fileinfo.type == PR_FILE_DIRECTORY) {
127 dir = PR_OpenDir(path);
128 if (!dir) {
129 PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
130 errorCount++;
131 return - 1;
134 /* Recursively delete all entries in the directory */
135 while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
136 sprintf(filename, "%s/%s", path, entry->name);
137 if (rm_dash_r(filename))
138 return - 1;
141 if (PR_CloseDir(dir) != PR_SUCCESS) {
142 PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
143 errorCount++;
144 return - 1;
147 /* Delete the directory itself */
148 if (PR_RmDir(path) != PR_SUCCESS) {
149 PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
150 errorCount++;
151 return - 1;
153 } else {
154 if (PR_Delete(path) != PR_SUCCESS) {
155 PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
156 errorCount++;
157 return - 1;
160 return 0;
165 * u s a g e
167 * Print some useful help information
172 void
173 Usage (void)
175 #define FPS PR_fprintf(outputFD,
176 FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
177 FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME);
178 FPS "\nUsage: %s -k keyName [-b basename] [-c Compression Level]\n"
179 "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n"
180 "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
181 "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n"
182 "\t\t [-p password] directory-tree\n", PROGRAM_NAME);
183 FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n"
184 "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n"
185 "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
186 "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n"
187 "\t\t directory-tree\n", PROGRAM_NAME);
188 FPS "\t%s -h \n", PROGRAM_NAME);
189 FPS "\t%s -H \n", PROGRAM_NAME);
190 FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
191 FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
192 FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME);
193 FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME);
194 FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME);
195 FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n"
196 "\t\t [--outfile] [-O] \n", PROGRAM_NAME);
197 FPS "\t%s -f filename\n" , PROGRAM_NAME);
198 exit (ERRX);
201 void
202 LongUsage(void)
204 FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
205 FPS "\n%-20s Signs the directory-tree\n",
206 "signtool directory-tree");
207 FPS "%-30s Nickname (key) of the certificate to sign with\n",
208 " -k keyname");
209 FPS "%-30s Base filename for the .rsa and.sf files in the\n",
210 " -b basename");
211 FPS "%-30s META-INF directory\n"," ");
212 FPS "%-30s Set the compression level. 0-9, 0=none\n",
213 " -c CompressionLevel");
214 FPS "%-30s Certificate database directory containing cert*db\n",
215 " -d certificate directory");
216 FPS "%-30s and key*db\n"," ");
217 FPS "%-30s Name of the installer script for SmartUpdate\n",
218 " -i installer script");
219 FPS "%-30s Name of a metadata control file\n",
220 " -m metafile");
221 FPS "%-30s For optimizing the archive for size.\n",
222 " -o");
223 FPS "%-30s Omit Optional Headers\n"," ");
224 FPS "%-30s Excludes the specified directory or file from\n",
225 " -x directory or file name");
226 FPS "%-30s signing\n"," ");
227 FPS "%-30s To not store the signing time in digital\n",
228 " -z directory or file name");
229 FPS "%-30s signature\n"," ");
230 FPS "%-30s Create XPI Compatible Archive. It requires -Z\n",
231 " -X directory or file name");
232 FPS "%-30s option\n"," ");
233 FPS "%-30s Sign only files with the given extension\n",
234 " -e");
235 FPS "%-30s Causes the specified directory to be signed and\n",
236 " -j");
237 FPS "%-30s tags its entries as inline JavaScript\n"," ");
238 FPS "%-30s Creates a JAR file with the specified name.\n",
239 " -Z");
240 FPS "%-30s -Z option cannot be used with -J option\n"," ");
241 FPS "%-30s Specifies a password for the private-key database\n",
242 " -p");
243 FPS "%-30s (insecure)\n"," ");
244 FPS "%-30s File to receive redirected output\n",
245 " --outfile filename");
246 FPS "%-30s Sets the quantity of information generated in\n",
247 " --verbosity value");
248 FPS "%-30s operation\n"," ");
249 FPS "%-30s Blocks recursion into subdirectories\n",
250 " --norecurse");
251 FPS "%-30s Retains the temporary .arc (archive) directories\n",
252 " --leavearc");
253 FPS "%-30s -J option creates\n"," ");
255 FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n",
256 "-J" );
257 FPS "%-20s creates as many archive files as are in the HTML tags.\n"," ");
259 FPS "%-20s The options are same as without any command option given\n"," ");
260 FPS "%-20s above. -Z and -J options are not allowed together\n"," ");
262 FPS "\n%-20s Generates a new private-public key pair and corresponding\n",
263 "-G nickname");
264 FPS "%-20s object-signing certificates with the given nickname\n"," ");
265 FPS "%-30s Specifies the size of the key for generated \n",
266 " --keysize|-s keysize");
267 FPS "%-30s certificate\n"," ");
268 FPS "%-30s Specifies which available token should generate\n",
269 " --token|-t token name ");
270 FPS "%-30s the key and receive the certificate\n"," ");
271 FPS "%-30s Specifies a file to receive redirected output\n",
272 " --outfile filename ");
274 FPS "\n%-20s Display signtool help\n",
275 "-h ");
277 FPS "\n%-20s Display signtool help(Detailed)\n",
278 "-H ");
280 FPS "\n%-20s Lists signing certificates, including issuing CAs\n",
281 "-l ");
282 FPS "%-30s Certificate database directory containing cert*db\n",
283 " -d certificate directory");
284 FPS "%-30s and key*db\n"," ");
286 FPS "%-30s Specifies a file to receive redirected output\n",
287 " --outfile filename ");
288 FPS "%-30s Specifies the nickname (key) of the certificate\n",
289 " -k keyname");
292 FPS "\n%-20s Lists the certificates in your database\n",
293 "-L ");
294 FPS "%-30s Certificate database directory containing cert*db\n",
295 " -d certificate directory");
296 FPS "%-30s and key*db\n"," ");
298 FPS "%-30s Specifies a file to receive redirected output\n",
299 " --outfile filename ");
300 FPS "%-30s Specifies the nickname (key) of the certificate\n",
301 " -k keyname");
303 FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n",
304 "-M ");
306 FPS "\n%-20s Displays the contents of an archive and verifies\n",
307 "-v archive");
308 FPS "%-20s cryptographic integrity\n"," ");
309 FPS "%-30s Certificate database directory containing cert*db\n",
310 " -d certificate directory");
311 FPS "%-30s and key*db\n"," ");
312 FPS "%-30s Specifies a file to receive redirected output\n",
313 " --outfile filename ");
315 FPS "\n%-20s Displays the names of signers in the archive\n",
316 "-w archive");
317 FPS "%-30s Specifies a file to receive redirected output\n",
318 " --outfile filename ");
321 FPS "\n%-30s Common option to all the above.\n",
322 " -O");
323 FPS "%-30s Enable OCSP checking\n"," ");
325 FPS "\n%-20s Specifies a text file containing options and arguments in\n",
326 "-f command-file");
327 FPS "%-20s keyword=value format. Commands are taken from this file\n"," ");
329 FPS "\n\n\n");
330 FPS "Example:\n");
331 FPS "%-10s -d \"certificate directory\" -k \"certnickname\" \\",
332 PROGRAM_NAME);
333 FPS "\n%-10s -p \"password\" -X -Z \"file.xpi\" directory-tree\n"," " );
334 FPS "Common syntax to create an XPInstall compatible"
335 " signed archive\n\n"," ");
336 FPS "\nCommand File Keywords and Example:\n");
337 FPS "\nKeyword\t\tValue\n");
338 FPS "basename\tSame as -b option\n");
339 FPS "compression\tSame as -c option\n");
340 FPS "certdir\t\tSame as -d option\n");
341 FPS "extension\tSame as -e option\n");
342 FPS "generate\tSame as -G option\n");
343 FPS "installscript\tSame as -i option\n");
344 FPS "javascriptdir\tSame as -j option\n");
345 FPS "htmldir\t\tSame as -J option\n");
346 FPS "certname\tNickname of certificate, as with -k option\n");
347 FPS "signdir\t\tThe directory to be signed, as with -k option\n");
348 FPS "list\t\tSame as -l option. Value is ignored,\n"
349 " \t\tbut = sign must be present\n");
350 FPS "listall\t\tSame as -L option. Value is ignored\n"
351 " \t\tbut = sign must be present\n");
352 FPS "metafile\tSame as -m option\n");
353 FPS "modules\t\tSame as -M option. Value is ignored,\n"
354 " \t\tbut = sign must be present\n");
355 FPS "optimize\tSame as -o option. Value is ignored,\n"
356 " \tbut = sign must be present\n");
357 FPS "ocsp\t\tSame as -O option\n");
358 FPS "password\tSame as -p option\n");
359 FPS "verify\t\tSame as -v option\n");
360 FPS "who\t\tSame as -w option\n");
361 FPS "exclude\t\tSame as -x option\n");
362 FPS "notime\t\tSame as -z option. Value is ignored,\n"
363 " \t\tbut = sign must be present\n");
364 FPS "jarfile\t\tSame as -Z option\n");
365 FPS "outfile\t\tSame as --outfile option. The argument\n");
366 FPS " \t\tis the name of a file to which output\n");
367 FPS " \t\tof a file and error messages will be \n");
368 FPS " \t\tredirected\n");
369 FPS "leavearc\tSame as --leavearc option\n");
370 FPS "verbosity\tSame as --verbosity option\n");
371 FPS "keysize\t\tSame as -s option\n");
372 FPS "token\t\tSame as -t option\n");
373 FPS "xpi\t\tSame as -X option\n");
374 FPS "\n\n");
375 FPS "Here's an example of the use of the command file. The command\n\n");
376 FPS " signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n"
377 " signdir > output.txt\n\n");
378 FPS "becomes\n\n");
379 FPS " signtool -f somefile\n\n");
380 FPS "where somefile contains the following lines:\n\n");
381 FPS " certdir=c:\\netscape\\users\\james\n"," ");
382 FPS " certname=mycert\n"," ");
383 FPS " jarfile=myjar.jar\n"," ");
384 FPS " signdir=signdir\n"," ");
385 FPS " outfile=output.txt\n"," ");
386 exit (ERRX);
387 #undef FPS
391 * p r i n t _ e r r o r
393 * For the undocumented -E function. If an older version
394 * of communicator gives you a numeric error, we can see what
395 * really happened without doing hex math.
399 void
400 print_error (int err)
402 PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error (err));
403 errorCount++;
404 give_help (err);
409 * o u t _ o f _ m e m o r y
411 * Out of memory, exit Signtool.
414 void
415 out_of_memory (void)
417 PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
418 errorCount++;
419 exit (ERRX);
424 * V e r i f y C e r t D i r
426 * Validate that the specified directory
427 * contains a certificate database
430 void
431 VerifyCertDir(char *dir, char *keyName)
433 char fn [FNSIZE];
435 /* don't try verifying if we don't have a local directory */
436 if (strncmp(dir, "multiaccess:", sizeof("multiaccess:") - 1) == 0) {
437 return;
439 /* this function is truly evil. Tools and applications should not have
440 * any knowledge of actual cert databases! */
441 return;
443 /* This code is really broken because it makes underlying assumptions about
444 * how the NSS profile directory is laid out, but these names can change
445 * from release to release. */
446 sprintf (fn, "%s/cert8.db", dir);
448 if (PR_Access (fn, PR_ACCESS_EXISTS)) {
449 PR_fprintf(errorFD, "%s: No certificate database in \"%s\"\n",
450 PROGRAM_NAME, dir);
451 PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
452 PROGRAM_NAME);
453 errorCount++;
454 exit (ERRX);
457 if (verbosity >= 0) {
458 PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
461 if (keyName == NULL)
462 return;
464 /* if the user gave the -k key argument, verify that
465 a key database already exists */
467 sprintf (fn, "%s/key3.db", dir);
469 if (PR_Access (fn, PR_ACCESS_EXISTS)) {
470 PR_fprintf(errorFD, "%s: No private key database in \"%s\"\n",
471 PROGRAM_NAME,
472 dir);
473 PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
474 PROGRAM_NAME);
475 errorCount++;
476 exit (ERRX);
482 * f o r e a c h
484 * A recursive function to loop through all names in
485 * the specified directory, as well as all subdirectories.
487 * FIX: Need to see if all platforms allow multiple
488 * opendir's to be called.
493 foreach(char *dirname, char *prefix,
494 int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
495 void*arg),
496 PRBool recurse, PRBool includeDirs, void *arg)
498 char newdir [FNSIZE];
499 int retval = 0;
501 PRDir * dir;
502 PRDirEntry * entry;
504 strcpy (newdir, dirname);
505 if (*prefix) {
506 strcat (newdir, "/");
507 strcat (newdir, prefix);
510 dir = PR_OpenDir (newdir);
511 if (!dir)
512 return - 1;
514 for (entry = PR_ReadDir (dir, 0); entry; entry = PR_ReadDir (dir, 0)) {
515 if ( strcmp(entry->name, ".") == 0 ||
516 strcmp(entry->name, "..") == 0 ) {
517 /* no infinite recursion, please */
518 continue;
521 /* can't sign self */
522 if (!strcmp (entry->name, "META-INF"))
523 continue;
525 /* -x option */
526 if (PL_HashTableLookup(excludeDirs, entry->name))
527 continue;
529 strcpy (newdir, dirname);
530 if (*dirname)
531 strcat (newdir, "/");
533 if (*prefix) {
534 strcat (newdir, prefix);
535 strcat (newdir, "/");
537 strcat (newdir, entry->name);
539 if (!is_dir(newdir) || includeDirs) {
540 char newpath [FNSIZE];
542 strcpy (newpath, prefix);
543 if (*newpath)
544 strcat (newpath, "/");
545 strcat (newpath, entry->name);
547 if ( (*fn) (newpath, dirname, prefix, (char *) entry->name,
548 arg)) {
549 retval = -1;
550 break;
554 if (is_dir (newdir)) {
555 if (recurse) {
556 char newprefix [FNSIZE];
558 strcpy (newprefix, prefix);
559 if (*newprefix) {
560 strcat (newprefix, "/");
562 strcat (newprefix, entry->name);
564 if (foreach (dirname, newprefix, fn, recurse,
565 includeDirs, arg)) {
566 retval = -1;
567 break;
574 PR_CloseDir (dir);
576 return retval;
581 * i s _ d i r
583 * Return 1 if file is a directory.
584 * Wonder if this runs on a mac, trust not.
587 static int is_dir (char *filename)
589 PRFileInfo finfo;
591 if ( PR_GetFileInfo(filename, &finfo) != PR_SUCCESS ) {
592 printf("Unable to get information about %s\n", filename);
593 return 0;
596 return ( finfo.type == PR_FILE_DIRECTORY );
600 /***************************************************************
602 * s e c E r r o r S t r i n g
604 * Returns an error string corresponding to the given error code.
605 * Doesn't cover all errors; returns a default for many.
606 * Returned string is only valid until the next call of this function.
608 const char *
609 secErrorString(long code)
611 static char errstring[80]; /* dynamically constructed error string */
612 char *c; /* the returned string */
614 switch (code) {
615 case SEC_ERROR_IO:
616 c = "io error";
617 break;
618 case SEC_ERROR_LIBRARY_FAILURE:
619 c = "security library failure";
620 break;
621 case SEC_ERROR_BAD_DATA:
622 c = "bad data";
623 break;
624 case SEC_ERROR_OUTPUT_LEN:
625 c = "output length";
626 break;
627 case SEC_ERROR_INPUT_LEN:
628 c = "input length";
629 break;
630 case SEC_ERROR_INVALID_ARGS:
631 c = "invalid args";
632 break;
633 case SEC_ERROR_EXPIRED_CERTIFICATE:
634 c = "expired certificate";
635 break;
636 case SEC_ERROR_REVOKED_CERTIFICATE:
637 c = "revoked certificate";
638 break;
639 case SEC_ERROR_INADEQUATE_KEY_USAGE:
640 c = "inadequate key usage";
641 break;
642 case SEC_ERROR_INADEQUATE_CERT_TYPE:
643 c = "inadequate certificate type";
644 break;
645 case SEC_ERROR_UNTRUSTED_CERT:
646 c = "untrusted cert";
647 break;
648 case SEC_ERROR_NO_KRL:
649 c = "no key revocation list";
650 break;
651 case SEC_ERROR_KRL_BAD_SIGNATURE:
652 c = "key revocation list: bad signature";
653 break;
654 case SEC_ERROR_KRL_EXPIRED:
655 c = "key revocation list expired";
656 break;
657 case SEC_ERROR_REVOKED_KEY:
658 c = "revoked key";
659 break;
660 case SEC_ERROR_CRL_BAD_SIGNATURE:
661 c = "certificate revocation list: bad signature";
662 break;
663 case SEC_ERROR_CRL_EXPIRED:
664 c = "certificate revocation list expired";
665 break;
666 case SEC_ERROR_CRL_NOT_YET_VALID:
667 c = "certificate revocation list not yet valid";
668 break;
669 case SEC_ERROR_UNKNOWN_ISSUER:
670 c = "unknown issuer";
671 break;
672 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
673 c = "expired issuer certificate";
674 break;
675 case SEC_ERROR_BAD_SIGNATURE:
676 c = "bad signature";
677 break;
678 case SEC_ERROR_BAD_KEY:
679 c = "bad key";
680 break;
681 case SEC_ERROR_NOT_FORTEZZA_ISSUER:
682 c = "not fortezza issuer";
683 break;
684 case SEC_ERROR_CA_CERT_INVALID:
685 c = "Certificate Authority certificate invalid";
686 break;
687 case SEC_ERROR_EXTENSION_NOT_FOUND:
688 c = "extension not found";
689 break;
690 case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
691 c = "certificate not in name space";
692 break;
693 case SEC_ERROR_UNTRUSTED_ISSUER:
694 c = "untrusted issuer";
695 break;
696 default:
697 sprintf(errstring, "security error %ld", code);
698 c = errstring;
699 break;
702 return c;
706 /***************************************************************
708 * d i s p l a y V e r i f y L o g
710 * Prints the log of a cert verification.
712 void
713 displayVerifyLog(CERTVerifyLog *log)
715 CERTVerifyLogNode * node;
716 CERTCertificate * cert;
717 char *name;
719 if ( !log || (log->count <= 0) ) {
720 return;
723 for (node = log->head; node != NULL; node = node->next) {
725 if ( !(cert = node->cert) ) {
726 continue;
729 /* Get a name for this cert */
730 if (cert->nickname != NULL) {
731 name = cert->nickname;
732 } else if (cert->emailAddr && cert->emailAddr[0]) {
733 name = cert->emailAddr;
734 } else {
735 name = cert->subjectName;
738 printf( "%s%s:\n", name,
739 (node->depth > 0) ? " [Certificate Authority]" : "");
741 printf("\t%s\n", secErrorString(node->error));
748 * J a r L i s t M o d u l e s
750 * Print a list of the PKCS11 modules that are
751 * available. This is useful for smartcard people to
752 * make sure they have the drivers loaded.
755 void
756 JarListModules(void)
758 int i;
759 int count = 0;
761 SECMODModuleList * modules = NULL;
762 static SECMODListLock *moduleLock = NULL;
764 SECMODModuleList * mlp;
766 if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) {
767 /* this is the wrong text */
768 PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
769 PROGRAM_NAME);
770 errorCount++;
771 exit (ERRX);
774 SECMOD_GetReadLock (moduleLock);
776 modules = SECMOD_GetDefaultModuleList();
778 if (modules == NULL) {
779 SECMOD_ReleaseReadLock (moduleLock);
780 PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
781 errorCount++;
782 exit (ERRX);
785 PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
786 PR_fprintf(outputFD, "-----------------------------------------------\n");
788 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
789 count++;
790 PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
792 if (mlp->module->internal)
793 PR_fprintf(outputFD, " (this module is internally loaded)\n");
794 else
795 PR_fprintf(outputFD, " (this is an external module)\n");
797 if (mlp->module->dllName)
798 PR_fprintf(outputFD, " DLL name: %s\n",
799 mlp->module->dllName);
801 if (mlp->module->slotCount == 0)
802 PR_fprintf(outputFD, " slots: There are no slots attached to this module\n");
803 else
804 PR_fprintf(outputFD, " slots: %d slots attached\n",
805 mlp->module->slotCount);
807 if (mlp->module->loaded == 0)
808 PR_fprintf(outputFD, " status: Not loaded\n");
809 else
810 PR_fprintf(outputFD, " status: loaded\n");
812 for (i = 0; i < mlp->module->slotCount; i++) {
813 PK11SlotInfo * slot = mlp->module->slots[i];
815 PR_fprintf(outputFD, "\n");
816 PR_fprintf(outputFD, " slot: %s\n", PK11_GetSlotName(slot));
817 PR_fprintf(outputFD, " token: %s\n", PK11_GetTokenName(slot));
821 PR_fprintf(outputFD, "-----------------------------------------------\n");
823 if (count == 0)
824 PR_fprintf(outputFD,
825 "Warning: no modules were found (should have at least one)\n");
827 SECMOD_ReleaseReadLock (moduleLock);
831 /**********************************************************************
832 * c h o p
834 * Eliminates leading and trailing whitespace. Returns a pointer to the
835 * beginning of non-whitespace, or an empty string if it's all whitespace.
837 char*
838 chop(char *str)
840 char *start, *end;
842 if (str) {
843 start = str;
845 /* Nip leading whitespace */
846 while (isspace(*start)) {
847 start++;
850 /* Nip trailing whitespace */
851 if (*start) {
852 end = start + strlen(start) - 1;
853 while (isspace(*end) && end > start) {
854 end--;
856 *(end + 1) = '\0';
859 return start;
860 } else {
861 return NULL;
866 /***********************************************************************
868 * F a t a l E r r o r
870 * Outputs an error message and bails out of the program.
872 void
873 FatalError(char *msg)
875 if (!msg)
876 msg = "";
878 PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
879 errorCount++;
880 exit(ERRX);
884 /*************************************************************************
886 * I n i t C r y p t o
889 InitCrypto(char *cert_dir, PRBool readOnly)
891 SECStatus rv;
892 static int prior = 0;
893 PK11SlotInfo * slotinfo;
895 if (prior == 0) {
896 /* some functions such as OpenKeyDB expect this path to be
897 * implicitly set prior to calling */
898 if (readOnly) {
899 rv = NSS_Init(cert_dir);
900 } else {
901 rv = NSS_InitReadWrite(cert_dir);
903 if (rv != SECSuccess) {
904 SECU_PrintPRandOSError(PROGRAM_NAME);
905 exit(-1);
908 SECU_ConfigDirectory (cert_dir);
910 /* Been there done that */
911 prior++;
913 PK11_SetPasswordFunc(SECU_GetModulePassword);
915 /* Must login to FIPS before you do anything else */
916 if (PK11_IsFIPS()) {
917 slotinfo = PK11_GetInternalSlot();
918 if (!slotinfo) {
919 fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
920 "\n", PROGRAM_NAME);
921 return - 1;
923 if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
924 &pwdata) != SECSuccess) {
925 fprintf(stderr, "%s: Unable to authenticate to %s.\n",
926 PROGRAM_NAME, PK11_GetSlotName(slotinfo));
927 PK11_FreeSlot(slotinfo);
928 return - 1;
930 PK11_FreeSlot(slotinfo);
933 /* Make sure there is a password set on the internal key slot */
934 slotinfo = PK11_GetInternalKeySlot();
935 if (!slotinfo) {
936 fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
937 "\n", PROGRAM_NAME);
938 return - 1;
940 if (PK11_NeedUserInit(slotinfo)) {
941 PR_fprintf(errorFD,
942 "\nWARNING: No password set on internal key database. Most operations will fail."
943 "\nYou must create a password.\n");
944 warningCount++;
947 /* Make sure we can authenticate to the key slot in FIPS mode */
948 if (PK11_IsFIPS()) {
949 if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
950 &pwdata) != SECSuccess) {
951 fprintf(stderr, "%s: Unable to authenticate to %s.\n",
952 PROGRAM_NAME, PK11_GetSlotName(slotinfo));
953 PK11_FreeSlot(slotinfo);
954 return - 1;
957 PK11_FreeSlot(slotinfo);
960 return 0;
964 /* Windows foolishness is now in the secutil lib */
966 /*****************************************************************
967 * g e t _ d e f a u l t _ c e r t _ d i r
969 * Attempt to locate a certificate directory.
970 * Failing that, complain that the user needs to
971 * use the -d(irectory) parameter.
974 char *get_default_cert_dir (void)
976 char *home;
978 char *cd = NULL;
979 static char db [FNSIZE];
981 #ifdef XP_UNIX
982 home = getenv ("HOME");
984 if (home && *home) {
985 sprintf (db, "%s/.netscape", home);
986 cd = db;
988 #endif
990 #ifdef XP_PC
991 FILE * fp;
993 /* first check the environment override */
995 home = getenv ("JAR_HOME");
997 if (home && *home) {
998 sprintf (db, "%s/cert7.db", home);
1000 if ((fp = fopen (db, "r")) != NULL) {
1001 fclose (fp);
1002 cd = home;
1006 /* try the old navigator directory */
1008 if (cd == NULL) {
1009 home = "c:/Program Files/Netscape/Navigator";
1011 sprintf (db, "%s/cert7.db", home);
1013 if ((fp = fopen (db, "r")) != NULL) {
1014 fclose (fp);
1015 cd = home;
1019 /* Try the current directory, I wonder if this
1020 is really a good idea. Remember, Windows only.. */
1022 if (cd == NULL) {
1023 home = ".";
1025 sprintf (db, "%s/cert7.db", home);
1027 if ((fp = fopen (db, "r")) != NULL) {
1028 fclose (fp);
1029 cd = home;
1033 #endif
1035 if (!cd) {
1036 PR_fprintf(errorFD,
1037 "You must specify the location of your certificate directory\n");
1038 PR_fprintf(errorFD,
1039 "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
1040 errorCount++;
1041 exit (ERRX);
1044 return cd;
1048 /************************************************************************
1049 * g i v e _ h e l p
1051 void give_help (int status)
1053 if (status == SEC_ERROR_UNKNOWN_ISSUER) {
1054 PR_fprintf(errorFD,
1055 "The Certificate Authority (CA) for this certificate\n");
1056 PR_fprintf(errorFD,
1057 "does not appear to be in your database. You should contact\n");
1058 PR_fprintf(errorFD,
1059 "the organization which issued this certificate to obtain\n");
1060 PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
1065 /**************************************************************************
1067 * p r _ f g e t s
1069 * fgets implemented with NSPR.
1071 char*
1072 pr_fgets(char *buf, int size, PRFileDesc *file)
1074 int i;
1075 int status;
1076 char c;
1078 i = 0;
1079 while (i < size - 1) {
1080 status = PR_Read(file, &c, 1);
1081 if (status == -1) {
1082 return NULL;
1083 } else if (status == 0) {
1084 if (i == 0) {
1085 return NULL;
1087 break;
1089 buf[i++] = c;
1090 if (c == '\n') {
1091 break;
1094 buf[i] = '\0';
1096 return buf;