summaryrefslogtreecommitdiff
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.c1012
1 files changed, 1012 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..76d1487f0
--- /dev/null
+++ b/security/nss/cmd/signtool/util.c
@@ -0,0 +1,1012 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include "cdbhdl.h"
+#include "prio.h"
+#include "prmem.h"
+
+static int is_dir (char *filename);
+static char *certDBNameCallback(void *arg, int dbVersion);
+
+/***********************************************************************
+ *
+ * O p e n C e r t D B
+ */
+CERTCertDBHandle *
+OpenCertDB(PRBool readOnly)
+{
+ CERTCertDBHandle *db;
+ SECStatus rv;
+
+ /* Allocate a handle to fill with CERT_OpenCertDB below */
+ db = (CERTCertDBHandle *) PORT_ZAlloc (sizeof(CERTCertDBHandle));
+ if (db == NULL)
+ {
+ SECU_PrintError(progName, "unable to get database handle");
+ return NULL;
+ }
+
+ rv = CERT_OpenCertDB (db, readOnly, certDBNameCallback, NULL);
+
+ if (rv)
+ {
+ SECU_PrintError(progName, "could not open certificate database");
+ if (db) PORT_Free (db);
+ return NULL;
+ }
+ else
+ {
+ CERT_SetDefaultCertDB(db);
+ }
+
+ return db;
+}
+
+/***********************************************************
+ * Nasty hackish function definitions
+ */
+
+long *mozilla_event_queue = 0;
+
+#ifndef XP_WIN
+char *XP_GetString (int i)
+{
+ return SECU_ErrorStringRaw ((int16) 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)
+{
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s %s - a signing tool for jar files\n", LONG_PROGRAM_NAME, VERSION);
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "Usage: %s [options] directory-tree \n\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " -b\"basename\"\t\tbasename of .sf, .rsa files for signing\n");
+ PR_fprintf(outputFD, " -c#\t\t\t\tCompression level, 0-9, 0=none\n");
+ PR_fprintf(outputFD, " -d\"certificate directory\"\tcontains cert*.db and key*.db\n");
+ PR_fprintf(outputFD, " -e\".ext\"\t\t\tsign only files with this extension\n");
+ PR_fprintf(outputFD, " -f\"filename\"\t\t\tread commands from file\n");
+ PR_fprintf(outputFD, " -G\"nickname\"\t\tcreate object-signing cert with this nickname\n");
+ PR_fprintf(outputFD, " -i\"installer script\"\tassign installer javascript\n");
+ PR_fprintf(outputFD, " -j\"javascript directory\"\tsign javascript files in this subtree\n");
+ PR_fprintf(outputFD, " -J\t\t\t\tdirectory contains HTML files. Javascript will\n"
+ "\t\t\t\tbe extracted and signed.\n");
+ PR_fprintf(outputFD, " -k\"cert nickname\"\t\tsign with this certificate\n");
+ PR_fprintf(outputFD, " --leavearc\t\t\tdo not delete .arc directories created\n"
+ "\t\t\t\tby -J option\n");
+ PR_fprintf(outputFD, " -m\"metafile\"\t\tinclude custom meta-information\n");
+ PR_fprintf(outputFD, " --norecurse\t\t\tdo not operate on subdirectories\n");
+ PR_fprintf(outputFD, " -o\t\t\t\toptimize - omit optional headers\n");
+ PR_fprintf(outputFD, " --outfile \"filename\"\tredirect output to file\n");
+ PR_fprintf(outputFD, " -p\"password\"\t\tfor password on command line (insecure)\n");
+ PR_fprintf(outputFD, " -s keysize\t\t\tkeysize in bits of generated cert\n");
+ PR_fprintf(outputFD, " -t token\t\t\tname of token on which to generate cert\n");
+ PR_fprintf(outputFD, " --verbosity #\t\tSet amount of debugging information to generate.\n"
+ "\t\t\t\tLower number means less output, 0 is default.\n");
+ PR_fprintf(outputFD, " -x\"name\"\t\t\tdirectory or filename to exclude\n");
+ PR_fprintf(outputFD, " -z\t\t\t\tomit signing time from signature\n");
+ PR_fprintf(outputFD, " -Z\"jarfile\"\t\t\tcreate JAR file with the given name.\n"
+ "\t\t\t\t(Default compression level is 6.)\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -l\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists the signing certificates in your database\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -L\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists all certificates in your database, marks object-signing certificates\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -M\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists the PKCS #11 modules available to %s\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -v file.jar\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " show the contents of the specified jar file\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -w file.jar\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " if valid, tries to tell you who signed the jar file\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "For more details, visit\n");
+ PR_fprintf(outputFD,
+" http://developer.netscape.com/library/documentation/signedobj/signtool/\n");
+
+ exit (0);
+}
+
+/*
+ * 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];
+
+ sprintf (fn, "%s/cert7.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 (*entry->name == '.' || *entry->name == '#')
+ 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 );
+}
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -p(password) argument
+ * of the command line. This is only to be used for build & testing purposes,
+ * as it's extraordinarily insecure.
+ *
+ * After use once, null it out otherwise PKCS11 calls us forever.
+ *
+ */
+SECItem *
+password_hardcode(void *arg, SECKEYKeyDBHandle *handle)
+{
+ SECItem *pw = NULL;
+ if (password) {
+ pw = SECITEM_AllocItem(NULL, NULL, PL_strlen(password));
+ pw->data = PL_strdup(password);
+ password = NULL;
+ }
+ return pw;
+}
+
+char *
+pk11_password_hardcode(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *pw;
+ pw = password ? PORT_Strdup (password) : NULL;
+ password = NULL;
+ return pw;
+}
+
+/************************************************************************
+ *
+ * c e r t D B N a m e C a l l b a c k
+ */
+static char *
+certDBNameCallback(void *arg, int dbVersion)
+{
+ char *fnarg;
+ char *dir;
+ char *filename;
+
+ dir = SECU_ConfigDirectory (NULL);
+
+ switch ( dbVersion ) {
+ case 7:
+ fnarg = "7";
+ break;
+ case 6:
+ fnarg = "6";
+ break;
+ case 5:
+ fnarg = "5";
+ break;
+ case 4:
+ default:
+ fnarg = "";
+ break;
+ }
+ filename = PR_smprintf("%s/cert%s.db", dir, fnarg);
+ return(filename);
+}
+
+/***************************************************************
+ *
+ * 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 != NULL) {
+ 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;
+
+ modules = SECMOD_GetDefaultModuleList();
+
+ if (modules == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if ((moduleLock = SECMOD_NewListLock()) == 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);
+
+ 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(strlen(start) > 0) {
+ 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;
+
+ CERTCertDBHandle *db;
+
+ if (prior == 0) {
+ /* some functions such as OpenKeyDB expect this path to be
+ * implicitly set prior to calling */
+ SECU_ConfigDirectory (cert_dir);
+
+ if ((rv = SECU_PKCS11Init(readOnly)) != SECSuccess) {
+ PR_fprintf(errorFD, "%s: Unable to initialize PKCS11, code %d\n",
+ PROGRAM_NAME, rv);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ SEC_Init();
+
+
+ /* Been there done that */
+ prior++;
+
+
+ /* open cert database and set the default certificate DB */
+ db = OpenCertDB(readOnly);
+
+ if (db == NULL) return -1;
+
+ CERT_SetDefaultCertDB (db);
+
+ if(password) {
+ PK11_SetPasswordFunc(pk11_password_hardcode);
+ }
+
+ /* 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*/,
+ NULL /*wincx*/) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ return -1;
+ }
+ }
+
+ /* 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 use Communicator to 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*/,
+ NULL /*wincx*/) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ return -1;
+ }
+ }
+ }
+
+ 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 = getenv ("HOME");
+
+ if (home && *home)
+ {
+ sprintf (db, "%s/.netscape", home);
+ cd = db;
+ }
+#endif
+
+#ifdef XP_PC
+ FILE *fp;
+
+ /* first check the environment override */
+
+ home = getenv ("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, (void*) &c, 1);
+ if(status==-1) {
+ return NULL;
+ } else if(status==0) {
+ break;
+ }
+ buf[i++] = c;
+ if(c=='\n') {
+ break;
+ }
+ }
+ buf[i]='\0';
+
+ return buf;
+}
+