1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/signtool/signtool.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1076 @@ 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 +/* 1.9 + * SIGNTOOL 1.10 + * 1.11 + * A command line tool to create manifest files 1.12 + * from a directory hierarchy. It is assumed that 1.13 + * the tree will be equivalent to what resides 1.14 + * or will reside in an archive. 1.15 + * 1.16 + * 1.17 + */ 1.18 + 1.19 +#include "nss.h" 1.20 +#include "signtool.h" 1.21 +#include "prmem.h" 1.22 +#include "prio.h" 1.23 + 1.24 +/*********************************************************************** 1.25 + * Global Variable Definitions 1.26 + */ 1.27 +char *progName; /* argv[0] */ 1.28 + 1.29 +/* password data */ 1.30 +secuPWData pwdata = { PW_NONE, 0 }; 1.31 + 1.32 +/* directories or files to exclude in descent */ 1.33 +PLHashTable *excludeDirs = NULL; 1.34 +static PRBool exclusionsGiven = PR_FALSE; 1.35 + 1.36 +/* zatharus is the man who knows no time, dies tragic death */ 1.37 +int no_time = 0; 1.38 + 1.39 +/* -b basename of .rsa, .sf files */ 1.40 +char *base = DEFAULT_BASE_NAME; 1.41 + 1.42 +/* Only sign files with this extension */ 1.43 +PLHashTable *extensions = NULL; 1.44 +PRBool extensionsGiven = PR_FALSE; 1.45 + 1.46 +char *scriptdir = NULL; 1.47 + 1.48 +int verbosity = 0; 1.49 + 1.50 +PRFileDesc *outputFD = NULL, *errorFD = NULL; 1.51 + 1.52 +int errorCount = 0, warningCount = 0; 1.53 + 1.54 +int compression_level = DEFAULT_COMPRESSION_LEVEL; 1.55 +PRBool compression_level_specified = PR_FALSE; 1.56 + 1.57 +int xpi_arc = 0; 1.58 + 1.59 +/* Command-line arguments */ 1.60 +static char *genkey = NULL; 1.61 +static char *verify = NULL; 1.62 +static char *zipfile = NULL; 1.63 +static char *cert_dir = NULL; 1.64 +static int javascript = 0; 1.65 +static char *jartree = NULL; 1.66 +static char *keyName = NULL; 1.67 +static char *metafile = NULL; 1.68 +static char *install_script = NULL; 1.69 +static int list_certs = 0; 1.70 +static int list_modules = 0; 1.71 +static int optimize = 0; 1.72 +static int enableOCSP = 0; 1.73 +static char *tell_who = NULL; 1.74 +static char *outfile = NULL; 1.75 +static char *cmdFile = NULL; 1.76 +static PRBool noRecurse = PR_FALSE; 1.77 +static PRBool leaveArc = PR_FALSE; 1.78 +static int keySize = -1; 1.79 +static char *token = NULL; 1.80 + 1.81 +typedef enum { 1.82 + UNKNOWN_OPT, 1.83 + HELP_OPT, 1.84 + LONG_HELP_OPT, 1.85 + BASE_OPT, 1.86 + COMPRESSION_OPT, 1.87 + CERT_DIR_OPT, 1.88 + EXTENSION_OPT, 1.89 + INSTALL_SCRIPT_OPT, 1.90 + SCRIPTDIR_OPT, 1.91 + CERTNAME_OPT, 1.92 + LIST_OBJSIGN_CERTS_OPT, 1.93 + LIST_ALL_CERTS_OPT, 1.94 + METAFILE_OPT, 1.95 + OPTIMIZE_OPT, 1.96 + ENABLE_OCSP_OPT, 1.97 + PASSWORD_OPT, 1.98 + VERIFY_OPT, 1.99 + WHO_OPT, 1.100 + EXCLUDE_OPT, 1.101 + NO_TIME_OPT, 1.102 + JAVASCRIPT_OPT, 1.103 + ZIPFILE_OPT, 1.104 + GENKEY_OPT, 1.105 + MODULES_OPT, 1.106 + NORECURSE_OPT, 1.107 + SIGNDIR_OPT, 1.108 + OUTFILE_OPT, 1.109 + COMMAND_FILE_OPT, 1.110 + LEAVE_ARC_OPT, 1.111 + VERBOSITY_OPT, 1.112 + KEYSIZE_OPT, 1.113 + TOKEN_OPT, 1.114 + XPI_ARC_OPT 1.115 +} 1.116 + 1.117 + 1.118 +OPT_TYPE; 1.119 + 1.120 +typedef enum { 1.121 + DUPLICATE_OPTION_ERR = 0, 1.122 + OPTION_NEEDS_ARG_ERR 1.123 +} 1.124 + 1.125 + 1.126 +Error; 1.127 + 1.128 +static char *errStrings[] = { 1.129 + "warning: %s option specified more than once.\n" 1.130 + "Only last specification will be used.\n", 1.131 + "ERROR: option \"%s\" requires an argument.\n" 1.132 +}; 1.133 + 1.134 + 1.135 +static int ProcessOneOpt(OPT_TYPE type, char *arg); 1.136 + 1.137 +/********************************************************************* 1.138 + * 1.139 + * P r o c e s s C o m m a n d F i l e 1.140 + */ 1.141 +int 1.142 +ProcessCommandFile() 1.143 +{ 1.144 + PRFileDesc * fd; 1.145 +#define CMD_FILE_BUFSIZE 1024 1.146 + char buf[CMD_FILE_BUFSIZE]; 1.147 + char *equals; 1.148 + int linenum = 0; 1.149 + int retval = -1; 1.150 + OPT_TYPE type; 1.151 + 1.152 + fd = PR_Open(cmdFile, PR_RDONLY, 0777); 1.153 + if (!fd) { 1.154 + PR_fprintf(errorFD, "ERROR: Unable to open command file %s.\n"); 1.155 + errorCount++; 1.156 + return - 1; 1.157 + } 1.158 + 1.159 + while (pr_fgets(buf, CMD_FILE_BUFSIZE, fd)) { 1.160 + char *eol; 1.161 + linenum++; 1.162 + 1.163 + /* Chop off final newline */ 1.164 + eol = PL_strchr(buf, '\r'); 1.165 + if (!eol) { 1.166 + eol = PL_strchr(buf, '\n'); 1.167 + } 1.168 + if (eol) 1.169 + *eol = '\0'; 1.170 + 1.171 + equals = PL_strchr(buf, '='); 1.172 + if (!equals) { 1.173 + continue; 1.174 + } 1.175 + 1.176 + *equals = '\0'; 1.177 + equals++; 1.178 + 1.179 + /* Now buf points to the attribute, and equals points to the value. */ 1.180 + 1.181 + /* This is pretty straightforward, just deal with whatever attribute 1.182 + * this is */ 1.183 + if (!PL_strcasecmp(buf, "basename")) { 1.184 + type = BASE_OPT; 1.185 + } else if (!PL_strcasecmp(buf, "compression")) { 1.186 + type = COMPRESSION_OPT; 1.187 + } else if (!PL_strcasecmp(buf, "certdir")) { 1.188 + type = CERT_DIR_OPT; 1.189 + } else if (!PL_strcasecmp(buf, "extension")) { 1.190 + type = EXTENSION_OPT; 1.191 + } else if (!PL_strcasecmp(buf, "generate")) { 1.192 + type = GENKEY_OPT; 1.193 + } else if (!PL_strcasecmp(buf, "installScript")) { 1.194 + type = INSTALL_SCRIPT_OPT; 1.195 + } else if (!PL_strcasecmp(buf, "javascriptdir")) { 1.196 + type = SCRIPTDIR_OPT; 1.197 + } else if (!PL_strcasecmp(buf, "htmldir")) { 1.198 + type = JAVASCRIPT_OPT; 1.199 + if (jartree) { 1.200 + PR_fprintf(errorFD, 1.201 + "warning: directory to be signed specified more than once." 1.202 + " Only last specification will be used.\n"); 1.203 + warningCount++; 1.204 + PR_Free(jartree); 1.205 + jartree = NULL; 1.206 + } 1.207 + jartree = PL_strdup(equals); 1.208 + } else if (!PL_strcasecmp(buf, "certname")) { 1.209 + type = CERTNAME_OPT; 1.210 + } else if (!PL_strcasecmp(buf, "signdir")) { 1.211 + type = SIGNDIR_OPT; 1.212 + } else if (!PL_strcasecmp(buf, "list")) { 1.213 + type = LIST_OBJSIGN_CERTS_OPT; 1.214 + } else if (!PL_strcasecmp(buf, "listall")) { 1.215 + type = LIST_ALL_CERTS_OPT; 1.216 + } else if (!PL_strcasecmp(buf, "metafile")) { 1.217 + type = METAFILE_OPT; 1.218 + } else if (!PL_strcasecmp(buf, "modules")) { 1.219 + type = MODULES_OPT; 1.220 + } else if (!PL_strcasecmp(buf, "optimize")) { 1.221 + type = OPTIMIZE_OPT; 1.222 + } else if (!PL_strcasecmp(buf, "ocsp")) { 1.223 + type = ENABLE_OCSP_OPT; 1.224 + } else if (!PL_strcasecmp(buf, "password")) { 1.225 + type = PASSWORD_OPT; 1.226 + } else if (!PL_strcasecmp(buf, "verify")) { 1.227 + type = VERIFY_OPT; 1.228 + } else if (!PL_strcasecmp(buf, "who")) { 1.229 + type = WHO_OPT; 1.230 + } else if (!PL_strcasecmp(buf, "exclude")) { 1.231 + type = EXCLUDE_OPT; 1.232 + } else if (!PL_strcasecmp(buf, "notime")) { 1.233 + type = NO_TIME_OPT; 1.234 + } else if (!PL_strcasecmp(buf, "jarfile")) { 1.235 + type = ZIPFILE_OPT; 1.236 + } else if (!PL_strcasecmp(buf, "outfile")) { 1.237 + type = OUTFILE_OPT; 1.238 + } else if (!PL_strcasecmp(buf, "leavearc")) { 1.239 + type = LEAVE_ARC_OPT; 1.240 + } else if (!PL_strcasecmp(buf, "verbosity")) { 1.241 + type = VERBOSITY_OPT; 1.242 + } else if (!PL_strcasecmp(buf, "keysize")) { 1.243 + type = KEYSIZE_OPT; 1.244 + } else if (!PL_strcasecmp(buf, "token")) { 1.245 + type = TOKEN_OPT; 1.246 + } else if (!PL_strcasecmp(buf, "xpi")) { 1.247 + type = XPI_ARC_OPT; 1.248 + } else { 1.249 + PR_fprintf(errorFD, 1.250 + "warning: unknown attribute \"%s\" in command file, line %d.\n", 1.251 + buf, linenum); 1.252 + warningCount++; 1.253 + type = UNKNOWN_OPT; 1.254 + } 1.255 + 1.256 + /* Process the option, whatever it is */ 1.257 + if (type != UNKNOWN_OPT) { 1.258 + if (ProcessOneOpt(type, equals) == -1) { 1.259 + goto finish; 1.260 + } 1.261 + } 1.262 + } 1.263 + 1.264 + retval = 0; 1.265 + 1.266 +finish: 1.267 + PR_Close(fd); 1.268 + return retval; 1.269 +} 1.270 + 1.271 + 1.272 +/********************************************************************* 1.273 + * 1.274 + * p a r s e _ a r g s 1.275 + */ 1.276 +static int 1.277 +parse_args(int argc, char *argv[]) 1.278 +{ 1.279 + char *opt; 1.280 + char *arg; 1.281 + int needsInc = 0; 1.282 + int i; 1.283 + OPT_TYPE type; 1.284 + 1.285 + /* Loop over all arguments */ 1.286 + for (i = 1; i < argc; i++) { 1.287 + opt = argv[i]; 1.288 + arg = NULL; 1.289 + 1.290 + if (opt[0] == '-') { 1.291 + if (opt[1] == '-') { 1.292 + /* word option */ 1.293 + if (i < argc - 1) { 1.294 + needsInc = 1; 1.295 + arg = argv[i+1]; 1.296 + } else { 1.297 + arg = NULL; 1.298 + } 1.299 + 1.300 + if ( !PL_strcasecmp(opt + 2, "norecurse")) { 1.301 + type = NORECURSE_OPT; 1.302 + } else if ( !PL_strcasecmp(opt + 2, "leavearc")) { 1.303 + type = LEAVE_ARC_OPT; 1.304 + } else if ( !PL_strcasecmp(opt + 2, "verbosity")) { 1.305 + type = VERBOSITY_OPT; 1.306 + } else if ( !PL_strcasecmp(opt + 2, "outfile")) { 1.307 + type = OUTFILE_OPT; 1.308 + } else if ( !PL_strcasecmp(opt + 2, "keysize")) { 1.309 + type = KEYSIZE_OPT; 1.310 + } else if ( !PL_strcasecmp(opt + 2, "token")) { 1.311 + type = TOKEN_OPT; 1.312 + } else { 1.313 + PR_fprintf(errorFD, "warning: unknown option: %s\n", 1.314 + opt); 1.315 + warningCount++; 1.316 + type = UNKNOWN_OPT; 1.317 + } 1.318 + } else { 1.319 + /* char option */ 1.320 + if (opt[2] != '\0') { 1.321 + arg = opt + 2; 1.322 + } else if (i < argc - 1) { 1.323 + needsInc = 1; 1.324 + arg = argv[i+1]; 1.325 + } else { 1.326 + arg = NULL; 1.327 + } 1.328 + 1.329 + switch (opt[1]) { 1.330 + case 'b': 1.331 + type = BASE_OPT; 1.332 + break; 1.333 + case 'c': 1.334 + type = COMPRESSION_OPT; 1.335 + break; 1.336 + case 'd': 1.337 + type = CERT_DIR_OPT; 1.338 + break; 1.339 + case 'e': 1.340 + type = EXTENSION_OPT; 1.341 + break; 1.342 + case 'f': 1.343 + type = COMMAND_FILE_OPT; 1.344 + break; 1.345 + case 'h': 1.346 + type = HELP_OPT; 1.347 + break; 1.348 + case 'H': 1.349 + type = LONG_HELP_OPT; 1.350 + break; 1.351 + case 'i': 1.352 + type = INSTALL_SCRIPT_OPT; 1.353 + break; 1.354 + case 'j': 1.355 + type = SCRIPTDIR_OPT; 1.356 + break; 1.357 + case 'k': 1.358 + type = CERTNAME_OPT; 1.359 + break; 1.360 + case 'l': 1.361 + type = LIST_OBJSIGN_CERTS_OPT; 1.362 + break; 1.363 + case 'L': 1.364 + type = LIST_ALL_CERTS_OPT; 1.365 + break; 1.366 + case 'm': 1.367 + type = METAFILE_OPT; 1.368 + break; 1.369 + case 'o': 1.370 + type = OPTIMIZE_OPT; 1.371 + break; 1.372 + case 'O': 1.373 + type = ENABLE_OCSP_OPT; 1.374 + break; 1.375 + case 'p': 1.376 + type = PASSWORD_OPT; 1.377 + break; 1.378 + case 'v': 1.379 + type = VERIFY_OPT; 1.380 + break; 1.381 + case 'w': 1.382 + type = WHO_OPT; 1.383 + break; 1.384 + case 'x': 1.385 + type = EXCLUDE_OPT; 1.386 + break; 1.387 + case 'X': 1.388 + type = XPI_ARC_OPT; 1.389 + break; 1.390 + case 'z': 1.391 + type = NO_TIME_OPT; 1.392 + break; 1.393 + case 'J': 1.394 + type = JAVASCRIPT_OPT; 1.395 + break; 1.396 + case 'Z': 1.397 + type = ZIPFILE_OPT; 1.398 + break; 1.399 + case 'G': 1.400 + type = GENKEY_OPT; 1.401 + break; 1.402 + case 'M': 1.403 + type = MODULES_OPT; 1.404 + break; 1.405 + case 's': 1.406 + type = KEYSIZE_OPT; 1.407 + break; 1.408 + case 't': 1.409 + type = TOKEN_OPT; 1.410 + break; 1.411 + default: 1.412 + type = UNKNOWN_OPT; 1.413 + PR_fprintf(errorFD, "warning: unrecognized option: -%c.\n", 1.414 + 1.415 + opt[1]); 1.416 + warningCount++; 1.417 + break; 1.418 + } 1.419 + } 1.420 + } else { 1.421 + type = UNKNOWN_OPT; 1.422 + if (i == argc - 1) { 1.423 + if (jartree) { 1.424 + PR_fprintf(errorFD, 1.425 + "warning: directory to be signed specified more than once.\n" 1.426 + " Only last specification will be used.\n"); 1.427 + warningCount++; 1.428 + PR_Free(jartree); 1.429 + jartree = NULL; 1.430 + } 1.431 + jartree = PL_strdup(opt); 1.432 + } else { 1.433 + PR_fprintf(errorFD, "warning: unrecognized option: %s\n", opt); 1.434 + warningCount++; 1.435 + } 1.436 + } 1.437 + 1.438 + if (type != UNKNOWN_OPT) { 1.439 + short ateArg = ProcessOneOpt(type, arg); 1.440 + if (ateArg == -1) { 1.441 + /* error */ 1.442 + return - 1; 1.443 + } 1.444 + if (ateArg && needsInc) { 1.445 + i++; 1.446 + } 1.447 + } 1.448 + } 1.449 + 1.450 + return 0; 1.451 +} 1.452 + 1.453 + 1.454 +/********************************************************************* 1.455 + * 1.456 + * P r o c e s s O n e O p t 1.457 + * 1.458 + * Since options can come from different places (command file, word options, 1.459 + * char options), this is a central function that is called to deal with 1.460 + * them no matter where they come from. 1.461 + * 1.462 + * type is the type of option. 1.463 + * arg is the argument to the option, possibly NULL. 1.464 + * Returns 1 if the argument was eaten, 0 if it wasn't, and -1 for error. 1.465 + */ 1.466 +static int 1.467 +ProcessOneOpt(OPT_TYPE type, char *arg) 1.468 +{ 1.469 + int ate = 0; 1.470 + 1.471 + switch (type) { 1.472 + case HELP_OPT: 1.473 + Usage(); 1.474 + break; 1.475 + case LONG_HELP_OPT: 1.476 + LongUsage(); 1.477 + break; 1.478 + case BASE_OPT: 1.479 + if (base) { 1.480 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-b"); 1.481 + warningCount++; 1.482 + PR_Free(base); 1.483 + base = NULL; 1.484 + } 1.485 + if (!arg) { 1.486 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-b"); 1.487 + errorCount++; 1.488 + goto loser; 1.489 + } 1.490 + base = PL_strdup(arg); 1.491 + ate = 1; 1.492 + break; 1.493 + case COMPRESSION_OPT: 1.494 + if (compression_level_specified) { 1.495 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-c"); 1.496 + warningCount++; 1.497 + } 1.498 + if ( !arg ) { 1.499 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-c"); 1.500 + errorCount++; 1.501 + goto loser; 1.502 + } 1.503 + compression_level = atoi(arg); 1.504 + compression_level_specified = PR_TRUE; 1.505 + ate = 1; 1.506 + break; 1.507 + case CERT_DIR_OPT: 1.508 + if (cert_dir) { 1.509 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-d"); 1.510 + warningCount++; 1.511 + PR_Free(cert_dir); 1.512 + cert_dir = NULL; 1.513 + } 1.514 + if (!arg) { 1.515 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-d"); 1.516 + errorCount++; 1.517 + goto loser; 1.518 + } 1.519 + cert_dir = PL_strdup(arg); 1.520 + ate = 1; 1.521 + break; 1.522 + case EXTENSION_OPT: 1.523 + if (!arg) { 1.524 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.525 + "extension (-e)"); 1.526 + errorCount++; 1.527 + goto loser; 1.528 + } 1.529 + PL_HashTableAdd(extensions, arg, arg); 1.530 + extensionsGiven = PR_TRUE; 1.531 + ate = 1; 1.532 + break; 1.533 + case INSTALL_SCRIPT_OPT: 1.534 + if (install_script) { 1.535 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.536 + "installScript (-i)"); 1.537 + warningCount++; 1.538 + PR_Free(install_script); 1.539 + install_script = NULL; 1.540 + } 1.541 + if (!arg) { 1.542 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.543 + "installScript (-i)"); 1.544 + errorCount++; 1.545 + goto loser; 1.546 + } 1.547 + install_script = PL_strdup(arg); 1.548 + ate = 1; 1.549 + break; 1.550 + case SCRIPTDIR_OPT: 1.551 + if (scriptdir) { 1.552 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.553 + "javascriptdir (-j)"); 1.554 + warningCount++; 1.555 + PR_Free(scriptdir); 1.556 + scriptdir = NULL; 1.557 + } 1.558 + if (!arg) { 1.559 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.560 + "javascriptdir (-j)"); 1.561 + errorCount++; 1.562 + goto loser; 1.563 + } 1.564 + scriptdir = PL_strdup(arg); 1.565 + ate = 1; 1.566 + break; 1.567 + case CERTNAME_OPT: 1.568 + if (keyName) { 1.569 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.570 + "keyName (-k)"); 1.571 + warningCount++; 1.572 + PR_Free(keyName); 1.573 + keyName = NULL; 1.574 + } 1.575 + if (!arg) { 1.576 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.577 + "keyName (-k)"); 1.578 + errorCount++; 1.579 + goto loser; 1.580 + } 1.581 + keyName = PL_strdup(arg); 1.582 + ate = 1; 1.583 + break; 1.584 + case LIST_OBJSIGN_CERTS_OPT: 1.585 + case LIST_ALL_CERTS_OPT: 1.586 + if (list_certs != 0) { 1.587 + PR_fprintf(errorFD, 1.588 + "warning: only one of -l and -L may be specified.\n"); 1.589 + warningCount++; 1.590 + } 1.591 + list_certs = (type == LIST_OBJSIGN_CERTS_OPT ? 1 : 2); 1.592 + break; 1.593 + case METAFILE_OPT: 1.594 + if (metafile) { 1.595 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.596 + "metafile (-m)"); 1.597 + warningCount++; 1.598 + PR_Free(metafile); 1.599 + metafile = NULL; 1.600 + } 1.601 + if (!arg) { 1.602 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.603 + "metafile (-m)"); 1.604 + errorCount++; 1.605 + goto loser; 1.606 + } 1.607 + metafile = PL_strdup(arg); 1.608 + ate = 1; 1.609 + break; 1.610 + case OPTIMIZE_OPT: 1.611 + optimize = 1; 1.612 + break; 1.613 + case ENABLE_OCSP_OPT: 1.614 + enableOCSP = 1; 1.615 + break; 1.616 + case PASSWORD_OPT: 1.617 + if (pwdata.data) { 1.618 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.619 + "password (-p)"); 1.620 + warningCount++; 1.621 + PR_Free(pwdata.data); 1.622 + pwdata.data = NULL; 1.623 + } 1.624 + if (!arg) { 1.625 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.626 + "password (-p)"); 1.627 + errorCount++; 1.628 + goto loser; 1.629 + } 1.630 + pwdata.source = PW_PLAINTEXT; 1.631 + pwdata.data = PL_strdup(arg); 1.632 + ate = 1; 1.633 + break; 1.634 + case VERIFY_OPT: 1.635 + if (verify) { 1.636 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.637 + "verify (-v)"); 1.638 + warningCount++; 1.639 + PR_Free(verify); 1.640 + verify = NULL; 1.641 + } 1.642 + if (!arg) { 1.643 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.644 + "verify (-v)"); 1.645 + errorCount++; 1.646 + goto loser; 1.647 + } 1.648 + verify = PL_strdup(arg); 1.649 + ate = 1; 1.650 + break; 1.651 + case WHO_OPT: 1.652 + if (tell_who) { 1.653 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.654 + "who (-v)"); 1.655 + warningCount++; 1.656 + PR_Free(tell_who); 1.657 + tell_who = NULL; 1.658 + } 1.659 + if (!arg) { 1.660 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.661 + "who (-w)"); 1.662 + errorCount++; 1.663 + goto loser; 1.664 + } 1.665 + tell_who = PL_strdup(arg); 1.666 + ate = 1; 1.667 + break; 1.668 + case EXCLUDE_OPT: 1.669 + if (!arg) { 1.670 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.671 + "exclude (-x)"); 1.672 + errorCount++; 1.673 + goto loser; 1.674 + } 1.675 + PL_HashTableAdd(excludeDirs, arg, arg); 1.676 + exclusionsGiven = PR_TRUE; 1.677 + ate = 1; 1.678 + break; 1.679 + case NO_TIME_OPT: 1.680 + no_time = 1; 1.681 + break; 1.682 + case JAVASCRIPT_OPT: 1.683 + javascript++; 1.684 + break; 1.685 + case ZIPFILE_OPT: 1.686 + if (zipfile) { 1.687 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.688 + "jarfile (-Z)"); 1.689 + warningCount++; 1.690 + PR_Free(zipfile); 1.691 + zipfile = NULL; 1.692 + } 1.693 + if (!arg) { 1.694 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.695 + "jarfile (-Z)"); 1.696 + errorCount++; 1.697 + goto loser; 1.698 + } 1.699 + zipfile = PL_strdup(arg); 1.700 + ate = 1; 1.701 + break; 1.702 + case GENKEY_OPT: 1.703 + if (genkey) { 1.704 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.705 + "generate (-G)"); 1.706 + warningCount++; 1.707 + PR_Free(genkey); 1.708 + genkey = NULL; 1.709 + } 1.710 + if (!arg) { 1.711 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.712 + "generate (-G)"); 1.713 + errorCount++; 1.714 + goto loser; 1.715 + } 1.716 + genkey = PL_strdup(arg); 1.717 + ate = 1; 1.718 + break; 1.719 + case MODULES_OPT: 1.720 + list_modules++; 1.721 + break; 1.722 + case SIGNDIR_OPT: 1.723 + if (jartree) { 1.724 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.725 + "signdir"); 1.726 + warningCount++; 1.727 + PR_Free(jartree); 1.728 + jartree = NULL; 1.729 + } 1.730 + if (!arg) { 1.731 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.732 + "signdir"); 1.733 + errorCount++; 1.734 + goto loser; 1.735 + } 1.736 + jartree = PL_strdup(arg); 1.737 + ate = 1; 1.738 + break; 1.739 + case OUTFILE_OPT: 1.740 + if (outfile) { 1.741 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.742 + "outfile"); 1.743 + warningCount++; 1.744 + PR_Free(outfile); 1.745 + outfile = NULL; 1.746 + } 1.747 + if (!arg) { 1.748 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.749 + "outfile"); 1.750 + errorCount++; 1.751 + goto loser; 1.752 + } 1.753 + outfile = PL_strdup(arg); 1.754 + ate = 1; 1.755 + break; 1.756 + case COMMAND_FILE_OPT: 1.757 + if (cmdFile) { 1.758 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], 1.759 + "-f"); 1.760 + warningCount++; 1.761 + PR_Free(cmdFile); 1.762 + cmdFile = NULL; 1.763 + } 1.764 + if (!arg) { 1.765 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.766 + "-f"); 1.767 + errorCount++; 1.768 + goto loser; 1.769 + } 1.770 + cmdFile = PL_strdup(arg); 1.771 + ate = 1; 1.772 + break; 1.773 + case NORECURSE_OPT: 1.774 + noRecurse = PR_TRUE; 1.775 + break; 1.776 + case LEAVE_ARC_OPT: 1.777 + leaveArc = PR_TRUE; 1.778 + break; 1.779 + case VERBOSITY_OPT: 1.780 + if (!arg) { 1.781 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], 1.782 + "--verbosity"); 1.783 + errorCount++; 1.784 + goto loser; 1.785 + } 1.786 + verbosity = atoi(arg); 1.787 + ate = 1; 1.788 + break; 1.789 + case KEYSIZE_OPT: 1.790 + if ( keySize != -1 ) { 1.791 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-s"); 1.792 + warningCount++; 1.793 + } 1.794 + keySize = atoi(arg); 1.795 + ate = 1; 1.796 + if ( keySize < 1 || keySize > MAX_RSA_KEY_SIZE ) { 1.797 + PR_fprintf(errorFD, "Invalid key size: %d.\n", keySize); 1.798 + errorCount++; 1.799 + goto loser; 1.800 + } 1.801 + break; 1.802 + case TOKEN_OPT: 1.803 + if ( token ) { 1.804 + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-t"); 1.805 + PR_Free(token); 1.806 + token = NULL; 1.807 + } 1.808 + if ( !arg ) { 1.809 + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-t"); 1.810 + errorCount++; 1.811 + goto loser; 1.812 + } 1.813 + token = PL_strdup(arg); 1.814 + ate = 1; 1.815 + break; 1.816 + case XPI_ARC_OPT: 1.817 + xpi_arc = 1; 1.818 + break; 1.819 + default: 1.820 + PR_fprintf(errorFD, "warning: unknown option\n"); 1.821 + warningCount++; 1.822 + break; 1.823 + } 1.824 + 1.825 + return ate; 1.826 +loser: 1.827 + return - 1; 1.828 +} 1.829 + 1.830 + 1.831 +/********************************************************************* 1.832 + * 1.833 + * m a i n 1.834 + */ 1.835 +int 1.836 +main(int argc, char *argv[]) 1.837 +{ 1.838 + PRBool readOnly; 1.839 + int retval = 0; 1.840 + 1.841 + outputFD = PR_STDOUT; 1.842 + errorFD = PR_STDERR; 1.843 + 1.844 + progName = argv[0]; 1.845 + 1.846 + if (argc < 2) { 1.847 + Usage(); 1.848 + } 1.849 + 1.850 + excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, 1.851 + PL_CompareStrings, NULL, NULL); 1.852 + extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, 1.853 + PL_CompareStrings, NULL, NULL); 1.854 + 1.855 + if (parse_args(argc, argv)) { 1.856 + retval = -1; 1.857 + goto cleanup; 1.858 + } 1.859 + 1.860 + /* Parse the command file if one was given */ 1.861 + if (cmdFile) { 1.862 + if (ProcessCommandFile()) { 1.863 + retval = -1; 1.864 + goto cleanup; 1.865 + } 1.866 + } 1.867 + 1.868 + /* Set up output redirection */ 1.869 + if (outfile) { 1.870 + if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) { 1.871 + /* delete the file if it is already present */ 1.872 + PR_fprintf(errorFD, 1.873 + "warning: %s already exists and will be overwritten.\n", 1.874 + outfile); 1.875 + warningCount++; 1.876 + if (PR_Delete(outfile) != PR_SUCCESS) { 1.877 + PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile); 1.878 + errorCount++; 1.879 + exit(ERRX); 1.880 + } 1.881 + } 1.882 + outputFD = PR_Open(outfile, 1.883 + PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777); 1.884 + if (!outputFD) { 1.885 + PR_fprintf(errorFD, "ERROR: Unable to create %s.\n", 1.886 + outfile); 1.887 + errorCount++; 1.888 + exit(ERRX); 1.889 + } 1.890 + errorFD = outputFD; 1.891 + } 1.892 + 1.893 + /* This seems to be a fairly common user error */ 1.894 + 1.895 + if (verify && list_certs > 0) { 1.896 + PR_fprintf (errorFD, "%s: Can't use -l and -v at the same time\n", 1.897 + PROGRAM_NAME); 1.898 + errorCount++; 1.899 + retval = -1; 1.900 + goto cleanup; 1.901 + } 1.902 + 1.903 + /* -J assumes -Z now */ 1.904 + 1.905 + if (javascript && zipfile) { 1.906 + PR_fprintf (errorFD, "%s: Can't use -J and -Z at the same time\n", 1.907 + PROGRAM_NAME); 1.908 + PR_fprintf (errorFD, "%s: -J option will create the jar files for you\n", 1.909 + PROGRAM_NAME); 1.910 + errorCount++; 1.911 + retval = -1; 1.912 + goto cleanup; 1.913 + } 1.914 + 1.915 + /* -X needs -Z */ 1.916 + 1.917 + if (xpi_arc && !zipfile) { 1.918 + PR_fprintf (errorFD, "%s: option XPI (-X) requires option jarfile (-Z)\n", 1.919 + PROGRAM_NAME); 1.920 + errorCount++; 1.921 + retval = -1; 1.922 + goto cleanup; 1.923 + } 1.924 + 1.925 + /* Less common mixing of -L with various options */ 1.926 + 1.927 + if (list_certs > 0 && 1.928 + (tell_who || zipfile || javascript || 1.929 + scriptdir || extensionsGiven || exclusionsGiven || install_script)) { 1.930 + PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n", 1.931 + PROGRAM_NAME); 1.932 + errorCount++; 1.933 + retval = -1; 1.934 + goto cleanup; 1.935 + } 1.936 + 1.937 + 1.938 + if (!cert_dir) 1.939 + cert_dir = get_default_cert_dir(); 1.940 + 1.941 + VerifyCertDir(cert_dir, keyName); 1.942 + 1.943 + 1.944 + if ( compression_level < MIN_COMPRESSION_LEVEL || 1.945 + compression_level > MAX_COMPRESSION_LEVEL) { 1.946 + PR_fprintf(errorFD, "Compression level must be between %d and %d.\n", 1.947 + MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL); 1.948 + errorCount++; 1.949 + retval = -1; 1.950 + goto cleanup; 1.951 + } 1.952 + 1.953 + if (jartree && !keyName) { 1.954 + PR_fprintf(errorFD, "You must specify a key with which to sign.\n"); 1.955 + errorCount++; 1.956 + retval = -1; 1.957 + goto cleanup; 1.958 + } 1.959 + 1.960 + readOnly = (genkey == NULL); /* only key generation requires write */ 1.961 + if (InitCrypto(cert_dir, readOnly)) { 1.962 + PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n"); 1.963 + errorCount++; 1.964 + retval = -1; 1.965 + goto cleanup; 1.966 + } 1.967 + 1.968 + if (enableOCSP) { 1.969 + SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB()); 1.970 + if (rv != SECSuccess) { 1.971 + PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n"); 1.972 + errorCount++; 1.973 + retval = -1; 1.974 + } 1.975 + } 1.976 + 1.977 + if (verify) { 1.978 + if (VerifyJar(verify)) { 1.979 + errorCount++; 1.980 + retval = -1; 1.981 + goto cleanup; 1.982 + } 1.983 + } else if (list_certs) { 1.984 + if (ListCerts(keyName, list_certs)) { 1.985 + errorCount++; 1.986 + retval = -1; 1.987 + goto cleanup; 1.988 + } 1.989 + } else if (list_modules) { 1.990 + JarListModules(); 1.991 + } else if (genkey) { 1.992 + if (GenerateCert(genkey, keySize, token)) { 1.993 + errorCount++; 1.994 + retval = -1; 1.995 + goto cleanup; 1.996 + } 1.997 + } else if (tell_who) { 1.998 + if (JarWho(tell_who)) { 1.999 + errorCount++; 1.1000 + retval = -1; 1.1001 + goto cleanup; 1.1002 + } 1.1003 + } else if (javascript && jartree) { 1.1004 + /* make sure directory exists */ 1.1005 + PRDir * dir; 1.1006 + dir = PR_OpenDir(jartree); 1.1007 + if (!dir) { 1.1008 + PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n", 1.1009 + jartree); 1.1010 + errorCount++; 1.1011 + retval = -1; 1.1012 + goto cleanup; 1.1013 + } else { 1.1014 + PR_CloseDir(dir); 1.1015 + } 1.1016 + 1.1017 + /* undo junk from prior runs of signtool*/ 1.1018 + if (RemoveAllArc(jartree)) { 1.1019 + PR_fprintf(errorFD, "Error removing archive directories under %s\n", 1.1020 + jartree); 1.1021 + errorCount++; 1.1022 + retval = -1; 1.1023 + goto cleanup; 1.1024 + } 1.1025 + 1.1026 + /* traverse all the htm|html files in the directory */ 1.1027 + if (InlineJavaScript(jartree, !noRecurse)) { 1.1028 + retval = -1; 1.1029 + goto cleanup; 1.1030 + } 1.1031 + 1.1032 + /* sign any resultant .arc directories created in above step */ 1.1033 + if (SignAllArc(jartree, keyName, javascript, metafile, install_script, 1.1034 + optimize, !noRecurse)) { 1.1035 + retval = -1; 1.1036 + goto cleanup; 1.1037 + } 1.1038 + 1.1039 + if (!leaveArc) { 1.1040 + RemoveAllArc(jartree); 1.1041 + } 1.1042 + 1.1043 + if (errorCount > 0 || warningCount > 0) { 1.1044 + PR_fprintf(outputFD, "%d error%s, %d warning%s.\n", 1.1045 + errorCount, 1.1046 + errorCount == 1 ? "" : "s", warningCount, warningCount 1.1047 + == 1 ? "" : "s"); 1.1048 + } else { 1.1049 + PR_fprintf(outputFD, "Directory %s signed successfully.\n", 1.1050 + jartree); 1.1051 + } 1.1052 + } else if (jartree) { 1.1053 + SignArchive(jartree, keyName, zipfile, javascript, metafile, 1.1054 + install_script, optimize, !noRecurse); 1.1055 + } else 1.1056 + Usage(); 1.1057 + 1.1058 +cleanup: 1.1059 + if (extensions) { 1.1060 + PL_HashTableDestroy(extensions); 1.1061 + extensions = NULL; 1.1062 + } 1.1063 + if (excludeDirs) { 1.1064 + PL_HashTableDestroy(excludeDirs); 1.1065 + excludeDirs = NULL; 1.1066 + } 1.1067 + if (outputFD != PR_STDOUT) { 1.1068 + PR_Close(outputFD); 1.1069 + } 1.1070 + rm_dash_r(TMP_OUTPUT); 1.1071 + if (retval == 0) { 1.1072 + if (NSS_Shutdown() != SECSuccess) { 1.1073 + exit(1); 1.1074 + } 1.1075 + } 1.1076 + return retval; 1.1077 +} 1.1078 + 1.1079 +