summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd/signtool/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/cmd/signtool/util.c')
-rw-r--r--security/nss/cmd/signtool/util.c1086
1 files changed, 1086 insertions, 0 deletions
diff --git a/security/nss/cmd/signtool/util.c b/security/nss/cmd/signtool/util.c
new file mode 100644
index 000000000..49b7f3b05
--- /dev/null
+++ b/security/nss/cmd/signtool/util.c
@@ -0,0 +1,1086 @@
+/* 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/. */
+
+#include "signtool.h"
+#include "prio.h"
+#include "prmem.h"
+#include "prenv.h"
+#include "nss.h"
+
+static int is_dir(char *filename);
+
+/***********************************************************
+ * Nasty hackish function definitions
+ */
+
+long *mozilla_event_queue = 0;
+
+#ifndef XP_WIN
+char *
+XP_GetString(int i)
+{
+ /* nasty hackish cast to avoid changing the signature of
+ * JAR_init_callbacks() */
+ return (char *)SECU_Strerror(i);
+}
+#endif
+
+void
+FE_SetPasswordEnabled()
+{
+}
+
+void /*MWContext*/ *
+FE_GetInitContext(void)
+{
+ return 0;
+}
+
+void /*MWContext*/ *
+XP_FindSomeContext()
+{
+ /* No windows context in command tools */
+ return NULL;
+}
+
+void
+ET_moz_CallFunction()
+{
+}
+
+/*
+ * R e m o v e A l l A r c
+ *
+ * Remove .arc directories that are lingering
+ * from a previous run of signtool.
+ *
+ */
+int
+RemoveAllArc(char *tree)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ char *archive = NULL;
+ int retval = 0;
+
+ dir = PR_OpenDir(tree);
+ if (!dir)
+ return -1;
+
+ for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir,
+ 0)) {
+
+ if (entry->name[0] == '.') {
+ continue;
+ }
+
+ if (archive)
+ PR_Free(archive);
+ archive = PR_smprintf("%s/%s", tree, entry->name);
+
+ if (PL_strcaserstr(entry->name, ".arc") ==
+ (entry->name + strlen(entry->name) - 4)) {
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "removing: %s\n", archive);
+ }
+
+ if (rm_dash_r(archive)) {
+ PR_fprintf(errorFD, "Error removing %s\n", archive);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+ } else if (is_dir(archive)) {
+ if (RemoveAllArc(archive)) {
+ retval = -1;
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ PR_CloseDir(dir);
+ if (archive)
+ PR_Free(archive);
+
+ return retval;
+}
+
+/*
+ * r m _ d a s h _ r
+ *
+ * Remove a file, or a directory recursively.
+ *
+ */
+int
+rm_dash_r(char *path)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ PRFileInfo fileinfo;
+ char filename[FNSIZE];
+
+ if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
+ return -1;
+ }
+ if (fileinfo.type == PR_FILE_DIRECTORY) {
+
+ dir = PR_OpenDir(path);
+ if (!dir) {
+ PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Recursively delete all entries in the directory */
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ sprintf(filename, "%s/%s", path, entry->name);
+ if (rm_dash_r(filename))
+ return -1;
+ }
+
+ if (PR_CloseDir(dir) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Delete the directory itself */
+ if (PR_RmDir(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ } else {
+ if (PR_Delete(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * u s a g e
+ *
+ * Print some useful help information
+ *
+ */
+
+void
+Usage(void)
+{
+#define FPS PR_fprintf(outputFD,
+ FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
+ FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME);
+ FPS "\nUsage: %s -k keyName [-b basename] [-c Compression Level]\n"
+ "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n"
+ "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
+ "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n"
+ "\t\t [-p password] directory-tree\n", PROGRAM_NAME);
+ FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n"
+ "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n"
+ "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
+ "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n"
+ "\t\t directory-tree\n", PROGRAM_NAME);
+ FPS "\t%s -h \n", PROGRAM_NAME);
+ FPS "\t%s -H \n", PROGRAM_NAME);
+ FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME);
+ FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME);
+ FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n"
+ "\t\t [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -f filename\n" , PROGRAM_NAME);
+ exit(ERRX);
+}
+
+void
+LongUsage(void)
+{
+ FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
+ FPS "\n%-20s Signs the directory-tree\n",
+ "signtool directory-tree");
+ FPS "%-30s Nickname (key) of the certificate to sign with\n",
+ " -k keyname");
+ FPS "%-30s Base filename for the .rsa and.sf files in the\n",
+ " -b basename");
+ FPS "%-30s META-INF directory\n"," ");
+ FPS "%-30s Set the compression level. 0-9, 0=none\n",
+ " -c CompressionLevel");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+ FPS "%-30s Name of the installer script for SmartUpdate\n",
+ " -i installer script");
+ FPS "%-30s Name of a metadata control file\n",
+ " -m metafile");
+ FPS "%-30s For optimizing the archive for size.\n",
+ " -o");
+ FPS "%-30s Omit Optional Headers\n"," ");
+ FPS "%-30s Excludes the specified directory or file from\n",
+ " -x directory or file name");
+ FPS "%-30s signing\n"," ");
+ FPS "%-30s To not store the signing time in digital\n",
+ " -z directory or file name");
+ FPS "%-30s signature\n"," ");
+ FPS "%-30s Create XPI Compatible Archive. It requires -Z\n",
+ " -X directory or file name");
+ FPS "%-30s option\n"," ");
+ FPS "%-30s Sign only files with the given extension\n",
+ " -e");
+ FPS "%-30s Causes the specified directory to be signed and\n",
+ " -j");
+ FPS "%-30s tags its entries as inline JavaScript\n"," ");
+ FPS "%-30s Creates a JAR file with the specified name.\n",
+ " -Z");
+ FPS "%-30s -Z option cannot be used with -J option\n"," ");
+ FPS "%-30s Specifies a password for the private-key database\n",
+ " -p");
+ FPS "%-30s (insecure)\n"," ");
+ FPS "%-30s File to receive redirected output\n",
+ " --outfile filename");
+ FPS "%-30s Sets the quantity of information generated in\n",
+ " --verbosity value");
+ FPS "%-30s operation\n"," ");
+ FPS "%-30s Blocks recursion into subdirectories\n",
+ " --norecurse");
+ FPS "%-30s Retains the temporary .arc (archive) directories\n",
+ " --leavearc");
+ FPS "%-30s -J option creates\n"," ");
+
+ FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n",
+ "-J" );
+ FPS "%-20s creates as many archive files as are in the HTML tags.\n"," ");
+
+ FPS "%-20s The options are same as without any command option given\n"," ");
+ FPS "%-20s above. -Z and -J options are not allowed together\n"," ");
+
+ FPS "\n%-20s Generates a new private-public key pair and corresponding\n",
+ "-G nickname");
+ FPS "%-20s object-signing certificates with the given nickname\n"," ");
+ FPS "%-30s Specifies the size of the key for generated \n",
+ " --keysize|-s keysize");
+ FPS "%-30s certificate\n"," ");
+ FPS "%-30s Specifies which available token should generate\n",
+ " --token|-t token name ");
+ FPS "%-30s the key and receive the certificate\n"," ");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-20s Display signtool help\n",
+ "-h ");
+
+ FPS "\n%-20s Display signtool help(Detailed)\n",
+ "-H ");
+
+ FPS "\n%-20s Lists signing certificates, including issuing CAs\n",
+ "-l ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+ FPS "%-30s Specifies the nickname (key) of the certificate\n",
+ " -k keyname");
+
+ FPS "\n%-20s Lists the certificates in your database\n",
+ "-L ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+ FPS "%-30s Specifies the nickname (key) of the certificate\n",
+ " -k keyname");
+
+ FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n",
+ "-M ");
+
+ FPS "\n%-20s Displays the contents of an archive and verifies\n",
+ "-v archive");
+ FPS "%-20s cryptographic integrity\n"," ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-20s Displays the names of signers in the archive\n",
+ "-w archive");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-30s Common option to all the above.\n",
+ " -O");
+ FPS "%-30s Enable OCSP checking\n"," ");
+
+ FPS "\n%-20s Specifies a text file containing options and arguments in\n",
+ "-f command-file");
+ FPS "%-20s keyword=value format. Commands are taken from this file\n"," ");
+
+ FPS "\n\n\n");
+ FPS "Example:\n");
+ FPS "%-10s -d \"certificate directory\" -k \"certnickname\" \\",
+ PROGRAM_NAME);
+ FPS "\n%-10s -p \"password\" -X -Z \"file.xpi\" directory-tree\n"," " );
+ FPS "Common syntax to create an XPInstall compatible"
+ " signed archive\n\n"," ");
+ FPS "\nCommand File Keywords and Example:\n");
+ FPS "\nKeyword\t\tValue\n");
+ FPS "basename\tSame as -b option\n");
+ FPS "compression\tSame as -c option\n");
+ FPS "certdir\t\tSame as -d option\n");
+ FPS "extension\tSame as -e option\n");
+ FPS "generate\tSame as -G option\n");
+ FPS "installscript\tSame as -i option\n");
+ FPS "javascriptdir\tSame as -j option\n");
+ FPS "htmldir\t\tSame as -J option\n");
+ FPS "certname\tNickname of certificate, as with -k option\n");
+ FPS "signdir\t\tThe directory to be signed, as with -k option\n");
+ FPS "list\t\tSame as -l option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "listall\t\tSame as -L option. Value is ignored\n"
+ " \t\tbut = sign must be present\n");
+ FPS "metafile\tSame as -m option\n");
+ FPS "modules\t\tSame as -M option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "optimize\tSame as -o option. Value is ignored,\n"
+ " \tbut = sign must be present\n");
+ FPS "ocsp\t\tSame as -O option\n");
+ FPS "password\tSame as -p option\n");
+ FPS "verify\t\tSame as -v option\n");
+ FPS "who\t\tSame as -w option\n");
+ FPS "exclude\t\tSame as -x option\n");
+ FPS "notime\t\tSame as -z option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "jarfile\t\tSame as -Z option\n");
+ FPS "outfile\t\tSame as --outfile option. The argument\n");
+ FPS " \t\tis the name of a file to which output\n");
+ FPS " \t\tof a file and error messages will be \n");
+ FPS " \t\tredirected\n");
+ FPS "leavearc\tSame as --leavearc option\n");
+ FPS "verbosity\tSame as --verbosity option\n");
+ FPS "keysize\t\tSame as -s option\n");
+ FPS "token\t\tSame as -t option\n");
+ FPS "xpi\t\tSame as -X option\n");
+ FPS "\n\n");
+ FPS "Here's an example of the use of the command file. The command\n\n");
+ FPS " signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n"
+ " signdir > output.txt\n\n");
+ FPS "becomes\n\n");
+ FPS " signtool -f somefile\n\n");
+ FPS "where somefile contains the following lines:\n\n");
+ FPS " certdir=c:\\netscape\\users\\james\n"," ");
+ FPS " certname=mycert\n"," ");
+ FPS " jarfile=myjar.jar\n"," ");
+ FPS " signdir=signdir\n"," ");
+ FPS " outfile=output.txt\n"," ");
+ exit(ERRX);
+#undef FPS
+}
+
+/*
+ * p r i n t _ e r r o r
+ *
+ * For the undocumented -E function. If an older version
+ * of communicator gives you a numeric error, we can see what
+ * really happened without doing hex math.
+ *
+ */
+
+void
+print_error(int err)
+{
+ PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error(err));
+ errorCount++;
+ give_help(err);
+}
+
+/*
+ * o u t _ o f _ m e m o r y
+ *
+ * Out of memory, exit Signtool.
+ *
+ */
+void
+out_of_memory(void)
+{
+ PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+}
+
+/*
+ * V e r i f y C e r t D i r
+ *
+ * Validate that the specified directory
+ * contains a certificate database
+ *
+ */
+void
+VerifyCertDir(char *dir, char *keyName)
+{
+ char fn[FNSIZE];
+
+ /* don't try verifying if we don't have a local directory */
+ if (strncmp(dir, "multiaccess:", sizeof("multiaccess:") - 1) == 0) {
+ return;
+ }
+ /* this function is truly evil. Tools and applications should not have
+ * any knowledge of actual cert databases! */
+ return;
+
+ /* This code is really broken because it makes underlying assumptions about
+ * how the NSS profile directory is laid out, but these names can change
+ * from release to release. */
+ sprintf(fn, "%s/cert8.db", dir);
+
+ if (PR_Access(fn, PR_ACCESS_EXISTS)) {
+ PR_fprintf(errorFD, "%s: No certificate database in \"%s\"\n",
+ PROGRAM_NAME, dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
+ }
+
+ if (keyName == NULL)
+ return;
+
+ /* if the user gave the -k key argument, verify that
+ a key database already exists */
+
+ sprintf(fn, "%s/key3.db", dir);
+
+ if (PR_Access(fn, PR_ACCESS_EXISTS)) {
+ PR_fprintf(errorFD, "%s: No private key database in \"%s\"\n",
+ PROGRAM_NAME,
+ dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+}
+
+/*
+ * f o r e a c h
+ *
+ * A recursive function to loop through all names in
+ * the specified directory, as well as all subdirectories.
+ *
+ * FIX: Need to see if all platforms allow multiple
+ * opendir's to be called.
+ *
+ */
+
+int foreach (char *dirname, char *prefix,
+ int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
+ void *arg),
+ PRBool recurse, PRBool includeDirs, void *arg)
+{
+ char newdir[FNSIZE];
+ int retval = 0;
+
+ PRDir *dir;
+ PRDirEntry *entry;
+
+ strcpy(newdir, dirname);
+ if (*prefix) {
+ strcat(newdir, "/");
+ strcat(newdir, prefix);
+ }
+
+ dir = PR_OpenDir(newdir);
+ if (!dir)
+ return -1;
+
+ for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir, 0)) {
+ if (strcmp(entry->name, ".") == 0 ||
+ strcmp(entry->name, "..") == 0) {
+ /* no infinite recursion, please */
+ continue;
+ }
+
+ /* can't sign self */
+ if (!strcmp(entry->name, "META-INF"))
+ continue;
+
+ /* -x option */
+ if (PL_HashTableLookup(excludeDirs, entry->name))
+ continue;
+
+ strcpy(newdir, dirname);
+ if (*dirname)
+ strcat(newdir, "/");
+
+ if (*prefix) {
+ strcat(newdir, prefix);
+ strcat(newdir, "/");
+ }
+ strcat(newdir, entry->name);
+
+ if (!is_dir(newdir) || includeDirs) {
+ char newpath[FNSIZE];
+
+ strcpy(newpath, prefix);
+ if (*newpath)
+ strcat(newpath, "/");
+ strcat(newpath, entry->name);
+
+ if ((*fn)(newpath, dirname, prefix, (char *)entry->name,
+ arg)) {
+ retval = -1;
+ break;
+ }
+ }
+
+ if (is_dir(newdir)) {
+ if (recurse) {
+ char newprefix[FNSIZE];
+
+ strcpy(newprefix, prefix);
+ if (*newprefix) {
+ strcat(newprefix, "/");
+ }
+ strcat(newprefix, entry->name);
+
+ if (foreach (dirname, newprefix, fn, recurse,
+ includeDirs, arg)) {
+ retval = -1;
+ break;
+ }
+ }
+ }
+ }
+
+ PR_CloseDir(dir);
+
+ return retval;
+}
+
+/*
+ * i s _ d i r
+ *
+ * Return 1 if file is a directory.
+ * Wonder if this runs on a mac, trust not.
+ *
+ */
+static int
+is_dir(char *filename)
+{
+ PRFileInfo finfo;
+
+ if (PR_GetFileInfo(filename, &finfo) != PR_SUCCESS) {
+ printf("Unable to get information about %s\n", filename);
+ return 0;
+ }
+
+ return (finfo.type == PR_FILE_DIRECTORY);
+}
+
+/***************************************************************
+ *
+ * s e c E r r o r S t r i n g
+ *
+ * Returns an error string corresponding to the given error code.
+ * Doesn't cover all errors; returns a default for many.
+ * Returned string is only valid until the next call of this function.
+ */
+const char *
+secErrorString(long code)
+{
+ static char errstring[80]; /* dynamically constructed error string */
+ char *c; /* the returned string */
+
+ switch (code) {
+ case SEC_ERROR_IO:
+ c = "io error";
+ break;
+ case SEC_ERROR_LIBRARY_FAILURE:
+ c = "security library failure";
+ break;
+ case SEC_ERROR_BAD_DATA:
+ c = "bad data";
+ break;
+ case SEC_ERROR_OUTPUT_LEN:
+ c = "output length";
+ break;
+ case SEC_ERROR_INPUT_LEN:
+ c = "input length";
+ break;
+ case SEC_ERROR_INVALID_ARGS:
+ c = "invalid args";
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ c = "expired certificate";
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ c = "revoked certificate";
+ break;
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ c = "inadequate key usage";
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ c = "inadequate certificate type";
+ break;
+ case SEC_ERROR_UNTRUSTED_CERT:
+ c = "untrusted cert";
+ break;
+ case SEC_ERROR_NO_KRL:
+ c = "no key revocation list";
+ break;
+ case SEC_ERROR_KRL_BAD_SIGNATURE:
+ c = "key revocation list: bad signature";
+ break;
+ case SEC_ERROR_KRL_EXPIRED:
+ c = "key revocation list expired";
+ break;
+ case SEC_ERROR_REVOKED_KEY:
+ c = "revoked key";
+ break;
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ c = "certificate revocation list: bad signature";
+ break;
+ case SEC_ERROR_CRL_EXPIRED:
+ c = "certificate revocation list expired";
+ break;
+ case SEC_ERROR_CRL_NOT_YET_VALID:
+ c = "certificate revocation list not yet valid";
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ c = "unknown issuer";
+ break;
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ c = "expired issuer certificate";
+ break;
+ case SEC_ERROR_BAD_SIGNATURE:
+ c = "bad signature";
+ break;
+ case SEC_ERROR_BAD_KEY:
+ c = "bad key";
+ break;
+ case SEC_ERROR_NOT_FORTEZZA_ISSUER:
+ c = "not fortezza issuer";
+ break;
+ case SEC_ERROR_CA_CERT_INVALID:
+ c = "Certificate Authority certificate invalid";
+ break;
+ case SEC_ERROR_EXTENSION_NOT_FOUND:
+ c = "extension not found";
+ break;
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
+ c = "certificate not in name space";
+ break;
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ c = "untrusted issuer";
+ break;
+ default:
+ sprintf(errstring, "security error %ld", code);
+ c = errstring;
+ break;
+ }
+
+ return c;
+}
+
+/***************************************************************
+ *
+ * d i s p l a y V e r i f y L o g
+ *
+ * Prints the log of a cert verification.
+ */
+void
+displayVerifyLog(CERTVerifyLog *log)
+{
+ CERTVerifyLogNode *node;
+ CERTCertificate *cert;
+ char *name;
+
+ if (!log || (log->count <= 0)) {
+ return;
+ }
+
+ for (node = log->head; node != NULL; node = node->next) {
+
+ if (!(cert = node->cert)) {
+ continue;
+ }
+
+ /* Get a name for this cert */
+ if (cert->nickname != NULL) {
+ name = cert->nickname;
+ } else if (cert->emailAddr && cert->emailAddr[0]) {
+ name = cert->emailAddr;
+ } else {
+ name = cert->subjectName;
+ }
+
+ printf("%s%s:\n", name,
+ (node->depth > 0) ? " [Certificate Authority]" : "");
+
+ printf("\t%s\n", secErrorString(node->error));
+ }
+}
+
+/*
+ * J a r L i s t M o d u l e s
+ *
+ * Print a list of the PKCS11 modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+void
+JarListModules(void)
+{
+ int i;
+ int count = 0;
+
+ SECMODModuleList *modules = NULL;
+ static SECMODListLock *moduleLock = NULL;
+
+ SECMODModuleList *mlp;
+
+ if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) {
+ /* this is the wrong text */
+ PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ SECMOD_GetReadLock(moduleLock);
+
+ modules = SECMOD_GetDefaultModuleList();
+
+ if (modules == NULL) {
+ SECMOD_ReleaseReadLock(moduleLock);
+ PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ for (mlp = modules; mlp != NULL; mlp = mlp->next) {
+ count++;
+ PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
+
+ if (mlp->module->internal)
+ PR_fprintf(outputFD, " (this module is internally loaded)\n");
+ else
+ PR_fprintf(outputFD, " (this is an external module)\n");
+
+ if (mlp->module->dllName)
+ PR_fprintf(outputFD, " DLL name: %s\n",
+ mlp->module->dllName);
+
+ if (mlp->module->slotCount == 0)
+ PR_fprintf(outputFD, " slots: There are no slots attached to this module\n");
+ else
+ PR_fprintf(outputFD, " slots: %d slots attached\n",
+ mlp->module->slotCount);
+
+ if (mlp->module->loaded == 0)
+ PR_fprintf(outputFD, " status: Not loaded\n");
+ else
+ PR_fprintf(outputFD, " status: loaded\n");
+
+ for (i = 0; i < mlp->module->slotCount; i++) {
+ PK11SlotInfo *slot = mlp->module->slots[i];
+
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, " slot: %s\n", PK11_GetSlotName(slot));
+ PR_fprintf(outputFD, " token: %s\n", PK11_GetTokenName(slot));
+ }
+ }
+
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ if (count == 0)
+ PR_fprintf(outputFD,
+ "Warning: no modules were found (should have at least one)\n");
+
+ SECMOD_ReleaseReadLock(moduleLock);
+}
+
+/**********************************************************************
+ * c h o p
+ *
+ * Eliminates leading and trailing whitespace. Returns a pointer to the
+ * beginning of non-whitespace, or an empty string if it's all whitespace.
+ */
+char *
+chop(char *str)
+{
+ char *start, *end;
+
+ if (str) {
+ start = str;
+
+ /* Nip leading whitespace */
+ while (isspace(*start)) {
+ start++;
+ }
+
+ /* Nip trailing whitespace */
+ if (*start) {
+ end = start + strlen(start) - 1;
+ while (isspace(*end) && end > start) {
+ end--;
+ }
+ *(end + 1) = '\0';
+ }
+
+ return start;
+ } else {
+ return NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * F a t a l E r r o r
+ *
+ * Outputs an error message and bails out of the program.
+ */
+void
+FatalError(char *msg)
+{
+ if (!msg)
+ msg = "";
+
+ PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
+ errorCount++;
+ exit(ERRX);
+}
+
+/*************************************************************************
+ *
+ * I n i t C r y p t o
+ */
+int
+InitCrypto(char *cert_dir, PRBool readOnly)
+{
+ SECStatus rv;
+ static int prior = 0;
+ PK11SlotInfo *slotinfo;
+
+ if (prior == 0) {
+ /* some functions such as OpenKeyDB expect this path to be
+ * implicitly set prior to calling */
+ if (readOnly) {
+ rv = NSS_Init(cert_dir);
+ } else {
+ rv = NSS_InitReadWrite(cert_dir);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(PROGRAM_NAME);
+ exit(-1);
+ }
+
+ SECU_ConfigDirectory(cert_dir);
+
+ /* Been there done that */
+ prior++;
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Must login to FIPS before you do anything else */
+ if (PK11_IsFIPS()) {
+ slotinfo = PK11_GetInternalSlot();
+ if (!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
+ "\n",
+ PROGRAM_NAME);
+ return -1;
+ }
+ if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ &pwdata) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ /* Make sure there is a password set on the internal key slot */
+ slotinfo = PK11_GetInternalKeySlot();
+ if (!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
+ "\n",
+ PROGRAM_NAME);
+ return -1;
+ }
+ if (PK11_NeedUserInit(slotinfo)) {
+ PR_fprintf(errorFD,
+ "\nWARNING: No password set on internal key database. Most operations will fail."
+ "\nYou must create a password.\n");
+ warningCount++;
+ }
+
+ /* Make sure we can authenticate to the key slot in FIPS mode */
+ if (PK11_IsFIPS()) {
+ if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ &pwdata) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ return 0;
+}
+
+/* Windows foolishness is now in the secutil lib */
+
+/*****************************************************************
+ * g e t _ d e f a u l t _ c e r t _ d i r
+ *
+ * Attempt to locate a certificate directory.
+ * Failing that, complain that the user needs to
+ * use the -d(irectory) parameter.
+ *
+ */
+char *
+get_default_cert_dir(void)
+{
+ char *home;
+
+ char *cd = NULL;
+ static char db[FNSIZE];
+
+#ifdef XP_UNIX
+ home = PR_GetEnvSecure("HOME");
+
+ if (home && *home) {
+ sprintf(db, "%s/.netscape", home);
+ cd = db;
+ }
+#endif
+
+#ifdef XP_PC
+ FILE *fp;
+
+ /* first check the environment override */
+
+ home = PR_GetEnvSecure("JAR_HOME");
+
+ if (home && *home) {
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+ /* try the old navigator directory */
+
+ if (cd == NULL) {
+ home = "c:/Program Files/Netscape/Navigator";
+
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+ /* Try the current directory, I wonder if this
+ is really a good idea. Remember, Windows only.. */
+
+ if (cd == NULL) {
+ home = ".";
+
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+#endif
+
+ if (!cd) {
+ PR_fprintf(errorFD,
+ "You must specify the location of your certificate directory\n");
+ PR_fprintf(errorFD,
+ "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
+ errorCount++;
+ exit(ERRX);
+ }
+
+ return cd;
+}
+
+/************************************************************************
+ * g i v e _ h e l p
+ */
+void
+give_help(int status)
+{
+ if (status == SEC_ERROR_UNKNOWN_ISSUER) {
+ PR_fprintf(errorFD,
+ "The Certificate Authority (CA) for this certificate\n");
+ PR_fprintf(errorFD,
+ "does not appear to be in your database. You should contact\n");
+ PR_fprintf(errorFD,
+ "the organization which issued this certificate to obtain\n");
+ PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
+ }
+}
+
+/**************************************************************************
+ *
+ * p r _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+char *
+pr_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i = 0;
+ while (i < size - 1) {
+ status = PR_Read(file, &c, 1);
+ if (status == -1) {
+ return NULL;
+ } else if (status == 0) {
+ if (i == 0) {
+ return NULL;
+ }
+ break;
+ }
+ buf[i++] = c;
+ if (c == '\n') {
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return buf;
+}