mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-11 10:20:19 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
1102 lines
27 KiB
C
1102 lines
27 KiB
C
/* 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 "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 = 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, &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;
|
|
}
|
|
|
|
|