diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/cmd/signtool/signtool.c | 1066 |
1 files changed, 1066 insertions, 0 deletions
diff --git a/security/nss/cmd/signtool/signtool.c b/security/nss/cmd/signtool/signtool.c new file mode 100644 index 0000000000..915a00fbc1 --- /dev/null +++ b/security/nss/cmd/signtool/signtool.c @@ -0,0 +1,1066 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * SIGNTOOL + * + * A command line tool to create manifest files + * from a directory hierarchy. It is assumed that + * the tree will be equivalent to what resides + * or will reside in an archive. + * + * + */ + +#include "nss.h" +#include "signtool.h" +#include "prmem.h" +#include "prio.h" + +/*********************************************************************** + * Global Variable Definitions + */ +char *progName; /* argv[0] */ + +/* password data */ +secuPWData pwdata = { PW_NONE, 0 }; + +/* directories or files to exclude in descent */ +PLHashTable *excludeDirs = NULL; +static PRBool exclusionsGiven = PR_FALSE; + +/* zatharus is the man who knows no time, dies tragic death */ +int no_time = 0; + +/* -b basename of .rsa, .sf files */ +char *base = DEFAULT_BASE_NAME; + +/* Only sign files with this extension */ +PLHashTable *extensions = NULL; +PRBool extensionsGiven = PR_FALSE; + +char *scriptdir = NULL; + +int verbosity = 0; + +PRFileDesc *outputFD = NULL, *errorFD = NULL; + +int errorCount = 0, warningCount = 0; + +int compression_level = DEFAULT_COMPRESSION_LEVEL; +PRBool compression_level_specified = PR_FALSE; + +int xpi_arc = 0; + +/* Command-line arguments */ +static char *genkey = NULL; +static char *verify = NULL; +static char *zipfile = NULL; +static char *cert_dir = NULL; +static int javascript = 0; +static char *jartree = NULL; +static char *keyName = NULL; +static char *metafile = NULL; +static char *install_script = NULL; +static int list_certs = 0; +static int list_modules = 0; +static int optimize = 0; +static int enableOCSP = 0; +static char *tell_who = NULL; +static char *outfile = NULL; +static char *cmdFile = NULL; +static PRBool noRecurse = PR_FALSE; +static PRBool leaveArc = PR_FALSE; +static int keySize = -1; +static char *token = NULL; + +typedef enum { + UNKNOWN_OPT, + HELP_OPT, + LONG_HELP_OPT, + BASE_OPT, + COMPRESSION_OPT, + CERT_DIR_OPT, + EXTENSION_OPT, + INSTALL_SCRIPT_OPT, + SCRIPTDIR_OPT, + CERTNAME_OPT, + LIST_OBJSIGN_CERTS_OPT, + LIST_ALL_CERTS_OPT, + METAFILE_OPT, + OPTIMIZE_OPT, + ENABLE_OCSP_OPT, + PASSWORD_OPT, + VERIFY_OPT, + WHO_OPT, + EXCLUDE_OPT, + NO_TIME_OPT, + JAVASCRIPT_OPT, + ZIPFILE_OPT, + GENKEY_OPT, + MODULES_OPT, + NORECURSE_OPT, + SIGNDIR_OPT, + OUTFILE_OPT, + COMMAND_FILE_OPT, + LEAVE_ARC_OPT, + VERBOSITY_OPT, + KEYSIZE_OPT, + TOKEN_OPT, + XPI_ARC_OPT +} + +OPT_TYPE; + +typedef enum { + DUPLICATE_OPTION_ERR = 0, + OPTION_NEEDS_ARG_ERR +} + +Error; + +static char *errStrings[] = { + "warning: %s option specified more than once.\n" + "Only last specification will be used.\n", + "ERROR: option \"%s\" requires an argument.\n" +}; + +static int ProcessOneOpt(OPT_TYPE type, char *arg); + +/********************************************************************* + * + * P r o c e s s C o m m a n d F i l e + */ +int +ProcessCommandFile() +{ + PRFileDesc *fd; +#define CMD_FILE_BUFSIZE 1024 + char buf[CMD_FILE_BUFSIZE]; + char *equals; + int linenum = 0; + int retval = -1; + OPT_TYPE type; + + fd = PR_Open(cmdFile, PR_RDONLY, 0777); + if (!fd) { + PR_fprintf(errorFD, "ERROR: Unable to open command file %s.\n"); + errorCount++; + return -1; + } + + while (pr_fgets(buf, CMD_FILE_BUFSIZE, fd)) { + char *eol; + linenum++; + + /* Chop off final newline */ + eol = PL_strchr(buf, '\r'); + if (!eol) { + eol = PL_strchr(buf, '\n'); + } + if (eol) + *eol = '\0'; + + equals = PL_strchr(buf, '='); + if (!equals) { + continue; + } + + *equals = '\0'; + equals++; + + /* Now buf points to the attribute, and equals points to the value. */ + + /* This is pretty straightforward, just deal with whatever attribute + * this is */ + if (!PL_strcasecmp(buf, "basename")) { + type = BASE_OPT; + } else if (!PL_strcasecmp(buf, "compression")) { + type = COMPRESSION_OPT; + } else if (!PL_strcasecmp(buf, "certdir")) { + type = CERT_DIR_OPT; + } else if (!PL_strcasecmp(buf, "extension")) { + type = EXTENSION_OPT; + } else if (!PL_strcasecmp(buf, "generate")) { + type = GENKEY_OPT; + } else if (!PL_strcasecmp(buf, "installScript")) { + type = INSTALL_SCRIPT_OPT; + } else if (!PL_strcasecmp(buf, "javascriptdir")) { + type = SCRIPTDIR_OPT; + } else if (!PL_strcasecmp(buf, "htmldir")) { + type = JAVASCRIPT_OPT; + if (jartree) { + PR_fprintf(errorFD, + "warning: directory to be signed specified more than once." + " Only last specification will be used.\n"); + warningCount++; + PR_Free(jartree); + jartree = NULL; + } + jartree = PL_strdup(equals); + } else if (!PL_strcasecmp(buf, "certname")) { + type = CERTNAME_OPT; + } else if (!PL_strcasecmp(buf, "signdir")) { + type = SIGNDIR_OPT; + } else if (!PL_strcasecmp(buf, "list")) { + type = LIST_OBJSIGN_CERTS_OPT; + } else if (!PL_strcasecmp(buf, "listall")) { + type = LIST_ALL_CERTS_OPT; + } else if (!PL_strcasecmp(buf, "metafile")) { + type = METAFILE_OPT; + } else if (!PL_strcasecmp(buf, "modules")) { + type = MODULES_OPT; + } else if (!PL_strcasecmp(buf, "optimize")) { + type = OPTIMIZE_OPT; + } else if (!PL_strcasecmp(buf, "ocsp")) { + type = ENABLE_OCSP_OPT; + } else if (!PL_strcasecmp(buf, "password")) { + type = PASSWORD_OPT; + } else if (!PL_strcasecmp(buf, "verify")) { + type = VERIFY_OPT; + } else if (!PL_strcasecmp(buf, "who")) { + type = WHO_OPT; + } else if (!PL_strcasecmp(buf, "exclude")) { + type = EXCLUDE_OPT; + } else if (!PL_strcasecmp(buf, "notime")) { + type = NO_TIME_OPT; + } else if (!PL_strcasecmp(buf, "jarfile")) { + type = ZIPFILE_OPT; + } else if (!PL_strcasecmp(buf, "outfile")) { + type = OUTFILE_OPT; + } else if (!PL_strcasecmp(buf, "leavearc")) { + type = LEAVE_ARC_OPT; + } else if (!PL_strcasecmp(buf, "verbosity")) { + type = VERBOSITY_OPT; + } else if (!PL_strcasecmp(buf, "keysize")) { + type = KEYSIZE_OPT; + } else if (!PL_strcasecmp(buf, "token")) { + type = TOKEN_OPT; + } else if (!PL_strcasecmp(buf, "xpi")) { + type = XPI_ARC_OPT; + } else { + PR_fprintf(errorFD, + "warning: unknown attribute \"%s\" in command file, line %d.\n", + buf, linenum); + warningCount++; + type = UNKNOWN_OPT; + } + + /* Process the option, whatever it is */ + if (type != UNKNOWN_OPT) { + if (ProcessOneOpt(type, equals) == -1) { + goto finish; + } + } + } + + retval = 0; + +finish: + PR_Close(fd); + return retval; +} + +/********************************************************************* + * + * p a r s e _ a r g s + */ +static int +parse_args(int argc, char *argv[]) +{ + char *opt; + char *arg; + int needsInc = 0; + int i; + OPT_TYPE type; + + /* Loop over all arguments */ + for (i = 1; i < argc; i++) { + opt = argv[i]; + arg = NULL; + + if (opt[0] == '-') { + if (opt[1] == '-') { + /* word option */ + if (i < argc - 1) { + needsInc = 1; + arg = argv[i + 1]; + } else { + arg = NULL; + } + + if (!PL_strcasecmp(opt + 2, "norecurse")) { + type = NORECURSE_OPT; + } else if (!PL_strcasecmp(opt + 2, "leavearc")) { + type = LEAVE_ARC_OPT; + } else if (!PL_strcasecmp(opt + 2, "verbosity")) { + type = VERBOSITY_OPT; + } else if (!PL_strcasecmp(opt + 2, "outfile")) { + type = OUTFILE_OPT; + } else if (!PL_strcasecmp(opt + 2, "keysize")) { + type = KEYSIZE_OPT; + } else if (!PL_strcasecmp(opt + 2, "token")) { + type = TOKEN_OPT; + } else { + PR_fprintf(errorFD, "warning: unknown option: %s\n", + opt); + warningCount++; + type = UNKNOWN_OPT; + } + } else { + /* char option */ + if (opt[2] != '\0') { + arg = opt + 2; + } else if (i < argc - 1) { + needsInc = 1; + arg = argv[i + 1]; + } else { + arg = NULL; + } + + switch (opt[1]) { + case 'b': + type = BASE_OPT; + break; + case 'c': + type = COMPRESSION_OPT; + break; + case 'd': + type = CERT_DIR_OPT; + break; + case 'e': + type = EXTENSION_OPT; + break; + case 'f': + type = COMMAND_FILE_OPT; + break; + case 'h': + type = HELP_OPT; + break; + case 'H': + type = LONG_HELP_OPT; + break; + case 'i': + type = INSTALL_SCRIPT_OPT; + break; + case 'j': + type = SCRIPTDIR_OPT; + break; + case 'k': + type = CERTNAME_OPT; + break; + case 'l': + type = LIST_OBJSIGN_CERTS_OPT; + break; + case 'L': + type = LIST_ALL_CERTS_OPT; + break; + case 'm': + type = METAFILE_OPT; + break; + case 'o': + type = OPTIMIZE_OPT; + break; + case 'O': + type = ENABLE_OCSP_OPT; + break; + case 'p': + type = PASSWORD_OPT; + break; + case 'v': + type = VERIFY_OPT; + break; + case 'w': + type = WHO_OPT; + break; + case 'x': + type = EXCLUDE_OPT; + break; + case 'X': + type = XPI_ARC_OPT; + break; + case 'z': + type = NO_TIME_OPT; + break; + case 'J': + type = JAVASCRIPT_OPT; + break; + case 'Z': + type = ZIPFILE_OPT; + break; + case 'G': + type = GENKEY_OPT; + break; + case 'M': + type = MODULES_OPT; + break; + case 's': + type = KEYSIZE_OPT; + break; + case 't': + type = TOKEN_OPT; + break; + default: + type = UNKNOWN_OPT; + PR_fprintf(errorFD, "warning: unrecognized option: -%c.\n", + opt[1]); + warningCount++; + break; + } + } + } else { + type = UNKNOWN_OPT; + if (i == argc - 1) { + if (jartree) { + PR_fprintf(errorFD, + "warning: directory to be signed specified more than once.\n" + " Only last specification will be used.\n"); + warningCount++; + PR_Free(jartree); + jartree = NULL; + } + jartree = PL_strdup(opt); + } else { + PR_fprintf(errorFD, "warning: unrecognized option: %s\n", opt); + warningCount++; + } + } + + if (type != UNKNOWN_OPT) { + short ateArg = ProcessOneOpt(type, arg); + if (ateArg == -1) { + /* error */ + return -1; + } + if (ateArg && needsInc) { + i++; + } + } + } + + return 0; +} + +/********************************************************************* + * + * P r o c e s s O n e O p t + * + * Since options can come from different places (command file, word options, + * char options), this is a central function that is called to deal with + * them no matter where they come from. + * + * type is the type of option. + * arg is the argument to the option, possibly NULL. + * Returns 1 if the argument was eaten, 0 if it wasn't, and -1 for error. + */ +static int +ProcessOneOpt(OPT_TYPE type, char *arg) +{ + int ate = 0; + + switch (type) { + case HELP_OPT: + Usage(); + break; + case LONG_HELP_OPT: + LongUsage(); + break; + case BASE_OPT: + if (base) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-b"); + warningCount++; + PR_Free(base); + base = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-b"); + errorCount++; + goto loser; + } + base = PL_strdup(arg); + ate = 1; + break; + case COMPRESSION_OPT: + if (compression_level_specified) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-c"); + warningCount++; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-c"); + errorCount++; + goto loser; + } + compression_level = atoi(arg); + compression_level_specified = PR_TRUE; + ate = 1; + break; + case CERT_DIR_OPT: + if (cert_dir) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-d"); + warningCount++; + PR_Free(cert_dir); + cert_dir = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-d"); + errorCount++; + goto loser; + } + cert_dir = PL_strdup(arg); + ate = 1; + break; + case EXTENSION_OPT: + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "extension (-e)"); + errorCount++; + goto loser; + } + PL_HashTableAdd(extensions, arg, arg); + extensionsGiven = PR_TRUE; + ate = 1; + break; + case INSTALL_SCRIPT_OPT: + if (install_script) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "installScript (-i)"); + warningCount++; + PR_Free(install_script); + install_script = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "installScript (-i)"); + errorCount++; + goto loser; + } + install_script = PL_strdup(arg); + ate = 1; + break; + case SCRIPTDIR_OPT: + if (scriptdir) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "javascriptdir (-j)"); + warningCount++; + PR_Free(scriptdir); + scriptdir = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "javascriptdir (-j)"); + errorCount++; + goto loser; + } + scriptdir = PL_strdup(arg); + ate = 1; + break; + case CERTNAME_OPT: + if (keyName) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "keyName (-k)"); + warningCount++; + PR_Free(keyName); + keyName = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "keyName (-k)"); + errorCount++; + goto loser; + } + keyName = PL_strdup(arg); + ate = 1; + break; + case LIST_OBJSIGN_CERTS_OPT: + case LIST_ALL_CERTS_OPT: + if (list_certs != 0) { + PR_fprintf(errorFD, + "warning: only one of -l and -L may be specified.\n"); + warningCount++; + } + list_certs = (type == LIST_OBJSIGN_CERTS_OPT ? 1 : 2); + break; + case METAFILE_OPT: + if (metafile) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "metafile (-m)"); + warningCount++; + PR_Free(metafile); + metafile = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "metafile (-m)"); + errorCount++; + goto loser; + } + metafile = PL_strdup(arg); + ate = 1; + break; + case OPTIMIZE_OPT: + optimize = 1; + break; + case ENABLE_OCSP_OPT: + enableOCSP = 1; + break; + case PASSWORD_OPT: + if (pwdata.data) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "password (-p)"); + warningCount++; + PR_Free(pwdata.data); + pwdata.data = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "password (-p)"); + errorCount++; + goto loser; + } + pwdata.source = PW_PLAINTEXT; + pwdata.data = PL_strdup(arg); + ate = 1; + break; + case VERIFY_OPT: + if (verify) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "verify (-v)"); + warningCount++; + PR_Free(verify); + verify = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "verify (-v)"); + errorCount++; + goto loser; + } + verify = PL_strdup(arg); + ate = 1; + break; + case WHO_OPT: + if (tell_who) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "who (-v)"); + warningCount++; + PR_Free(tell_who); + tell_who = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "who (-w)"); + errorCount++; + goto loser; + } + tell_who = PL_strdup(arg); + ate = 1; + break; + case EXCLUDE_OPT: + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "exclude (-x)"); + errorCount++; + goto loser; + } + PL_HashTableAdd(excludeDirs, arg, arg); + exclusionsGiven = PR_TRUE; + ate = 1; + break; + case NO_TIME_OPT: + no_time = 1; + break; + case JAVASCRIPT_OPT: + javascript++; + break; + case ZIPFILE_OPT: + if (zipfile) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "jarfile (-Z)"); + warningCount++; + PR_Free(zipfile); + zipfile = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "jarfile (-Z)"); + errorCount++; + goto loser; + } + zipfile = PL_strdup(arg); + ate = 1; + break; + case GENKEY_OPT: + if (genkey) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "generate (-G)"); + warningCount++; + PR_Free(genkey); + genkey = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "generate (-G)"); + errorCount++; + goto loser; + } + genkey = PL_strdup(arg); + ate = 1; + break; + case MODULES_OPT: + list_modules++; + break; + case SIGNDIR_OPT: + if (jartree) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "signdir"); + warningCount++; + PR_Free(jartree); + jartree = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "signdir"); + errorCount++; + goto loser; + } + jartree = PL_strdup(arg); + ate = 1; + break; + case OUTFILE_OPT: + if (outfile) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "outfile"); + warningCount++; + PR_Free(outfile); + outfile = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "outfile"); + errorCount++; + goto loser; + } + outfile = PL_strdup(arg); + ate = 1; + break; + case COMMAND_FILE_OPT: + if (cmdFile) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], + "-f"); + warningCount++; + PR_Free(cmdFile); + cmdFile = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "-f"); + errorCount++; + goto loser; + } + cmdFile = PL_strdup(arg); + ate = 1; + break; + case NORECURSE_OPT: + noRecurse = PR_TRUE; + break; + case LEAVE_ARC_OPT: + leaveArc = PR_TRUE; + break; + case VERBOSITY_OPT: + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], + "--verbosity"); + errorCount++; + goto loser; + } + verbosity = atoi(arg); + ate = 1; + break; + case KEYSIZE_OPT: + if (keySize != -1) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-s"); + warningCount++; + } + keySize = atoi(arg); + ate = 1; + if (keySize < 1 || keySize > MAX_RSA_KEY_SIZE) { + PR_fprintf(errorFD, "Invalid key size: %d.\n", keySize); + errorCount++; + goto loser; + } + break; + case TOKEN_OPT: + if (token) { + PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-t"); + PR_Free(token); + token = NULL; + } + if (!arg) { + PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-t"); + errorCount++; + goto loser; + } + token = PL_strdup(arg); + ate = 1; + break; + case XPI_ARC_OPT: + xpi_arc = 1; + break; + default: + PR_fprintf(errorFD, "warning: unknown option\n"); + warningCount++; + break; + } + + return ate; +loser: + return -1; +} + +/********************************************************************* + * + * m a i n + */ +int +main(int argc, char *argv[]) +{ + PRBool readOnly; + int retval = 0; + + outputFD = PR_STDOUT; + errorFD = PR_STDERR; + + progName = argv[0]; + + if (argc < 2) { + Usage(); + } + + excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, + PL_CompareStrings, NULL, NULL); + extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, + PL_CompareStrings, NULL, NULL); + + if (parse_args(argc, argv)) { + retval = -1; + goto cleanup; + } + + /* Parse the command file if one was given */ + if (cmdFile) { + if (ProcessCommandFile()) { + retval = -1; + goto cleanup; + } + } + + /* Set up output redirection */ + if (outfile) { + if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) { + /* delete the file if it is already present */ + PR_fprintf(errorFD, + "warning: %s already exists and will be overwritten.\n", + outfile); + warningCount++; + if (PR_Delete(outfile) != PR_SUCCESS) { + PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile); + errorCount++; + exit(ERRX); + } + } + outputFD = PR_Open(outfile, + PR_WRONLY | + PR_CREATE_FILE | PR_TRUNCATE, + 0777); + if (!outputFD) { + PR_fprintf(errorFD, "ERROR: Unable to create %s.\n", + outfile); + errorCount++; + exit(ERRX); + } + errorFD = outputFD; + } + + /* This seems to be a fairly common user error */ + + if (verify && list_certs > 0) { + PR_fprintf(errorFD, "%s: Can't use -l and -v at the same time\n", + PROGRAM_NAME); + errorCount++; + retval = -1; + goto cleanup; + } + + /* -J assumes -Z now */ + + if (javascript && zipfile) { + PR_fprintf(errorFD, "%s: Can't use -J and -Z at the same time\n", + PROGRAM_NAME); + PR_fprintf(errorFD, "%s: -J option will create the jar files for you\n", + PROGRAM_NAME); + errorCount++; + retval = -1; + goto cleanup; + } + + /* -X needs -Z */ + + if (xpi_arc && !zipfile) { + PR_fprintf(errorFD, "%s: option XPI (-X) requires option jarfile (-Z)\n", + PROGRAM_NAME); + errorCount++; + retval = -1; + goto cleanup; + } + + /* Less common mixing of -L with various options */ + + if (list_certs > 0 && + (tell_who || zipfile || javascript || + scriptdir || extensionsGiven || exclusionsGiven || install_script)) { + PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n", + PROGRAM_NAME); + errorCount++; + retval = -1; + goto cleanup; + } + + if (!cert_dir) + cert_dir = get_default_cert_dir(); + + VerifyCertDir(cert_dir, keyName); + + if (compression_level < MIN_COMPRESSION_LEVEL || + compression_level > MAX_COMPRESSION_LEVEL) { + PR_fprintf(errorFD, "Compression level must be between %d and %d.\n", + MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL); + errorCount++; + retval = -1; + goto cleanup; + } + + if (jartree && !keyName) { + PR_fprintf(errorFD, "You must specify a key with which to sign.\n"); + errorCount++; + retval = -1; + goto cleanup; + } + + readOnly = (genkey == NULL); /* only key generation requires write */ + if (InitCrypto(cert_dir, readOnly)) { + PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n"); + errorCount++; + retval = -1; + goto cleanup; + } + + if (enableOCSP) { + SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB()); + if (rv != SECSuccess) { + PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n"); + errorCount++; + retval = -1; + } + } + + if (verify) { + if (VerifyJar(verify)) { + errorCount++; + retval = -1; + goto cleanup; + } + } else if (list_certs) { + if (ListCerts(keyName, list_certs)) { + errorCount++; + retval = -1; + goto cleanup; + } + } else if (list_modules) { + JarListModules(); + } else if (genkey) { + if (GenerateCert(genkey, keySize, token)) { + errorCount++; + retval = -1; + goto cleanup; + } + } else if (tell_who) { + if (JarWho(tell_who)) { + errorCount++; + retval = -1; + goto cleanup; + } + } else if (javascript && jartree) { + /* make sure directory exists */ + PRDir *dir; + dir = PR_OpenDir(jartree); + if (!dir) { + PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n", + jartree); + errorCount++; + retval = -1; + goto cleanup; + } else { + PR_CloseDir(dir); + } + + /* undo junk from prior runs of signtool*/ + if (RemoveAllArc(jartree)) { + PR_fprintf(errorFD, "Error removing archive directories under %s\n", + jartree); + errorCount++; + retval = -1; + goto cleanup; + } + + /* traverse all the htm|html files in the directory */ + if (InlineJavaScript(jartree, !noRecurse)) { + retval = -1; + goto cleanup; + } + + /* sign any resultant .arc directories created in above step */ + if (SignAllArc(jartree, keyName, javascript, metafile, install_script, + optimize, !noRecurse)) { + retval = -1; + goto cleanup; + } + + if (!leaveArc) { + RemoveAllArc(jartree); + } + + if (errorCount > 0 || warningCount > 0) { + PR_fprintf(outputFD, "%d error%s, %d warning%s.\n", + errorCount, + errorCount == 1 ? "" : "s", warningCount, warningCount == 1 ? "" : "s"); + } else { + PR_fprintf(outputFD, "Directory %s signed successfully.\n", + jartree); + } + } else if (jartree) { + SignArchive(jartree, keyName, zipfile, javascript, metafile, + install_script, optimize, !noRecurse); + } else + Usage(); + +cleanup: + if (extensions) { + PL_HashTableDestroy(extensions); + extensions = NULL; + } + if (excludeDirs) { + PL_HashTableDestroy(excludeDirs); + excludeDirs = NULL; + } + if (outputFD != PR_STDOUT) { + PR_Close(outputFD); + } + rm_dash_r(TMP_OUTPUT); + if (retval == 0) { + if (NSS_Shutdown() != SECSuccess) { + exit(1); + } + } + return retval; +} |