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 +