security/nss/cmd/signtool/signtool.c

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

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

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  *  SIGNTOOL
     7  *
     8  *  A command line tool to create manifest files
     9  *  from a directory hierarchy. It is assumed that
    10  *  the tree will be equivalent to what resides
    11  *  or will reside in an archive. 
    12  *
    13  * 
    14  */
    16 #include "nss.h"
    17 #include "signtool.h"
    18 #include "prmem.h"
    19 #include "prio.h"
    21 /***********************************************************************
    22  * Global Variable Definitions
    23  */
    24 char	*progName; /* argv[0] */
    26 /* password data */
    27 secuPWData  pwdata = { PW_NONE, 0 };
    29 /* directories or files to exclude in descent */
    30 PLHashTable *excludeDirs = NULL;
    31 static PRBool exclusionsGiven = PR_FALSE;
    33 /* zatharus is the man who knows no time, dies tragic death */
    34 int	no_time = 0;
    36 /* -b basename of .rsa, .sf files */
    37 char	*base = DEFAULT_BASE_NAME;
    39 /* Only sign files with this extension */
    40 PLHashTable *extensions = NULL;
    41 PRBool extensionsGiven = PR_FALSE;
    43 char	*scriptdir = NULL;
    45 int	verbosity = 0;
    47 PRFileDesc *outputFD = NULL, *errorFD = NULL;
    49 int	errorCount = 0, warningCount = 0;
    51 int	compression_level = DEFAULT_COMPRESSION_LEVEL;
    52 PRBool compression_level_specified = PR_FALSE;
    54 int	xpi_arc = 0;
    56 /* Command-line arguments */
    57 static char	*genkey = NULL;
    58 static char	*verify = NULL;
    59 static char	*zipfile = NULL;
    60 static char	*cert_dir = NULL;
    61 static int	javascript = 0;
    62 static char	*jartree = NULL;
    63 static char	*keyName = NULL;
    64 static char	*metafile = NULL;
    65 static char	*install_script = NULL;
    66 static int	list_certs = 0;
    67 static int	list_modules = 0;
    68 static int	optimize = 0;
    69 static int	enableOCSP = 0;
    70 static char	*tell_who = NULL;
    71 static char	*outfile = NULL;
    72 static char	*cmdFile = NULL;
    73 static PRBool noRecurse = PR_FALSE;
    74 static PRBool leaveArc = PR_FALSE;
    75 static int	keySize = -1;
    76 static char	*token = NULL;
    78 typedef enum {
    79     UNKNOWN_OPT,
    80     HELP_OPT,
    81     LONG_HELP_OPT,
    82     BASE_OPT,
    83     COMPRESSION_OPT,
    84     CERT_DIR_OPT,
    85     EXTENSION_OPT,
    86     INSTALL_SCRIPT_OPT,
    87     SCRIPTDIR_OPT,
    88     CERTNAME_OPT,
    89     LIST_OBJSIGN_CERTS_OPT,
    90     LIST_ALL_CERTS_OPT,
    91     METAFILE_OPT,
    92     OPTIMIZE_OPT,
    93     ENABLE_OCSP_OPT,
    94     PASSWORD_OPT,
    95     VERIFY_OPT,
    96     WHO_OPT,
    97     EXCLUDE_OPT,
    98     NO_TIME_OPT,
    99     JAVASCRIPT_OPT,
   100     ZIPFILE_OPT,
   101     GENKEY_OPT,
   102     MODULES_OPT,
   103     NORECURSE_OPT,
   104     SIGNDIR_OPT,
   105     OUTFILE_OPT,
   106     COMMAND_FILE_OPT,
   107     LEAVE_ARC_OPT,
   108     VERBOSITY_OPT,
   109     KEYSIZE_OPT,
   110     TOKEN_OPT,
   111     XPI_ARC_OPT
   112 } 
   115 OPT_TYPE;
   117 typedef enum {
   118     DUPLICATE_OPTION_ERR = 0,
   119     OPTION_NEEDS_ARG_ERR
   120 } 
   123 Error;
   125 static char	*errStrings[] = {
   126     "warning: %s option specified more than once.\n"
   127     "Only last specification will be used.\n",
   128     "ERROR: option \"%s\" requires an argument.\n"
   129 };
   132 static int	ProcessOneOpt(OPT_TYPE type, char *arg);
   134 /*********************************************************************
   135  *
   136  * P r o c e s s C o m m a n d F i l e
   137  */
   138 int
   139 ProcessCommandFile()
   140 {
   141     PRFileDesc * fd;
   142 #define CMD_FILE_BUFSIZE 1024
   143     char	buf[CMD_FILE_BUFSIZE];
   144     char	*equals;
   145     int	linenum = 0;
   146     int	retval = -1;
   147     OPT_TYPE type;
   149     fd = PR_Open(cmdFile, PR_RDONLY, 0777);
   150     if (!fd) {
   151 	PR_fprintf(errorFD, "ERROR: Unable to open command file %s.\n");
   152 	errorCount++;
   153 	return - 1;
   154     }
   156     while (pr_fgets(buf, CMD_FILE_BUFSIZE, fd)) {
   157 	char	*eol;
   158 	linenum++;
   160 	/* Chop off final newline */
   161 	eol = PL_strchr(buf, '\r');
   162 	if (!eol) {
   163 	    eol = PL_strchr(buf, '\n');
   164 	}
   165 	if (eol) 
   166 	    *eol = '\0';
   168 	equals = PL_strchr(buf, '=');
   169 	if (!equals) {
   170 	    continue;
   171 	}
   173 	*equals = '\0';
   174 	equals++;
   176 	/* Now buf points to the attribute, and equals points to the value. */
   178 	/* This is pretty straightforward, just deal with whatever attribute
   179 		 * this is */
   180 	if (!PL_strcasecmp(buf, "basename")) {
   181 	    type = BASE_OPT;
   182 	} else if (!PL_strcasecmp(buf, "compression")) {
   183 	    type = COMPRESSION_OPT;
   184 	} else if (!PL_strcasecmp(buf, "certdir")) {
   185 	    type = CERT_DIR_OPT;
   186 	} else if (!PL_strcasecmp(buf, "extension")) {
   187 	    type = EXTENSION_OPT;
   188 	} else if (!PL_strcasecmp(buf, "generate")) {
   189 	    type = GENKEY_OPT;
   190 	} else if (!PL_strcasecmp(buf, "installScript")) {
   191 	    type = INSTALL_SCRIPT_OPT;
   192 	} else if (!PL_strcasecmp(buf, "javascriptdir")) {
   193 	    type = SCRIPTDIR_OPT;
   194 	} else if (!PL_strcasecmp(buf, "htmldir")) {
   195 	    type = JAVASCRIPT_OPT;
   196 	    if (jartree) {
   197 		PR_fprintf(errorFD,
   198 		    "warning: directory to be signed specified more than once."
   199 		    " Only last specification will be used.\n");
   200 		warningCount++;
   201 		PR_Free(jartree); 
   202 		jartree = NULL;
   203 	    }
   204 	    jartree = PL_strdup(equals);
   205 	} else if (!PL_strcasecmp(buf, "certname")) {
   206 	    type = CERTNAME_OPT;
   207 	} else if (!PL_strcasecmp(buf, "signdir")) {
   208 	    type = SIGNDIR_OPT;
   209 	} else if (!PL_strcasecmp(buf, "list")) {
   210 	    type = LIST_OBJSIGN_CERTS_OPT;
   211 	} else if (!PL_strcasecmp(buf, "listall")) {
   212 	    type = LIST_ALL_CERTS_OPT;
   213 	} else if (!PL_strcasecmp(buf, "metafile")) {
   214 	    type = METAFILE_OPT;
   215 	} else if (!PL_strcasecmp(buf, "modules")) {
   216 	    type = MODULES_OPT;
   217 	} else if (!PL_strcasecmp(buf, "optimize")) {
   218 	    type = OPTIMIZE_OPT;
   219 	} else if (!PL_strcasecmp(buf, "ocsp")) {
   220 	    type = ENABLE_OCSP_OPT;
   221 	} else if (!PL_strcasecmp(buf, "password")) {
   222 	    type = PASSWORD_OPT;
   223 	} else if (!PL_strcasecmp(buf, "verify")) {
   224 	    type = VERIFY_OPT;
   225 	} else if (!PL_strcasecmp(buf, "who")) {
   226 	    type = WHO_OPT;
   227 	} else if (!PL_strcasecmp(buf, "exclude")) {
   228 	    type = EXCLUDE_OPT;
   229 	} else if (!PL_strcasecmp(buf, "notime")) {
   230 	    type = NO_TIME_OPT;
   231 	} else if (!PL_strcasecmp(buf, "jarfile")) {
   232 	    type = ZIPFILE_OPT;
   233 	} else if (!PL_strcasecmp(buf, "outfile")) {
   234 	    type = OUTFILE_OPT;
   235 	} else if (!PL_strcasecmp(buf, "leavearc")) {
   236 	    type = LEAVE_ARC_OPT;
   237 	} else if (!PL_strcasecmp(buf, "verbosity")) {
   238 	    type = VERBOSITY_OPT;
   239 	} else if (!PL_strcasecmp(buf, "keysize")) {
   240 	    type = KEYSIZE_OPT;
   241 	} else if (!PL_strcasecmp(buf, "token")) {
   242 	    type = TOKEN_OPT;
   243 	} else if (!PL_strcasecmp(buf, "xpi")) {
   244 	    type = XPI_ARC_OPT;
   245 	} else {
   246 	    PR_fprintf(errorFD,
   247 	        "warning: unknown attribute \"%s\" in command file, line %d.\n",
   248 	         					buf, linenum);
   249 	    warningCount++;
   250 	    type = UNKNOWN_OPT;
   251 	}
   253 	/* Process the option, whatever it is */
   254 	if (type != UNKNOWN_OPT) {
   255 	    if (ProcessOneOpt(type, equals) == -1) {
   256 		goto finish;
   257 	    }
   258 	}
   259     }
   261     retval = 0;
   263 finish:
   264     PR_Close(fd);
   265     return retval;
   266 }
   269 /*********************************************************************
   270  *
   271  * p a r s e _ a r g s
   272  */
   273 static int	
   274 parse_args(int argc, char *argv[])
   275 {
   276     char	*opt;
   277     char	*arg;
   278     int	needsInc = 0;
   279     int	i;
   280     OPT_TYPE type;
   282     /* Loop over all arguments */
   283     for (i = 1; i < argc; i++) {
   284 	opt = argv[i];
   285 	arg = NULL;
   287 	if (opt[0] == '-') {
   288 	    if (opt[1] == '-') {
   289 		/* word option */
   290 		if (i < argc - 1) {
   291 		    needsInc = 1;
   292 		    arg = argv[i+1];
   293 		} else {
   294 		    arg = NULL;
   295 		}
   297 		if ( !PL_strcasecmp(opt + 2, "norecurse")) {
   298 		    type = NORECURSE_OPT;
   299 		} else if ( !PL_strcasecmp(opt + 2, "leavearc")) {
   300 		    type = LEAVE_ARC_OPT;
   301 		} else if ( !PL_strcasecmp(opt + 2, "verbosity")) {
   302 		    type = VERBOSITY_OPT;
   303 		} else if ( !PL_strcasecmp(opt + 2, "outfile")) {
   304 		    type = OUTFILE_OPT;
   305 		} else if ( !PL_strcasecmp(opt + 2, "keysize")) {
   306 		    type = KEYSIZE_OPT;
   307 		} else if ( !PL_strcasecmp(opt + 2, "token")) {
   308 		    type = TOKEN_OPT;
   309 		} else {
   310 		    PR_fprintf(errorFD, "warning: unknown option: %s\n",
   311 		         opt);
   312 		    warningCount++;
   313 		    type = UNKNOWN_OPT;
   314 		}
   315 	    } else {
   316 		/* char option */
   317 		if (opt[2] != '\0') {
   318 		    arg = opt + 2;
   319 		} else if (i < argc - 1) {
   320 		    needsInc = 1;
   321 		    arg = argv[i+1];
   322 		} else {
   323 		    arg = NULL;
   324 		}
   326 		switch (opt[1]) {
   327 		case 'b':
   328 		    type = BASE_OPT;
   329 		    break;
   330 		case 'c':
   331 		    type = COMPRESSION_OPT;
   332 		    break;
   333 		case 'd':
   334 		    type = CERT_DIR_OPT;
   335 		    break;
   336 		case 'e':
   337 		    type = EXTENSION_OPT;
   338 		    break;
   339 		case 'f':
   340 		    type = COMMAND_FILE_OPT;
   341 		    break;
   342 		case 'h':
   343 		    type = HELP_OPT;
   344 		    break;
   345 		case 'H':
   346 		    type = LONG_HELP_OPT;
   347 		    break;
   348 		case 'i':
   349 		    type = INSTALL_SCRIPT_OPT;
   350 		    break;
   351 		case 'j':
   352 		    type = SCRIPTDIR_OPT;
   353 		    break;
   354 		case 'k':
   355 		    type = CERTNAME_OPT;
   356 		    break;
   357 		case 'l':
   358 		    type = LIST_OBJSIGN_CERTS_OPT;
   359 		    break;
   360 		case 'L':
   361 		    type = LIST_ALL_CERTS_OPT;
   362 		    break;
   363 		case 'm':
   364 		    type = METAFILE_OPT;
   365 		    break;
   366 		case 'o':
   367 		    type = OPTIMIZE_OPT;
   368 		    break;
   369 		case 'O':
   370 		    type = ENABLE_OCSP_OPT;
   371 		    break;
   372 		case 'p':
   373 		    type = PASSWORD_OPT;
   374 		    break;
   375 		case 'v':
   376 		    type = VERIFY_OPT;
   377 		    break;
   378 		case 'w':
   379 		    type = WHO_OPT;
   380 		    break;
   381 		case 'x':
   382 		    type = EXCLUDE_OPT;
   383 		    break;
   384 		case 'X':
   385 		    type = XPI_ARC_OPT;
   386 		    break;
   387 		case 'z':
   388 		    type = NO_TIME_OPT;
   389 		    break;
   390 		case 'J':
   391 		    type = JAVASCRIPT_OPT;
   392 		    break;
   393 		case 'Z':
   394 		    type = ZIPFILE_OPT;
   395 		    break;
   396 		case 'G':
   397 		    type = GENKEY_OPT;
   398 		    break;
   399 		case 'M':
   400 		    type = MODULES_OPT;
   401 		    break;
   402 		case 's':
   403 		    type = KEYSIZE_OPT;
   404 		    break;
   405 		case 't':
   406 		    type = TOKEN_OPT;
   407 		    break;
   408 		default:
   409 		    type = UNKNOWN_OPT;
   410 		    PR_fprintf(errorFD, "warning: unrecognized option: -%c.\n",
   412 		        opt[1]);
   413 		    warningCount++;
   414 		    break;
   415 		}
   416 	    }
   417 	} else {
   418 	    type = UNKNOWN_OPT;
   419 	    if (i == argc - 1) {
   420 		if (jartree) {
   421 		    PR_fprintf(errorFD,
   422 		        "warning: directory to be signed specified more than once.\n"
   423 		        " Only last specification will be used.\n");
   424 		    warningCount++;
   425 		    PR_Free(jartree); 
   426 		    jartree = NULL;
   427 		}
   428 		jartree = PL_strdup(opt);
   429 	    } else {
   430 		PR_fprintf(errorFD, "warning: unrecognized option: %s\n", opt);
   431 		warningCount++;
   432 	    }
   433 	}
   435 	if (type != UNKNOWN_OPT) {
   436 	    short	ateArg = ProcessOneOpt(type, arg);
   437 	    if (ateArg == -1) {
   438 		/* error */
   439 		return - 1;
   440 	    } 
   441 	    if (ateArg && needsInc) {
   442 		i++;
   443 	    }
   444 	}
   445     }
   447     return 0;
   448 }
   451 /*********************************************************************
   452  *
   453  * P r o c e s s O n e O p t
   454  *
   455  * Since options can come from different places (command file, word options,
   456  * char options), this is a central function that is called to deal with
   457  * them no matter where they come from.
   458  *
   459  * type is the type of option.
   460  * arg is the argument to the option, possibly NULL.
   461  * Returns 1 if the argument was eaten, 0 if it wasn't, and -1 for error.
   462  */
   463 static int	
   464 ProcessOneOpt(OPT_TYPE type, char *arg)
   465 {
   466     int	ate = 0;
   468     switch (type) {
   469     case HELP_OPT:
   470 	Usage();
   471 	break;
   472     case LONG_HELP_OPT:
   473 	LongUsage();
   474 	break;
   475     case BASE_OPT:
   476 	if (base) {
   477 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-b");
   478 	    warningCount++;
   479 	    PR_Free(base); 
   480 	    base = NULL;
   481 	}
   482 	if (!arg) {
   483 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-b");
   484 	    errorCount++;
   485 	    goto loser;
   486 	}
   487 	base = PL_strdup(arg);
   488 	ate = 1;
   489 	break;
   490     case COMPRESSION_OPT:
   491 	if (compression_level_specified) {
   492 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-c");
   493 	    warningCount++;
   494 	}
   495 	if ( !arg ) {
   496 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-c");
   497 	    errorCount++;
   498 	    goto loser;
   499 	}
   500 	compression_level = atoi(arg);
   501 	compression_level_specified = PR_TRUE;
   502 	ate = 1;
   503 	break;
   504     case CERT_DIR_OPT:
   505 	if (cert_dir) {
   506 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-d");
   507 	    warningCount++;
   508 	    PR_Free(cert_dir); 
   509 	    cert_dir = NULL;
   510 	}
   511 	if (!arg) {
   512 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-d");
   513 	    errorCount++;
   514 	    goto loser;
   515 	}
   516 	cert_dir = PL_strdup(arg);
   517 	ate = 1;
   518 	break;
   519     case EXTENSION_OPT:
   520 	if (!arg) {
   521 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   522 	         				"extension (-e)");
   523 	    errorCount++;
   524 	    goto loser;
   525 	}
   526 	PL_HashTableAdd(extensions, arg, arg);
   527 	extensionsGiven = PR_TRUE;
   528 	ate = 1;
   529 	break;
   530     case INSTALL_SCRIPT_OPT:
   531 	if (install_script) {
   532 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   533 	         				"installScript (-i)");
   534 	    warningCount++;
   535 	    PR_Free(install_script); 
   536 	    install_script = NULL;
   537 	}
   538 	if (!arg) {
   539 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   540 	         				"installScript (-i)");
   541 	    errorCount++;
   542 	    goto loser;
   543 	}
   544 	install_script = PL_strdup(arg);
   545 	ate = 1;
   546 	break;
   547     case SCRIPTDIR_OPT:
   548 	if (scriptdir) {
   549 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   550 	         				"javascriptdir (-j)");
   551 	    warningCount++;
   552 	    PR_Free(scriptdir); 
   553 	    scriptdir = NULL;
   554 	}
   555 	if (!arg) {
   556 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   557 	         				"javascriptdir (-j)");
   558 	    errorCount++;
   559 	    goto loser;
   560 	}
   561 	scriptdir = PL_strdup(arg);
   562 	ate = 1;
   563 	break;
   564     case CERTNAME_OPT:
   565 	if (keyName) {
   566 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   567 	         				"keyName (-k)");
   568 	    warningCount++;
   569 	    PR_Free(keyName); 
   570 	    keyName = NULL;
   571 	}
   572 	if (!arg) {
   573 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   574 	         				"keyName (-k)");
   575 	    errorCount++;
   576 	    goto loser;
   577 	}
   578 	keyName = PL_strdup(arg);
   579 	ate = 1;
   580 	break;
   581     case LIST_OBJSIGN_CERTS_OPT:
   582     case LIST_ALL_CERTS_OPT:
   583 	if (list_certs != 0) {
   584 	    PR_fprintf(errorFD,
   585 	        "warning: only one of -l and -L may be specified.\n");
   586 	    warningCount++;
   587 	}
   588 	list_certs = (type == LIST_OBJSIGN_CERTS_OPT ? 1 : 2);
   589 	break;
   590     case METAFILE_OPT:
   591 	if (metafile) {
   592 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   593 	         				"metafile (-m)");
   594 	    warningCount++;
   595 	    PR_Free(metafile); 
   596 	    metafile = NULL;
   597 	}
   598 	if (!arg) {
   599 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   600 	         				"metafile (-m)");
   601 	    errorCount++;
   602 	    goto loser;
   603 	}
   604 	metafile = PL_strdup(arg);
   605 	ate = 1;
   606 	break;
   607     case OPTIMIZE_OPT:
   608 	optimize = 1;
   609 	break;
   610     case ENABLE_OCSP_OPT:
   611 	enableOCSP = 1;
   612 	break;
   613     case PASSWORD_OPT:
   614 	if (pwdata.data) {
   615 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   616 	         				"password (-p)");
   617 	    warningCount++;
   618 	    PR_Free(pwdata.data); 
   619 	    pwdata.data = NULL;
   620 	}
   621 	if (!arg) {
   622 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   623 	         				"password (-p)");
   624 	    errorCount++;
   625 	    goto loser;
   626 	}
   627         pwdata.source = PW_PLAINTEXT;
   628 	pwdata.data = PL_strdup(arg);
   629 	ate = 1;
   630 	break;
   631     case VERIFY_OPT:
   632 	if (verify) {
   633 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   634 	         				"verify (-v)");
   635 	    warningCount++;
   636 	    PR_Free(verify); 
   637 	    verify = NULL;
   638 	}
   639 	if (!arg) {
   640 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   641 	         				"verify (-v)");
   642 	    errorCount++;
   643 	    goto loser;
   644 	}
   645 	verify = PL_strdup(arg);
   646 	ate = 1;
   647 	break;
   648     case WHO_OPT:
   649 	if (tell_who) {
   650 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   651 	         				"who (-v)");
   652 	    warningCount++;
   653 	    PR_Free(tell_who); 
   654 	    tell_who = NULL;
   655 	}
   656 	if (!arg) {
   657 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   658 	         				"who (-w)");
   659 	    errorCount++;
   660 	    goto loser;
   661 	}
   662 	tell_who = PL_strdup(arg);
   663 	ate = 1;
   664 	break;
   665     case EXCLUDE_OPT:
   666 	if (!arg) {
   667 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   668 	         				"exclude (-x)");
   669 	    errorCount++;
   670 	    goto loser;
   671 	}
   672 	PL_HashTableAdd(excludeDirs, arg, arg);
   673 	exclusionsGiven = PR_TRUE;
   674 	ate = 1;
   675 	break;
   676     case NO_TIME_OPT:
   677 	no_time = 1;
   678 	break;
   679     case JAVASCRIPT_OPT:
   680 	javascript++;
   681 	break;
   682     case ZIPFILE_OPT:
   683 	if (zipfile) {
   684 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   685 	         				"jarfile (-Z)");
   686 	    warningCount++;
   687 	    PR_Free(zipfile); 
   688 	    zipfile = NULL;
   689 	}
   690 	if (!arg) {
   691 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   692 	         				"jarfile (-Z)");
   693 	    errorCount++;
   694 	    goto loser;
   695 	}
   696 	zipfile = PL_strdup(arg);
   697 	ate = 1;
   698 	break;
   699     case GENKEY_OPT:
   700 	if (genkey) {
   701 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   702 	         				"generate (-G)");
   703 	    warningCount++;
   704 	    PR_Free(genkey); 
   705 	    genkey = NULL;
   706 	}
   707 	if (!arg) {
   708 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   709 	         				"generate (-G)");
   710 	    errorCount++;
   711 	    goto loser;
   712 	}
   713 	genkey = PL_strdup(arg);
   714 	ate = 1;
   715 	break;
   716     case MODULES_OPT:
   717 	list_modules++;
   718 	break;
   719     case SIGNDIR_OPT:
   720 	if (jartree) {
   721 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   722 	         				"signdir");
   723 	    warningCount++;
   724 	    PR_Free(jartree); 
   725 	    jartree = NULL;
   726 	}
   727 	if (!arg) {
   728 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   729 	         "signdir");
   730 	    errorCount++;
   731 	    goto loser;
   732 	}
   733 	jartree = PL_strdup(arg);
   734 	ate = 1;
   735 	break;
   736     case OUTFILE_OPT:
   737 	if (outfile) {
   738 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   739 	         				"outfile");
   740 	    warningCount++;
   741 	    PR_Free(outfile); 
   742 	    outfile = NULL;
   743 	}
   744 	if (!arg) {
   745 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   746 	         "outfile");
   747 	    errorCount++;
   748 	    goto loser;
   749 	}
   750 	outfile = PL_strdup(arg);
   751 	ate = 1;
   752 	break;
   753     case COMMAND_FILE_OPT:
   754 	if (cmdFile) {
   755 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
   756 	         "-f");
   757 	    warningCount++;
   758 	    PR_Free(cmdFile); 
   759 	    cmdFile = NULL;
   760 	}
   761 	if (!arg) {
   762 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   763 	         "-f");
   764 	    errorCount++;
   765 	    goto loser;
   766 	}
   767 	cmdFile = PL_strdup(arg);
   768 	ate = 1;
   769 	break;
   770     case NORECURSE_OPT:
   771 	noRecurse = PR_TRUE;
   772 	break;
   773     case LEAVE_ARC_OPT:
   774 	leaveArc = PR_TRUE;
   775 	break;
   776     case VERBOSITY_OPT:
   777 	if (!arg) {
   778 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
   779 	         			  "--verbosity");
   780 	    errorCount++;
   781 	    goto loser;
   782 	}
   783 	verbosity = atoi(arg);
   784 	ate = 1;
   785 	break;
   786     case KEYSIZE_OPT:
   787 	if ( keySize != -1 ) {
   788 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-s");
   789 	    warningCount++;
   790 	}
   791 	keySize = atoi(arg);
   792 	ate = 1;
   793 	if ( keySize < 1 || keySize > MAX_RSA_KEY_SIZE ) {
   794 	    PR_fprintf(errorFD, "Invalid key size: %d.\n", keySize);
   795 	    errorCount++;
   796 	    goto loser;
   797 	}
   798 	break;
   799     case TOKEN_OPT:
   800 	if ( token ) {
   801 	    PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-t");
   802 	    PR_Free(token); 
   803 	    token = NULL;
   804 	}
   805 	if ( !arg ) {
   806 	    PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-t");
   807 	    errorCount++;
   808 	    goto loser;
   809 	}
   810 	token = PL_strdup(arg);
   811 	ate = 1;
   812 	break;
   813     case XPI_ARC_OPT:
   814 	xpi_arc = 1;
   815 	break;
   816     default:
   817 	PR_fprintf(errorFD, "warning: unknown option\n");
   818 	warningCount++;
   819 	break;
   820     }
   822     return ate;
   823 loser:
   824     return - 1;
   825 }
   828 /*********************************************************************
   829  *
   830  * m a i n
   831  */
   832 int
   833 main(int argc, char *argv[])
   834 {
   835     PRBool readOnly;
   836     int	retval = 0;
   838     outputFD = PR_STDOUT;
   839     errorFD = PR_STDERR;
   841     progName = argv[0];
   843     if (argc < 2) {
   844 	Usage();
   845     }
   847     excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
   848          					PL_CompareStrings, NULL, NULL);
   849     extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
   850          					PL_CompareStrings, NULL, NULL);
   852     if (parse_args(argc, argv)) {
   853 	retval = -1;
   854 	goto cleanup;
   855     }
   857     /* Parse the command file if one was given */
   858     if (cmdFile) {
   859 	if (ProcessCommandFile()) {
   860 	    retval = -1;
   861 	    goto cleanup;
   862 	}
   863     }
   865     /* Set up output redirection */
   866     if (outfile) {
   867 	if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) {
   868 	    /* delete the file if it is already present */
   869 	    PR_fprintf(errorFD,
   870 	        "warning: %s already exists and will be overwritten.\n",
   871 	         				outfile);
   872 	    warningCount++;
   873 	    if (PR_Delete(outfile) != PR_SUCCESS) {
   874 		PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile);
   875 		errorCount++;
   876 		exit(ERRX);
   877 	    }
   878 	}
   879 	outputFD = PR_Open(outfile,
   880 	    PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777);
   881 	if (!outputFD) {
   882 	    PR_fprintf(errorFD, "ERROR: Unable to create %s.\n",
   883 	         outfile);
   884 	    errorCount++;
   885 	    exit(ERRX);
   886 	}
   887 	errorFD = outputFD;
   888     }
   890     /* This seems to be a fairly common user error */
   892     if (verify && list_certs > 0) {
   893 	PR_fprintf (errorFD, "%s: Can't use -l and -v at the same time\n",
   894 	     		PROGRAM_NAME);
   895 	errorCount++;
   896 	retval = -1;
   897 	goto cleanup;
   898     }
   900     /* -J assumes -Z now */
   902     if (javascript && zipfile) {
   903 	PR_fprintf (errorFD, "%s: Can't use -J and -Z at the same time\n",
   904 	     		PROGRAM_NAME);
   905 	PR_fprintf (errorFD, "%s: -J option will create the jar files for you\n",
   906 	     		PROGRAM_NAME);
   907 	errorCount++;
   908 	retval = -1;
   909 	goto cleanup;
   910     }
   912     /* -X needs -Z */
   914     if (xpi_arc && !zipfile) {
   915 	PR_fprintf (errorFD, "%s: option XPI (-X) requires option jarfile (-Z)\n",
   916 	     		PROGRAM_NAME);
   917 	errorCount++;
   918 	retval = -1;
   919 	goto cleanup;
   920     }
   922     /* Less common mixing of -L with various options */
   924     if (list_certs > 0 && 
   925         (tell_who || zipfile || javascript || 
   926         scriptdir || extensionsGiven || exclusionsGiven || install_script)) {
   927 	PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n",
   928 	     			PROGRAM_NAME);
   929 	errorCount++;
   930 	retval = -1;
   931 	goto cleanup;
   932     }
   935     if (!cert_dir)
   936 	cert_dir = get_default_cert_dir();
   938     VerifyCertDir(cert_dir, keyName);
   941     if (	compression_level < MIN_COMPRESSION_LEVEL || 
   942         compression_level > MAX_COMPRESSION_LEVEL) {
   943 	PR_fprintf(errorFD, "Compression level must be between %d and %d.\n",
   944 	     		 MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
   945 	errorCount++;
   946 	retval = -1;
   947 	goto cleanup;
   948     }
   950     if (jartree && !keyName) {
   951 	PR_fprintf(errorFD, "You must specify a key with which to sign.\n");
   952 	errorCount++;
   953 	retval = -1;
   954 	goto cleanup;
   955     }
   957     readOnly = (genkey == NULL); /* only key generation requires write */
   958     if (InitCrypto(cert_dir, readOnly)) {
   959 	PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n");
   960 	errorCount++;
   961 	retval = -1;
   962 	goto cleanup;
   963     }
   965     if (enableOCSP) {
   966 	SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
   967 	if (rv != SECSuccess) {
   968 	    PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n");
   969 	    errorCount++;
   970 	    retval = -1;
   971 	}
   972     }
   974     if (verify) {
   975 	if (VerifyJar(verify)) {
   976 	    errorCount++;
   977 	    retval = -1;
   978 	    goto cleanup;
   979 	}
   980     } else if (list_certs) {
   981 	if (ListCerts(keyName, list_certs)) {
   982 	    errorCount++;
   983 	    retval = -1;
   984 	    goto cleanup;
   985 	}
   986     } else if (list_modules) {
   987 	JarListModules();
   988     } else if (genkey) {
   989 	if (GenerateCert(genkey, keySize, token)) {
   990 	    errorCount++;
   991 	    retval = -1;
   992 	    goto cleanup;
   993 	}
   994     } else if (tell_who) {
   995 	if (JarWho(tell_who)) {
   996 	    errorCount++;
   997 	    retval = -1;
   998 	    goto cleanup;
   999 	}
  1000     } else if (javascript && jartree) {
  1001 	/* make sure directory exists */
  1002 	PRDir * dir;
  1003 	dir = PR_OpenDir(jartree);
  1004 	if (!dir) {
  1005 	    PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n",
  1006 	         jartree);
  1007 	    errorCount++;
  1008 	    retval = -1;
  1009 	    goto cleanup;
  1010 	} else {
  1011 	    PR_CloseDir(dir);
  1014 	/* undo junk from prior runs of signtool*/
  1015 	if (RemoveAllArc(jartree)) {
  1016 	    PR_fprintf(errorFD, "Error removing archive directories under %s\n",
  1017 	         jartree);
  1018 	    errorCount++;
  1019 	    retval = -1;
  1020 	    goto cleanup;
  1023 	/* traverse all the htm|html files in the directory */
  1024 	if (InlineJavaScript(jartree, !noRecurse)) {
  1025 	    retval = -1;
  1026 	    goto cleanup;
  1029 	/* sign any resultant .arc directories created in above step */
  1030 	if (SignAllArc(jartree, keyName, javascript, metafile, install_script,
  1031 	     		optimize, !noRecurse)) {
  1032 	    retval = -1;
  1033 	    goto cleanup;
  1036 	if (!leaveArc) {
  1037 	    RemoveAllArc(jartree);
  1040 	if (errorCount > 0 || warningCount > 0) {
  1041 	    PR_fprintf(outputFD, "%d error%s, %d warning%s.\n",
  1042 	         errorCount,
  1043 	        errorCount == 1 ? "" : "s", warningCount, warningCount
  1044 	        == 1 ? "" : "s");
  1045 	} else {
  1046 	    PR_fprintf(outputFD, "Directory %s signed successfully.\n",
  1047 	         jartree);
  1049     } else if (jartree) {
  1050 	SignArchive(jartree, keyName, zipfile, javascript, metafile,
  1051 	     		install_script, optimize, !noRecurse);
  1052     } else
  1053 	Usage();
  1055 cleanup:
  1056     if (extensions) {
  1057 	PL_HashTableDestroy(extensions); 
  1058 	extensions = NULL;
  1060     if (excludeDirs) {
  1061 	PL_HashTableDestroy(excludeDirs); 
  1062 	excludeDirs = NULL;
  1064     if (outputFD != PR_STDOUT) {
  1065 	PR_Close(outputFD);
  1067     rm_dash_r(TMP_OUTPUT);
  1068     if (retval == 0) {
  1069 	if (NSS_Shutdown() != SECSuccess) {
  1070 	    exit(1);
  1073     return retval;

mercurial