security/nss/cmd/signtool/util.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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
    14  */
    16 long	*mozilla_event_queue = 0;
    18 #ifndef XP_WIN
    19 char	*XP_GetString (int i)
    20 {
    21     return SECU_Strerror (i);
    22 }
    23 #endif
    25 void	FE_SetPasswordEnabled()
    26 {
    27 }
    30 void	/*MWContext*/ *FE_GetInitContext (void)
    31 {
    32     return 0;
    33 }
    36 void	/*MWContext*/ *XP_FindSomeContext()
    37 {
    38     /* No windows context in command tools */
    39     return NULL;
    40 }
    43 void	ET_moz_CallFunction()
    44 {
    45 }
    48 /*
    49  *  R e m o v e A l l A r c
    50  *
    51  *  Remove .arc directories that are lingering
    52  *  from a previous run of signtool.
    53  *
    54  */
    55 int
    56 RemoveAllArc(char *tree)
    57 {
    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;
    72 	}
    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);
    83 	    }
    85 	    if (rm_dash_r(archive)) {
    86 		PR_fprintf(errorFD, "Error removing %s\n", archive);
    87 		errorCount++;
    88 		retval = -1;
    89 		goto finish;
    90 	    }
    91 	} else if (is_dir(archive)) {
    92 	    if (RemoveAllArc(archive)) {
    93 		retval = -1;
    94 		goto finish;
    95 	    }
    96 	}
    97     }
    99 finish:
   100     PR_CloseDir (dir);
   101     if (archive) 
   102 	PR_Free(archive);
   104     return retval;
   105 }
   108 /*
   109  *  r m _ d a s h _ r
   110  *
   111  *  Remove a file, or a directory recursively.
   112  *
   113  */
   114 int	rm_dash_r (char *path)
   115 {
   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;
   124     }
   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;
   132 	}
   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;
   139 	}
   141 	if (PR_CloseDir(dir) != PR_SUCCESS) {
   142 	    PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
   143 	    errorCount++;
   144 	    return - 1;
   145 	}
   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;
   152 	}
   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;
   158 	}
   159     }
   160     return 0;
   161 }
   164 /*
   165  *  u s a g e 
   166  * 
   167  *  Print some useful help information
   168  *
   169  */
   172 void
   173 Usage (void)
   174 {
   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);
   199 }
   201 void 
   202 LongUsage(void)
   203 {
   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
   388 }
   390 /*
   391  *  p r i n t _ e r r o r
   392  *
   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.
   396  *
   397  */
   399 void
   400 print_error (int err)
   401 {
   402     PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error (err));
   403     errorCount++;
   404     give_help (err);
   405 }
   408 /*
   409  *  o u t _ o f _ m e m o r y
   410  *
   411  *  Out of memory, exit Signtool.
   412  * 
   413  */
   414 void
   415 out_of_memory (void)
   416 {
   417     PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
   418     errorCount++;
   419     exit (ERRX);
   420 }
   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     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;
   438     }
   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);
   455     }
   457     if (verbosity >= 0) {
   458 	PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
   459     }
   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);
   477     }
   478 }
   481 /*
   482  *  f o r e a c h 
   483  * 
   484  *  A recursive function to loop through all names in
   485  *  the specified directory, as well as all subdirectories.
   486  *
   487  *  FIX: Need to see if all platforms allow multiple
   488  *  opendir's to be called.
   489  *
   490  */
   492 int
   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) 
   497 {
   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);
   508     }
   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;
   519 	}
   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, "/");
   536 	}
   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;
   551 	    }
   552 	}
   554 	if (is_dir (newdir)) {
   555 	    if (recurse) {
   556 		char	newprefix [FNSIZE];
   558 		strcpy (newprefix, prefix);
   559 		if (*newprefix) {
   560 		    strcat (newprefix, "/");
   561 		}
   562 		strcat (newprefix, entry->name);
   564 		if (foreach (dirname, newprefix, fn, recurse,
   565 		     includeDirs, arg)) {
   566 		    retval = -1;
   567 		    break;
   568 		}
   569 	    }
   570 	}
   572     }
   574     PR_CloseDir (dir);
   576     return retval;
   577 }
   580 /*
   581  *  i s _ d i r
   582  *
   583  *  Return 1 if file is a directory.
   584  *  Wonder if this runs on a mac, trust not.
   585  *
   586  */
   587 static int	is_dir (char *filename)
   588 {
   589     PRFileInfo	finfo;
   591     if ( PR_GetFileInfo(filename, &finfo) != PR_SUCCESS ) {
   592 	printf("Unable to get information about %s\n", filename);
   593 	return 0;
   594     }
   596     return ( finfo.type == PR_FILE_DIRECTORY );
   597 }
   600 /***************************************************************
   601  *
   602  * s e c E r r o r S t r i n g
   603  *
   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.
   607  */
   608 const char	*
   609 secErrorString(long code)
   610 {
   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;
   700     }
   702     return c;
   703 }
   706 /***************************************************************
   707  *
   708  * d i s p l a y V e r i f y L o g
   709  *
   710  * Prints the log of a cert verification.
   711  */
   712 void
   713 displayVerifyLog(CERTVerifyLog *log)
   714 {
   715     CERTVerifyLogNode	 * node;
   716     CERTCertificate		 * cert;
   717     char	*name;
   719     if ( !log  || (log->count <= 0) ) {
   720 	return;
   721     }
   723     for (node = log->head; node != NULL; node = node->next) {
   725 	if ( !(cert = node->cert) ) {
   726 	    continue;
   727 	}
   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;
   736 	}
   738 	printf( "%s%s:\n", name,
   739 	    (node->depth > 0) ? " [Certificate Authority]" : "");
   741 	printf("\t%s\n", secErrorString(node->error));
   743     }
   744 }
   747 /*
   748  *  J a r L i s t M o d u l e s
   749  *
   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.
   753  *
   754  */
   755 void
   756 JarListModules(void)
   757 {
   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);
   772     }
   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);
   783     }
   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));
   818 	}
   819     }
   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);
   828 }
   831 /**********************************************************************
   832  * c h o p
   833  *
   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.
   836  */
   837 char*
   838 chop(char *str)
   839 {
   840     char	*start, *end;
   842     if (str) {
   843 	start = str;
   845 	/* Nip leading whitespace */
   846 	while (isspace(*start)) {
   847 	    start++;
   848 	}
   850 	/* Nip trailing whitespace */
   851 	if (*start) {
   852 	    end = start + strlen(start) - 1;
   853 	    while (isspace(*end) && end > start) {
   854 		end--;
   855 	    }
   856 	    *(end + 1) = '\0';
   857 	}
   859 	return start;
   860     } else {
   861 	return NULL;
   862     }
   863 }
   866 /***********************************************************************
   867  *
   868  * F a t a l E r r o r
   869  *
   870  * Outputs an error message and bails out of the program.
   871  */
   872 void
   873 FatalError(char *msg)
   874 {
   875     if (!msg) 
   876 	msg = "";
   878     PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
   879     errorCount++;
   880     exit(ERRX);
   881 }
   884 /*************************************************************************
   885  *
   886  * I n i t C r y p t o
   887  */
   888 int
   889 InitCrypto(char *cert_dir, PRBool readOnly)
   890 {
   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);
   902 	}
   903 	if (rv != SECSuccess) {
   904 	    SECU_PrintPRandOSError(PROGRAM_NAME);
   905 	    exit(-1);
   906 	}
   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;
   922 	    }
   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;
   929 	    }
   930 	    PK11_FreeSlot(slotinfo);
   931 	}
   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;
   939 	}
   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++;
   945 	}
   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;
   955 	    }
   956 	}
   957 	PK11_FreeSlot(slotinfo);
   958     }
   960     return 0;
   961 }
   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
   968  *
   969  *  Attempt to locate a certificate directory.
   970  *  Failing that, complain that the user needs to
   971  *  use the -d(irectory) parameter.
   972  *
   973  */
   974 char	*get_default_cert_dir (void)
   975 {
   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;
   987     }
   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
  1050  */
  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.
  1070  */
  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;

mercurial