security/nss/cmd/signtool/util.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/signtool/util.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1099 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "signtool.h"
     1.9 +#include "prio.h"
    1.10 +#include "prmem.h"
    1.11 +#include "nss.h"
    1.12 +
    1.13 +static int	is_dir (char *filename);
    1.14 +
    1.15 +/***********************************************************
    1.16 + * Nasty hackish function definitions
    1.17 + */
    1.18 +
    1.19 +long	*mozilla_event_queue = 0;
    1.20 +
    1.21 +#ifndef XP_WIN
    1.22 +char	*XP_GetString (int i)
    1.23 +{
    1.24 +    return SECU_Strerror (i);
    1.25 +}
    1.26 +#endif
    1.27 +
    1.28 +void	FE_SetPasswordEnabled()
    1.29 +{
    1.30 +}
    1.31 +
    1.32 +
    1.33 +void	/*MWContext*/ *FE_GetInitContext (void)
    1.34 +{
    1.35 +    return 0;
    1.36 +}
    1.37 +
    1.38 +
    1.39 +void	/*MWContext*/ *XP_FindSomeContext()
    1.40 +{
    1.41 +    /* No windows context in command tools */
    1.42 +    return NULL;
    1.43 +}
    1.44 +
    1.45 +
    1.46 +void	ET_moz_CallFunction()
    1.47 +{
    1.48 +}
    1.49 +
    1.50 +
    1.51 +/*
    1.52 + *  R e m o v e A l l A r c
    1.53 + *
    1.54 + *  Remove .arc directories that are lingering
    1.55 + *  from a previous run of signtool.
    1.56 + *
    1.57 + */
    1.58 +int
    1.59 +RemoveAllArc(char *tree)
    1.60 +{
    1.61 +    PRDir * dir;
    1.62 +    PRDirEntry * entry;
    1.63 +    char	*archive = NULL;
    1.64 +    int	retval = 0;
    1.65 +
    1.66 +    dir = PR_OpenDir (tree);
    1.67 +    if (!dir) 
    1.68 +	return - 1;
    1.69 +
    1.70 +    for (entry = PR_ReadDir (dir, 0); entry; entry = PR_ReadDir (dir,
    1.71 +         0)) {
    1.72 +
    1.73 +	if (entry->name[0] == '.') {
    1.74 +	    continue;
    1.75 +	}
    1.76 +
    1.77 +	if (archive) 
    1.78 +	    PR_Free(archive);
    1.79 +	archive = PR_smprintf("%s/%s", tree, entry->name);
    1.80 +
    1.81 +	if (PL_strcaserstr (entry->name, ".arc")
    1.82 +	     == (entry->name + strlen(entry->name) - 4) ) {
    1.83 +
    1.84 +	    if (verbosity >= 0) {
    1.85 +		PR_fprintf(outputFD, "removing: %s\n", archive);
    1.86 +	    }
    1.87 +
    1.88 +	    if (rm_dash_r(archive)) {
    1.89 +		PR_fprintf(errorFD, "Error removing %s\n", archive);
    1.90 +		errorCount++;
    1.91 +		retval = -1;
    1.92 +		goto finish;
    1.93 +	    }
    1.94 +	} else if (is_dir(archive)) {
    1.95 +	    if (RemoveAllArc(archive)) {
    1.96 +		retval = -1;
    1.97 +		goto finish;
    1.98 +	    }
    1.99 +	}
   1.100 +    }
   1.101 +
   1.102 +finish:
   1.103 +    PR_CloseDir (dir);
   1.104 +    if (archive) 
   1.105 +	PR_Free(archive);
   1.106 +
   1.107 +    return retval;
   1.108 +}
   1.109 +
   1.110 +
   1.111 +/*
   1.112 + *  r m _ d a s h _ r
   1.113 + *
   1.114 + *  Remove a file, or a directory recursively.
   1.115 + *
   1.116 + */
   1.117 +int	rm_dash_r (char *path)
   1.118 +{
   1.119 +    PRDir	 * dir;
   1.120 +    PRDirEntry * entry;
   1.121 +    PRFileInfo fileinfo;
   1.122 +    char	filename[FNSIZE];
   1.123 +
   1.124 +    if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
   1.125 +	/*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
   1.126 +	return - 1;
   1.127 +    }
   1.128 +    if (fileinfo.type == PR_FILE_DIRECTORY) {
   1.129 +
   1.130 +	dir = PR_OpenDir(path);
   1.131 +	if (!dir) {
   1.132 +	    PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
   1.133 +	    errorCount++;
   1.134 +	    return - 1;
   1.135 +	}
   1.136 +
   1.137 +	/* Recursively delete all entries in the directory */
   1.138 +	while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
   1.139 +	    sprintf(filename, "%s/%s", path, entry->name);
   1.140 +	    if (rm_dash_r(filename)) 
   1.141 +		return - 1;
   1.142 +	}
   1.143 +
   1.144 +	if (PR_CloseDir(dir) != PR_SUCCESS) {
   1.145 +	    PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
   1.146 +	    errorCount++;
   1.147 +	    return - 1;
   1.148 +	}
   1.149 +
   1.150 +	/* Delete the directory itself */
   1.151 +	if (PR_RmDir(path) != PR_SUCCESS) {
   1.152 +	    PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
   1.153 +	    errorCount++;
   1.154 +	    return - 1;
   1.155 +	}
   1.156 +    } else {
   1.157 +	if (PR_Delete(path) != PR_SUCCESS) {
   1.158 +	    PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
   1.159 +	    errorCount++;
   1.160 +	    return - 1;
   1.161 +	}
   1.162 +    }
   1.163 +    return 0;
   1.164 +}
   1.165 +
   1.166 +
   1.167 +/*
   1.168 + *  u s a g e 
   1.169 + * 
   1.170 + *  Print some useful help information
   1.171 + *
   1.172 + */
   1.173 +
   1.174 +
   1.175 +void
   1.176 +Usage (void)
   1.177 +{
   1.178 +#define FPS PR_fprintf(outputFD,
   1.179 +    FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
   1.180 +    FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME);
   1.181 +    FPS "\nUsage:  %s -k keyName [-b basename] [-c Compression Level]\n"
   1.182 +        "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n"
   1.183 +        "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
   1.184 +        "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n"
   1.185 +        "\t\t [-p password] directory-tree\n", PROGRAM_NAME);
   1.186 +    FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n"
   1.187 +        "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n"
   1.188 +        "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
   1.189 +        "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n"
   1.190 +        "\t\t directory-tree\n", PROGRAM_NAME);
   1.191 +    FPS "\t%s -h \n", PROGRAM_NAME);
   1.192 +    FPS "\t%s -H \n", PROGRAM_NAME);
   1.193 +    FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
   1.194 +    FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
   1.195 +    FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME);
   1.196 +    FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME);
   1.197 +    FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME);
   1.198 +    FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n"
   1.199 +        "\t\t [--outfile] [-O] \n", PROGRAM_NAME);
   1.200 +    FPS "\t%s -f filename\n" , PROGRAM_NAME);
   1.201 +    exit (ERRX);
   1.202 +}
   1.203 +
   1.204 +void 
   1.205 +LongUsage(void)
   1.206 +{
   1.207 +    FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
   1.208 +    FPS "\n%-20s  Signs the directory-tree\n",
   1.209 +        "signtool directory-tree");
   1.210 +    FPS "%-30s Nickname (key) of the certificate to sign with\n",
   1.211 +        "   -k keyname");
   1.212 +    FPS "%-30s Base filename for the .rsa and.sf files in the\n",
   1.213 +        "   -b basename");
   1.214 +    FPS "%-30s META-INF directory\n"," ");
   1.215 +    FPS "%-30s Set the compression level. 0-9, 0=none\n", 
   1.216 +	"   -c CompressionLevel");
   1.217 +    FPS "%-30s Certificate database directory containing cert*db\n",
   1.218 +	"   -d certificate directory");
   1.219 +    FPS "%-30s and key*db\n"," ");
   1.220 +    FPS "%-30s Name of the installer script for SmartUpdate\n",
   1.221 +	"   -i installer script");
   1.222 +    FPS "%-30s Name of a metadata control file\n",
   1.223 +	"   -m metafile");
   1.224 +    FPS "%-30s For optimizing the archive for size.\n",
   1.225 +	"   -o");
   1.226 +    FPS "%-30s Omit Optional Headers\n"," ");
   1.227 +    FPS "%-30s Excludes the specified directory or file from\n",
   1.228 +	"   -x  directory or file name");
   1.229 +    FPS "%-30s signing\n"," ");
   1.230 +    FPS "%-30s To not store the signing time in digital\n",
   1.231 +	"   -z  directory or file name");
   1.232 +    FPS "%-30s signature\n"," ");
   1.233 +    FPS "%-30s Create XPI Compatible Archive. It requires -Z\n",
   1.234 +	"   -X  directory or file name");
   1.235 +    FPS "%-30s option\n"," ");
   1.236 +    FPS "%-30s Sign only files with the given extension\n",
   1.237 +	"   -e");
   1.238 +    FPS "%-30s Causes the specified directory to be signed and\n",
   1.239 +	"   -j");
   1.240 +    FPS "%-30s tags its entries as inline JavaScript\n"," ");
   1.241 +    FPS "%-30s Creates a JAR file with the specified name.\n",
   1.242 +	"   -Z");
   1.243 +    FPS "%-30s -Z option cannot be used with -J option\n"," ");
   1.244 +    FPS "%-30s Specifies a password for the private-key database\n",
   1.245 +	"   -p");
   1.246 +    FPS "%-30s (insecure)\n"," ");
   1.247 +    FPS "%-30s File to receive redirected output\n",
   1.248 +    	"   --outfile filename");
   1.249 +    FPS "%-30s Sets the quantity of information generated in\n",
   1.250 +	"   --verbosity value");
   1.251 +    FPS "%-30s operation\n"," ");
   1.252 +    FPS "%-30s Blocks recursion into subdirectories\n",
   1.253 +	"   --norecurse");
   1.254 +    FPS "%-30s Retains the temporary .arc (archive) directories\n",
   1.255 +	"   --leavearc");
   1.256 +    FPS "%-30s -J option creates\n"," ");
   1.257 +
   1.258 +    FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n",
   1.259 +	"-J" );
   1.260 +    FPS "%-20s creates as many archive files as are in the HTML tags.\n"," ");
   1.261 +
   1.262 +    FPS "%-20s The options are same as without any command option given\n"," ");
   1.263 +    FPS "%-20s above. -Z and -J options are not allowed together\n"," ");
   1.264 +    
   1.265 +    FPS "\n%-20s Generates a new private-public key pair and corresponding\n",
   1.266 +	"-G nickname");
   1.267 +    FPS "%-20s object-signing certificates with the given nickname\n"," ");
   1.268 +    FPS "%-30s Specifies the size of the key for generated \n",
   1.269 +	"   --keysize|-s keysize");
   1.270 +    FPS "%-30s certificate\n"," ");
   1.271 +    FPS "%-30s Specifies which available token should generate\n",
   1.272 +	"   --token|-t token name ");
   1.273 +    FPS "%-30s the key and receive the certificate\n"," ");
   1.274 +    FPS "%-30s Specifies a file to receive redirected output\n",
   1.275 +	"   --outfile filename ");
   1.276 +    
   1.277 +    FPS "\n%-20s Display signtool help\n",
   1.278 +	"-h ");
   1.279 +    
   1.280 +    FPS "\n%-20s Display signtool help(Detailed)\n",
   1.281 +	"-H ");
   1.282 +    
   1.283 +    FPS "\n%-20s Lists signing certificates, including issuing CAs\n",
   1.284 +	"-l ");
   1.285 +    FPS "%-30s Certificate database directory containing cert*db\n",
   1.286 +	"   -d certificate directory");
   1.287 +    FPS "%-30s and key*db\n"," ");
   1.288 +
   1.289 +    FPS "%-30s Specifies a file to receive redirected output\n",
   1.290 +	"   --outfile filename ");
   1.291 +    FPS "%-30s Specifies the nickname (key) of the certificate\n",
   1.292 +	"   -k keyname");
   1.293 +
   1.294 +    
   1.295 +    FPS "\n%-20s Lists the certificates in your database\n",
   1.296 +	"-L ");
   1.297 +    FPS "%-30s Certificate database directory containing cert*db\n",
   1.298 +	"   -d certificate directory");
   1.299 +    FPS "%-30s and key*db\n"," ");
   1.300 +
   1.301 +    FPS "%-30s Specifies a file to receive redirected output\n",
   1.302 +	"   --outfile filename ");
   1.303 +    FPS "%-30s Specifies the nickname (key) of the certificate\n",
   1.304 +	"   -k keyname");
   1.305 +    
   1.306 +    FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n",
   1.307 +	"-M ");
   1.308 +   
   1.309 +    FPS "\n%-20s Displays the contents of an archive and verifies\n",
   1.310 +	"-v archive");
   1.311 +    FPS "%-20s cryptographic integrity\n"," ");
   1.312 +    FPS "%-30s Certificate database directory containing cert*db\n",
   1.313 +	"   -d certificate directory");
   1.314 +    FPS "%-30s and key*db\n"," ");
   1.315 +    FPS "%-30s Specifies a file to receive redirected output\n",
   1.316 +	"   --outfile filename ");
   1.317 +    
   1.318 +    FPS "\n%-20s Displays the names of signers in the archive\n",
   1.319 +	"-w archive");
   1.320 +    FPS "%-30s Specifies a file to receive redirected output\n",
   1.321 +	"   --outfile filename ");
   1.322 +
   1.323 +    
   1.324 +    FPS "\n%-30s Common option to all the above.\n",
   1.325 +	"   -O");
   1.326 +    FPS "%-30s Enable OCSP checking\n"," ");
   1.327 +    
   1.328 +    FPS "\n%-20s Specifies a text file containing options and arguments in\n",
   1.329 +	"-f command-file");
   1.330 +    FPS "%-20s keyword=value format. Commands are taken from this file\n"," ");
   1.331 +
   1.332 +    FPS  "\n\n\n");
   1.333 +    FPS  "Example:\n");
   1.334 +    FPS  "%-10s -d \"certificate directory\" -k \"certnickname\" \\",
   1.335 +         PROGRAM_NAME);
   1.336 +    FPS  "\n%-10s -p \"password\"  -X -Z \"file.xpi\" directory-tree\n"," " );
   1.337 +    FPS  "Common syntax to create an XPInstall compatible"
   1.338 +         " signed archive\n\n"," ");
   1.339 +    FPS  "\nCommand File Keywords and Example:\n");
   1.340 +    FPS "\nKeyword\t\tValue\n");
   1.341 +    FPS "basename\tSame as -b option\n");
   1.342 +    FPS "compression\tSame as -c option\n");
   1.343 +    FPS "certdir\t\tSame as -d option\n");
   1.344 +    FPS "extension\tSame as -e option\n");
   1.345 +    FPS "generate\tSame as -G option\n");
   1.346 +    FPS "installscript\tSame as -i option\n");
   1.347 +    FPS "javascriptdir\tSame as -j option\n");
   1.348 +    FPS "htmldir\t\tSame as -J option\n");
   1.349 +    FPS "certname\tNickname of certificate, as with -k  option\n");
   1.350 +    FPS "signdir\t\tThe directory to be signed, as with -k option\n");
   1.351 +    FPS "list\t\tSame as -l option. Value is ignored,\n"
   1.352 +        "    \t\tbut = sign must be present\n");
   1.353 +    FPS "listall\t\tSame as -L option. Value is ignored\n"
   1.354 +        "       \t\tbut = sign must be present\n");
   1.355 +    FPS "metafile\tSame as -m option\n");
   1.356 +    FPS "modules\t\tSame as -M option. Value is ignored,\n"
   1.357 +        "       \t\tbut = sign must be present\n");
   1.358 +    FPS "optimize\tSame as -o option. Value is ignored,\n" 
   1.359 +        "        \tbut = sign must be present\n");
   1.360 +    FPS "ocsp\t\tSame as -O option\n");
   1.361 +    FPS "password\tSame as -p option\n");
   1.362 +    FPS "verify\t\tSame as -v option\n");
   1.363 +    FPS "who\t\tSame as -w option\n");
   1.364 +    FPS "exclude\t\tSame as -x option\n");
   1.365 +    FPS "notime\t\tSame as -z option. Value is ignored,\n"
   1.366 +        "      \t\tbut = sign must be present\n");
   1.367 +    FPS "jarfile\t\tSame as -Z option\n");
   1.368 +    FPS "outfile\t\tSame as --outfile option. The argument\n");
   1.369 +    FPS "       \t\tis the name of a file to which output\n");
   1.370 +    FPS "       \t\tof a file and error messages will be  \n");
   1.371 +    FPS "       \t\tredirected\n");
   1.372 +    FPS "leavearc\tSame as --leavearc option\n");
   1.373 +    FPS "verbosity\tSame as --verbosity option\n");
   1.374 +    FPS "keysize\t\tSame as -s option\n");
   1.375 +    FPS "token\t\tSame as -t option\n");
   1.376 +    FPS "xpi\t\tSame as -X option\n");
   1.377 +    FPS "\n\n");
   1.378 +    FPS "Here's an example of the use of the command file. The command\n\n");
   1.379 +    FPS "   signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n"
   1.380 +        "   signdir > output.txt\n\n"); 
   1.381 +    FPS "becomes\n\n");
   1.382 +    FPS "   signtool -f somefile\n\n");
   1.383 +    FPS "where somefile contains the following lines:\n\n");
   1.384 +    FPS "   certdir=c:\\netscape\\users\\james\n"," "); 
   1.385 +    FPS "   certname=mycert\n"," "); 
   1.386 +    FPS "   jarfile=myjar.jar\n"," "); 
   1.387 +    FPS "   signdir=signdir\n"," "); 
   1.388 +    FPS "   outfile=output.txt\n"," "); 
   1.389 +    exit (ERRX);
   1.390 +#undef FPS
   1.391 +}
   1.392 +
   1.393 +/*
   1.394 + *  p r i n t _ e r r o r
   1.395 + *
   1.396 + *  For the undocumented -E function. If an older version
   1.397 + *  of communicator gives you a numeric error, we can see what
   1.398 + *  really happened without doing hex math.
   1.399 + *
   1.400 + */
   1.401 +
   1.402 +void
   1.403 +print_error (int err)
   1.404 +{
   1.405 +    PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error (err));
   1.406 +    errorCount++;
   1.407 +    give_help (err);
   1.408 +}
   1.409 +
   1.410 +
   1.411 +/*
   1.412 + *  o u t _ o f _ m e m o r y
   1.413 + *
   1.414 + *  Out of memory, exit Signtool.
   1.415 + * 
   1.416 + */
   1.417 +void
   1.418 +out_of_memory (void)
   1.419 +{
   1.420 +    PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
   1.421 +    errorCount++;
   1.422 +    exit (ERRX);
   1.423 +}
   1.424 +
   1.425 +
   1.426 +/*
   1.427 + *  V e r i f y C e r t D i r
   1.428 + *
   1.429 + *  Validate that the specified directory
   1.430 + *  contains a certificate database
   1.431 + *
   1.432 + */
   1.433 +void
   1.434 +VerifyCertDir(char *dir, char *keyName)
   1.435 +{
   1.436 +    char	fn [FNSIZE];
   1.437 +
   1.438 +    /* don't try verifying if we don't have a local directory */
   1.439 +    if (strncmp(dir, "multiaccess:", sizeof("multiaccess:") - 1) == 0) {
   1.440 +	return;
   1.441 +    }
   1.442 +    /* this function is truly evil. Tools and applications should not have
   1.443 +     * any knowledge of actual cert databases! */
   1.444 +    return;
   1.445 +
   1.446 +    /* This code is really broken because it makes underlying assumptions about
   1.447 +   * how the NSS profile directory is laid out, but these names can change
   1.448 +   * from release to release. */
   1.449 +    sprintf (fn, "%s/cert8.db", dir);
   1.450 +
   1.451 +    if (PR_Access (fn, PR_ACCESS_EXISTS)) {
   1.452 +	PR_fprintf(errorFD, "%s: No certificate database in \"%s\"\n",
   1.453 +			 PROGRAM_NAME, dir);
   1.454 +	PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
   1.455 +	     		PROGRAM_NAME);
   1.456 +	errorCount++;
   1.457 +	exit (ERRX);
   1.458 +    }
   1.459 +
   1.460 +    if (verbosity >= 0) {
   1.461 +	PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
   1.462 +    }
   1.463 +
   1.464 +    if (keyName == NULL)
   1.465 +	return;
   1.466 +
   1.467 +    /* if the user gave the -k key argument, verify that 
   1.468 +     a key database already exists */
   1.469 +
   1.470 +    sprintf (fn, "%s/key3.db", dir);
   1.471 +
   1.472 +    if (PR_Access (fn, PR_ACCESS_EXISTS)) {
   1.473 +	PR_fprintf(errorFD, "%s: No private key database in \"%s\"\n",
   1.474 +	     PROGRAM_NAME,
   1.475 +	    dir);
   1.476 +	PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
   1.477 +	     		PROGRAM_NAME);
   1.478 +	errorCount++;
   1.479 +	exit (ERRX);
   1.480 +    }
   1.481 +}
   1.482 +
   1.483 +
   1.484 +/*
   1.485 + *  f o r e a c h 
   1.486 + * 
   1.487 + *  A recursive function to loop through all names in
   1.488 + *  the specified directory, as well as all subdirectories.
   1.489 + *
   1.490 + *  FIX: Need to see if all platforms allow multiple
   1.491 + *  opendir's to be called.
   1.492 + *
   1.493 + */
   1.494 +
   1.495 +int
   1.496 +foreach(char *dirname, char *prefix, 
   1.497 +int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
   1.498 +void*arg),
   1.499 +PRBool recurse, PRBool includeDirs, void *arg) 
   1.500 +{
   1.501 +    char	newdir [FNSIZE];
   1.502 +    int	retval = 0;
   1.503 +
   1.504 +    PRDir * dir;
   1.505 +    PRDirEntry * entry;
   1.506 +
   1.507 +    strcpy (newdir, dirname);
   1.508 +    if (*prefix) {
   1.509 +	strcat (newdir, "/");
   1.510 +	strcat (newdir, prefix);
   1.511 +    }
   1.512 +
   1.513 +    dir = PR_OpenDir (newdir);
   1.514 +    if (!dir) 
   1.515 +	return - 1;
   1.516 +
   1.517 +    for (entry = PR_ReadDir (dir, 0); entry; entry = PR_ReadDir (dir, 0)) {
   1.518 +	if ( strcmp(entry->name, ".") == 0   || 
   1.519 +	    strcmp(entry->name, "..") == 0 ) {
   1.520 +	    /* no infinite recursion, please */
   1.521 +	    continue;
   1.522 +	}
   1.523 +
   1.524 +	/* can't sign self */
   1.525 +	if (!strcmp (entry->name, "META-INF"))
   1.526 +	    continue;
   1.527 +
   1.528 +	/* -x option */
   1.529 +	if (PL_HashTableLookup(excludeDirs, entry->name))
   1.530 +	    continue;
   1.531 +
   1.532 +	strcpy (newdir, dirname);
   1.533 +	if (*dirname)
   1.534 +	    strcat (newdir, "/");
   1.535 +
   1.536 +	if (*prefix) {
   1.537 +	    strcat (newdir, prefix);
   1.538 +	    strcat (newdir, "/");
   1.539 +	}
   1.540 +	strcat (newdir, entry->name);
   1.541 +
   1.542 +	if (!is_dir(newdir) || includeDirs) {
   1.543 +	    char	newpath [FNSIZE];
   1.544 +
   1.545 +	    strcpy (newpath, prefix);
   1.546 +	    if (*newpath)
   1.547 +		strcat (newpath, "/");
   1.548 +	    strcat (newpath, entry->name);
   1.549 +
   1.550 +	    if ( (*fn) (newpath, dirname, prefix, (char *) entry->name,
   1.551 +	         arg)) {
   1.552 +		retval = -1;
   1.553 +		break;
   1.554 +	    }
   1.555 +	}
   1.556 +
   1.557 +	if (is_dir (newdir)) {
   1.558 +	    if (recurse) {
   1.559 +		char	newprefix [FNSIZE];
   1.560 +
   1.561 +		strcpy (newprefix, prefix);
   1.562 +		if (*newprefix) {
   1.563 +		    strcat (newprefix, "/");
   1.564 +		}
   1.565 +		strcat (newprefix, entry->name);
   1.566 +
   1.567 +		if (foreach (dirname, newprefix, fn, recurse,
   1.568 +		     includeDirs, arg)) {
   1.569 +		    retval = -1;
   1.570 +		    break;
   1.571 +		}
   1.572 +	    }
   1.573 +	}
   1.574 +
   1.575 +    }
   1.576 +
   1.577 +    PR_CloseDir (dir);
   1.578 +
   1.579 +    return retval;
   1.580 +}
   1.581 +
   1.582 +
   1.583 +/*
   1.584 + *  i s _ d i r
   1.585 + *
   1.586 + *  Return 1 if file is a directory.
   1.587 + *  Wonder if this runs on a mac, trust not.
   1.588 + *
   1.589 + */
   1.590 +static int	is_dir (char *filename)
   1.591 +{
   1.592 +    PRFileInfo	finfo;
   1.593 +
   1.594 +    if ( PR_GetFileInfo(filename, &finfo) != PR_SUCCESS ) {
   1.595 +	printf("Unable to get information about %s\n", filename);
   1.596 +	return 0;
   1.597 +    }
   1.598 +
   1.599 +    return ( finfo.type == PR_FILE_DIRECTORY );
   1.600 +}
   1.601 +
   1.602 +
   1.603 +/***************************************************************
   1.604 + *
   1.605 + * s e c E r r o r S t r i n g
   1.606 + *
   1.607 + * Returns an error string corresponding to the given error code.
   1.608 + * Doesn't cover all errors; returns a default for many.
   1.609 + * Returned string is only valid until the next call of this function.
   1.610 + */
   1.611 +const char	*
   1.612 +secErrorString(long code)
   1.613 +{
   1.614 +    static char	errstring[80]; /* dynamically constructed error string */
   1.615 +    char	*c; /* the returned string */
   1.616 +
   1.617 +    switch (code) {
   1.618 +    case SEC_ERROR_IO: 
   1.619 +	c = "io error";
   1.620 +	break;
   1.621 +    case SEC_ERROR_LIBRARY_FAILURE: 
   1.622 +	c = "security library failure";
   1.623 +	break;
   1.624 +    case SEC_ERROR_BAD_DATA: 
   1.625 +	c = "bad data";
   1.626 +	break;
   1.627 +    case SEC_ERROR_OUTPUT_LEN: 
   1.628 +	c = "output length";
   1.629 +	break;
   1.630 +    case SEC_ERROR_INPUT_LEN: 
   1.631 +	c = "input length";
   1.632 +	break;
   1.633 +    case SEC_ERROR_INVALID_ARGS: 
   1.634 +	c = "invalid args";
   1.635 +	break;
   1.636 +    case SEC_ERROR_EXPIRED_CERTIFICATE: 
   1.637 +	c = "expired certificate";
   1.638 +	break;
   1.639 +    case SEC_ERROR_REVOKED_CERTIFICATE: 
   1.640 +	c = "revoked certificate";
   1.641 +	break;
   1.642 +    case SEC_ERROR_INADEQUATE_KEY_USAGE: 
   1.643 +	c = "inadequate key usage";
   1.644 +	break;
   1.645 +    case SEC_ERROR_INADEQUATE_CERT_TYPE: 
   1.646 +	c = "inadequate certificate type";
   1.647 +	break;
   1.648 +    case SEC_ERROR_UNTRUSTED_CERT: 
   1.649 +	c = "untrusted cert";
   1.650 +	break;
   1.651 +    case SEC_ERROR_NO_KRL: 
   1.652 +	c = "no key revocation list";
   1.653 +	break;
   1.654 +    case SEC_ERROR_KRL_BAD_SIGNATURE: 
   1.655 +	c = "key revocation list: bad signature";
   1.656 +	break;
   1.657 +    case SEC_ERROR_KRL_EXPIRED: 
   1.658 +	c = "key revocation list expired";
   1.659 +	break;
   1.660 +    case SEC_ERROR_REVOKED_KEY: 
   1.661 +	c = "revoked key";
   1.662 +	break;
   1.663 +    case SEC_ERROR_CRL_BAD_SIGNATURE:
   1.664 +	c = "certificate revocation list: bad signature";
   1.665 +	break;
   1.666 +    case SEC_ERROR_CRL_EXPIRED: 
   1.667 +	c = "certificate revocation list expired";
   1.668 +	break;
   1.669 +    case SEC_ERROR_CRL_NOT_YET_VALID:
   1.670 +	c = "certificate revocation list not yet valid";
   1.671 +	break;
   1.672 +    case SEC_ERROR_UNKNOWN_ISSUER: 
   1.673 +	c = "unknown issuer";
   1.674 +	break;
   1.675 +    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 
   1.676 +	c = "expired issuer certificate";
   1.677 +	break;
   1.678 +    case SEC_ERROR_BAD_SIGNATURE: 
   1.679 +	c = "bad signature";
   1.680 +	break;
   1.681 +    case SEC_ERROR_BAD_KEY: 
   1.682 +	c = "bad key";
   1.683 +	break;
   1.684 +    case SEC_ERROR_NOT_FORTEZZA_ISSUER: 
   1.685 +	c = "not fortezza issuer";
   1.686 +	break;
   1.687 +    case SEC_ERROR_CA_CERT_INVALID:
   1.688 +	c = "Certificate Authority certificate invalid";
   1.689 +	break;
   1.690 +    case SEC_ERROR_EXTENSION_NOT_FOUND: 
   1.691 +	c = "extension not found";
   1.692 +	break;
   1.693 +    case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 
   1.694 +	c = "certificate not in name space";
   1.695 +	break;
   1.696 +    case SEC_ERROR_UNTRUSTED_ISSUER: 
   1.697 +	c = "untrusted issuer";
   1.698 +	break;
   1.699 +    default:
   1.700 +	sprintf(errstring, "security error %ld", code);
   1.701 +	c = errstring;
   1.702 +	break;
   1.703 +    }
   1.704 +
   1.705 +    return c;
   1.706 +}
   1.707 +
   1.708 +
   1.709 +/***************************************************************
   1.710 + *
   1.711 + * d i s p l a y V e r i f y L o g
   1.712 + *
   1.713 + * Prints the log of a cert verification.
   1.714 + */
   1.715 +void
   1.716 +displayVerifyLog(CERTVerifyLog *log)
   1.717 +{
   1.718 +    CERTVerifyLogNode	 * node;
   1.719 +    CERTCertificate		 * cert;
   1.720 +    char	*name;
   1.721 +
   1.722 +    if ( !log  || (log->count <= 0) ) {
   1.723 +	return;
   1.724 +    }
   1.725 +
   1.726 +    for (node = log->head; node != NULL; node = node->next) {
   1.727 +
   1.728 +	if ( !(cert = node->cert) ) {
   1.729 +	    continue;
   1.730 +	}
   1.731 +
   1.732 +	/* Get a name for this cert */
   1.733 +	if (cert->nickname != NULL) {
   1.734 +	    name = cert->nickname;
   1.735 +	} else if (cert->emailAddr && cert->emailAddr[0]) {
   1.736 +	    name = cert->emailAddr;
   1.737 +	} else {
   1.738 +	    name = cert->subjectName;
   1.739 +	}
   1.740 +
   1.741 +	printf( "%s%s:\n", name,
   1.742 +	    (node->depth > 0) ? " [Certificate Authority]" : "");
   1.743 +
   1.744 +	printf("\t%s\n", secErrorString(node->error));
   1.745 +
   1.746 +    }
   1.747 +}
   1.748 +
   1.749 +
   1.750 +/*
   1.751 + *  J a r L i s t M o d u l e s
   1.752 + *
   1.753 + *  Print a list of the PKCS11 modules that are
   1.754 + *  available. This is useful for smartcard people to
   1.755 + *  make sure they have the drivers loaded.
   1.756 + *
   1.757 + */
   1.758 +void
   1.759 +JarListModules(void)
   1.760 +{
   1.761 +    int	i;
   1.762 +    int	count = 0;
   1.763 +
   1.764 +    SECMODModuleList * modules = NULL;
   1.765 +    static SECMODListLock *moduleLock = NULL;
   1.766 +
   1.767 +    SECMODModuleList * mlp;
   1.768 +
   1.769 +    if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) {
   1.770 +	/* this is the wrong text */
   1.771 +	PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
   1.772 +	     		PROGRAM_NAME);
   1.773 +	errorCount++;
   1.774 +	exit (ERRX);
   1.775 +    }
   1.776 +
   1.777 +    SECMOD_GetReadLock (moduleLock);
   1.778 +
   1.779 +    modules = SECMOD_GetDefaultModuleList();
   1.780 +
   1.781 +    if (modules == NULL) {
   1.782 +	SECMOD_ReleaseReadLock (moduleLock);
   1.783 +	PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
   1.784 +	errorCount++;
   1.785 +	exit (ERRX);
   1.786 +    }
   1.787 +
   1.788 +    PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
   1.789 +    PR_fprintf(outputFD, "-----------------------------------------------\n");
   1.790 +
   1.791 +    for (mlp = modules; mlp != NULL; mlp = mlp->next) {
   1.792 +	count++;
   1.793 +	PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
   1.794 +
   1.795 +	if (mlp->module->internal)
   1.796 +	    PR_fprintf(outputFD, "          (this module is internally loaded)\n");
   1.797 +	else
   1.798 +	    PR_fprintf(outputFD, "          (this is an external module)\n");
   1.799 +
   1.800 +	if (mlp->module->dllName)
   1.801 +	    PR_fprintf(outputFD, "          DLL name: %s\n",
   1.802 +	        mlp->module->dllName);
   1.803 +
   1.804 +	if (mlp->module->slotCount == 0)
   1.805 +	    PR_fprintf(outputFD, "          slots: There are no slots attached to this module\n");
   1.806 +	else
   1.807 +	    PR_fprintf(outputFD, "          slots: %d slots attached\n",
   1.808 +	         mlp->module->slotCount);
   1.809 +
   1.810 +	if (mlp->module->loaded == 0)
   1.811 +	    PR_fprintf(outputFD, "          status: Not loaded\n");
   1.812 +	else
   1.813 +	    PR_fprintf(outputFD, "          status: loaded\n");
   1.814 +
   1.815 +	for (i = 0; i < mlp->module->slotCount; i++) {
   1.816 +	    PK11SlotInfo * slot = mlp->module->slots[i];
   1.817 +
   1.818 +	    PR_fprintf(outputFD, "\n");
   1.819 +	    PR_fprintf(outputFD, "    slot: %s\n", PK11_GetSlotName(slot));
   1.820 +	    PR_fprintf(outputFD, "   token: %s\n", PK11_GetTokenName(slot));
   1.821 +	}
   1.822 +    }
   1.823 +
   1.824 +    PR_fprintf(outputFD, "-----------------------------------------------\n");
   1.825 +
   1.826 +    if (count == 0)
   1.827 +	PR_fprintf(outputFD,
   1.828 +	    "Warning: no modules were found (should have at least one)\n");
   1.829 +
   1.830 +    SECMOD_ReleaseReadLock (moduleLock);
   1.831 +}
   1.832 +
   1.833 +
   1.834 +/**********************************************************************
   1.835 + * c h o p
   1.836 + *
   1.837 + * Eliminates leading and trailing whitespace.  Returns a pointer to the 
   1.838 + * beginning of non-whitespace, or an empty string if it's all whitespace.
   1.839 + */
   1.840 +char*
   1.841 +chop(char *str)
   1.842 +{
   1.843 +    char	*start, *end;
   1.844 +
   1.845 +    if (str) {
   1.846 +	start = str;
   1.847 +
   1.848 +	/* Nip leading whitespace */
   1.849 +	while (isspace(*start)) {
   1.850 +	    start++;
   1.851 +	}
   1.852 +
   1.853 +	/* Nip trailing whitespace */
   1.854 +	if (*start) {
   1.855 +	    end = start + strlen(start) - 1;
   1.856 +	    while (isspace(*end) && end > start) {
   1.857 +		end--;
   1.858 +	    }
   1.859 +	    *(end + 1) = '\0';
   1.860 +	}
   1.861 +
   1.862 +	return start;
   1.863 +    } else {
   1.864 +	return NULL;
   1.865 +    }
   1.866 +}
   1.867 +
   1.868 +
   1.869 +/***********************************************************************
   1.870 + *
   1.871 + * F a t a l E r r o r
   1.872 + *
   1.873 + * Outputs an error message and bails out of the program.
   1.874 + */
   1.875 +void
   1.876 +FatalError(char *msg)
   1.877 +{
   1.878 +    if (!msg) 
   1.879 +	msg = "";
   1.880 +
   1.881 +    PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
   1.882 +    errorCount++;
   1.883 +    exit(ERRX);
   1.884 +}
   1.885 +
   1.886 +
   1.887 +/*************************************************************************
   1.888 + *
   1.889 + * I n i t C r y p t o
   1.890 + */
   1.891 +int
   1.892 +InitCrypto(char *cert_dir, PRBool readOnly)
   1.893 +{
   1.894 +    SECStatus rv;
   1.895 +    static int	prior = 0;
   1.896 +    PK11SlotInfo * slotinfo;
   1.897 +
   1.898 +    if (prior == 0) {
   1.899 +	/* some functions such as OpenKeyDB expect this path to be
   1.900 +	 * implicitly set prior to calling */
   1.901 +	if (readOnly) {
   1.902 +	    rv = NSS_Init(cert_dir);
   1.903 +	} else {
   1.904 +	    rv = NSS_InitReadWrite(cert_dir);
   1.905 +	}
   1.906 +	if (rv != SECSuccess) {
   1.907 +	    SECU_PrintPRandOSError(PROGRAM_NAME);
   1.908 +	    exit(-1);
   1.909 +	}
   1.910 +
   1.911 +	SECU_ConfigDirectory (cert_dir);
   1.912 +
   1.913 +	/* Been there done that */
   1.914 +	prior++;
   1.915 +
   1.916 +        PK11_SetPasswordFunc(SECU_GetModulePassword);
   1.917 +
   1.918 +	/* Must login to FIPS before you do anything else */
   1.919 +	if (PK11_IsFIPS()) {
   1.920 +	    slotinfo = PK11_GetInternalSlot();
   1.921 +	    if (!slotinfo) {
   1.922 +		fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
   1.923 +				    "\n", PROGRAM_NAME);
   1.924 +		return - 1;
   1.925 +	    }
   1.926 +	    if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
   1.927 +	         			  &pwdata) != SECSuccess) {
   1.928 +		fprintf(stderr, "%s: Unable to authenticate to %s.\n",
   1.929 +				    PROGRAM_NAME, PK11_GetSlotName(slotinfo));
   1.930 +		PK11_FreeSlot(slotinfo);
   1.931 +		return - 1;
   1.932 +	    }
   1.933 +	    PK11_FreeSlot(slotinfo);
   1.934 +	}
   1.935 +
   1.936 +	/* Make sure there is a password set on the internal key slot */
   1.937 +	slotinfo = PK11_GetInternalKeySlot();
   1.938 +	if (!slotinfo) {
   1.939 +	    fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
   1.940 +	        "\n", PROGRAM_NAME);
   1.941 +	    return - 1;
   1.942 +	}
   1.943 +	if (PK11_NeedUserInit(slotinfo)) {
   1.944 +	    PR_fprintf(errorFD,
   1.945 +	        "\nWARNING: No password set on internal key database.  Most operations will fail."
   1.946 +	        "\nYou must create a password.\n");
   1.947 +	    warningCount++;
   1.948 +	}
   1.949 +
   1.950 +	/* Make sure we can authenticate to the key slot in FIPS mode */
   1.951 +	if (PK11_IsFIPS()) {
   1.952 +	    if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
   1.953 +	         			  &pwdata) != SECSuccess) {
   1.954 +		fprintf(stderr, "%s: Unable to authenticate to %s.\n",
   1.955 +				PROGRAM_NAME, PK11_GetSlotName(slotinfo));
   1.956 +		PK11_FreeSlot(slotinfo);
   1.957 +		return - 1;
   1.958 +	    }
   1.959 +	}
   1.960 +	PK11_FreeSlot(slotinfo);
   1.961 +    }
   1.962 +
   1.963 +    return 0;
   1.964 +}
   1.965 +
   1.966 +
   1.967 +/* Windows foolishness is now in the secutil lib */
   1.968 +
   1.969 +/*****************************************************************
   1.970 + *  g e t _ d e f a u l t _ c e r t _ d i r
   1.971 + *
   1.972 + *  Attempt to locate a certificate directory.
   1.973 + *  Failing that, complain that the user needs to
   1.974 + *  use the -d(irectory) parameter.
   1.975 + *
   1.976 + */
   1.977 +char	*get_default_cert_dir (void)
   1.978 +{
   1.979 +    char	*home;
   1.980 +
   1.981 +    char	*cd = NULL;
   1.982 +    static char	db [FNSIZE];
   1.983 +
   1.984 +#ifdef XP_UNIX
   1.985 +    home = getenv ("HOME");
   1.986 +
   1.987 +    if (home && *home) {
   1.988 +	sprintf (db, "%s/.netscape", home);
   1.989 +	cd = db;
   1.990 +    }
   1.991 +#endif
   1.992 +
   1.993 +#ifdef XP_PC
   1.994 +    FILE * fp;
   1.995 +
   1.996 +    /* first check the environment override */
   1.997 +
   1.998 +    home = getenv ("JAR_HOME");
   1.999 +
  1.1000 +    if (home && *home) {
  1.1001 +	sprintf (db, "%s/cert7.db", home);
  1.1002 +
  1.1003 +	if ((fp = fopen (db, "r")) != NULL) {
  1.1004 +	    fclose (fp);
  1.1005 +	    cd = home;
  1.1006 +	}
  1.1007 +    }
  1.1008 +
  1.1009 +    /* try the old navigator directory */
  1.1010 +
  1.1011 +    if (cd == NULL) {
  1.1012 +	home = "c:/Program Files/Netscape/Navigator";
  1.1013 +
  1.1014 +	sprintf (db, "%s/cert7.db", home);
  1.1015 +
  1.1016 +	if ((fp = fopen (db, "r")) != NULL) {
  1.1017 +	    fclose (fp);
  1.1018 +	    cd = home;
  1.1019 +	}
  1.1020 +    }
  1.1021 +
  1.1022 +    /* Try the current directory, I wonder if this
  1.1023 +     is really a good idea. Remember, Windows only.. */
  1.1024 +
  1.1025 +    if (cd == NULL) {
  1.1026 +	home = ".";
  1.1027 +
  1.1028 +	sprintf (db, "%s/cert7.db", home);
  1.1029 +
  1.1030 +	if ((fp = fopen (db, "r")) != NULL) {
  1.1031 +	    fclose (fp);
  1.1032 +	    cd = home;
  1.1033 +	}
  1.1034 +    }
  1.1035 +
  1.1036 +#endif
  1.1037 +
  1.1038 +    if (!cd) {
  1.1039 +	PR_fprintf(errorFD,
  1.1040 +	    "You must specify the location of your certificate directory\n");
  1.1041 +	PR_fprintf(errorFD,
  1.1042 +	    "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
  1.1043 +	errorCount++;
  1.1044 +	exit (ERRX);
  1.1045 +    }
  1.1046 +
  1.1047 +    return cd;
  1.1048 +}
  1.1049 +
  1.1050 +
  1.1051 +/************************************************************************
  1.1052 + * g i v e _ h e l p
  1.1053 + */
  1.1054 +void	give_help (int status)
  1.1055 +{
  1.1056 +    if (status == SEC_ERROR_UNKNOWN_ISSUER) {
  1.1057 +	PR_fprintf(errorFD,
  1.1058 +	    "The Certificate Authority (CA) for this certificate\n");
  1.1059 +	PR_fprintf(errorFD,
  1.1060 +	    "does not appear to be in your database. You should contact\n");
  1.1061 +	PR_fprintf(errorFD,
  1.1062 +	    "the organization which issued this certificate to obtain\n");
  1.1063 +	PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
  1.1064 +    }
  1.1065 +}
  1.1066 +
  1.1067 +
  1.1068 +/**************************************************************************
  1.1069 + *
  1.1070 + * p r _ f g e t s
  1.1071 + *
  1.1072 + * fgets implemented with NSPR.
  1.1073 + */
  1.1074 +char*
  1.1075 +pr_fgets(char *buf, int size, PRFileDesc *file)
  1.1076 +{
  1.1077 +    int	i;
  1.1078 +    int	status;
  1.1079 +    char	c;
  1.1080 +
  1.1081 +    i = 0;
  1.1082 +    while (i < size - 1) {
  1.1083 +	status = PR_Read(file, &c, 1);
  1.1084 +	if (status == -1) {
  1.1085 +	    return NULL;
  1.1086 +	} else if (status == 0) {
  1.1087 +	    if (i == 0) {
  1.1088 +		return NULL;
  1.1089 +	    }
  1.1090 +	    break;
  1.1091 +	}
  1.1092 +	buf[i++] = c;
  1.1093 +	if (c == '\n') {
  1.1094 +	    break;
  1.1095 +	}
  1.1096 +    }
  1.1097 +    buf[i] = '\0';
  1.1098 +
  1.1099 +    return buf;
  1.1100 +}
  1.1101 +
  1.1102 +

mercurial