mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 03:30:17 +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
974 lines
26 KiB
C
974 lines
26 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/. */
|
|
|
|
/* To edit this file, set TABSTOPS to 4 spaces.
|
|
* This is not the normal NSS convention.
|
|
*/
|
|
|
|
#include "modutil.h"
|
|
#include "install.h"
|
|
#include <plstr.h>
|
|
#include "certdb.h" /* for CERT_DB_FILE_VERSION */
|
|
#include "nss.h"
|
|
|
|
static void install_error(char *message);
|
|
static char* PR_fgets(char *buf, int size, PRFileDesc *file);
|
|
static char *progName;
|
|
|
|
|
|
/* This enum must be kept in sync with the commandNames list */
|
|
typedef enum {
|
|
NO_COMMAND,
|
|
ADD_COMMAND,
|
|
CHANGEPW_COMMAND,
|
|
CREATE_COMMAND,
|
|
DEFAULT_COMMAND,
|
|
DELETE_COMMAND,
|
|
DISABLE_COMMAND,
|
|
ENABLE_COMMAND,
|
|
FIPS_COMMAND,
|
|
JAR_COMMAND,
|
|
LIST_COMMAND,
|
|
RAW_LIST_COMMAND,
|
|
RAW_ADD_COMMAND,
|
|
CHKFIPS_COMMAND,
|
|
UNDEFAULT_COMMAND
|
|
} Command;
|
|
|
|
/* This list must be kept in sync with the Command enum */
|
|
static char *commandNames[] = {
|
|
"(no command)",
|
|
"-add",
|
|
"-changepw",
|
|
"-create",
|
|
"-default",
|
|
"-delete",
|
|
"-disable",
|
|
"-enable",
|
|
"-fips",
|
|
"-jar",
|
|
"-list",
|
|
"-rawlist",
|
|
"-rawadd",
|
|
"-chkfips",
|
|
"-undefault"
|
|
};
|
|
|
|
|
|
/* this enum must be kept in sync with the optionStrings list */
|
|
typedef enum {
|
|
ADD_ARG=0,
|
|
RAW_ADD_ARG,
|
|
CHANGEPW_ARG,
|
|
CIPHERS_ARG,
|
|
CREATE_ARG,
|
|
DBDIR_ARG,
|
|
DBPREFIX_ARG,
|
|
DEFAULT_ARG,
|
|
DELETE_ARG,
|
|
DISABLE_ARG,
|
|
ENABLE_ARG,
|
|
FIPS_ARG,
|
|
FORCE_ARG,
|
|
JAR_ARG,
|
|
LIBFILE_ARG,
|
|
LIST_ARG,
|
|
RAW_LIST_ARG,
|
|
MECHANISMS_ARG,
|
|
NEWPWFILE_ARG,
|
|
PWFILE_ARG,
|
|
SLOT_ARG,
|
|
UNDEFAULT_ARG,
|
|
INSTALLDIR_ARG,
|
|
TEMPDIR_ARG,
|
|
SECMOD_ARG,
|
|
NOCERTDB_ARG,
|
|
STRING_ARG,
|
|
CHKFIPS_ARG,
|
|
|
|
NUM_ARGS /* must be last */
|
|
} Arg;
|
|
|
|
/* This list must be kept in sync with the Arg enum */
|
|
static char *optionStrings[] = {
|
|
"-add",
|
|
"-rawadd",
|
|
"-changepw",
|
|
"-ciphers",
|
|
"-create",
|
|
"-dbdir",
|
|
"-dbprefix",
|
|
"-default",
|
|
"-delete",
|
|
"-disable",
|
|
"-enable",
|
|
"-fips",
|
|
"-force",
|
|
"-jar",
|
|
"-libfile",
|
|
"-list",
|
|
"-rawlist",
|
|
"-mechanisms",
|
|
"-newpwfile",
|
|
"-pwfile",
|
|
"-slot",
|
|
"-undefault",
|
|
"-installdir",
|
|
"-tempdir",
|
|
"-secmod",
|
|
"-nocertdb",
|
|
"-string",
|
|
"-chkfips",
|
|
};
|
|
|
|
char *msgStrings[] = {
|
|
"FIPS mode enabled.\n",
|
|
"FIPS mode disabled.\n",
|
|
"Using database directory %s...\n",
|
|
"Creating \"%s\"...",
|
|
"Module \"%s\" added to database.\n",
|
|
"Module \"%s\" deleted from database.\n",
|
|
"Token \"%s\" password changed successfully.\n",
|
|
"Incorrect password, try again...\n",
|
|
"Passwords do not match, try again...\n",
|
|
"done.\n",
|
|
"Slot \"%s\" %s.\n",
|
|
"Successfully changed defaults.\n",
|
|
"Successfully changed defaults.\n",
|
|
"\nWARNING: Performing this operation while the browser is running could cause"
|
|
"\ncorruption of your security databases. If the browser is currently running,"
|
|
"\nyou should exit browser before continuing this operation. Type "
|
|
"\n'q <enter>' to abort, or <enter> to continue: ",
|
|
"\nAborting...\n"
|
|
};
|
|
|
|
/* Increment i if doing so would have i still be less than j. If you
|
|
are able to do this, return 0. Otherwise return 1. */
|
|
#define TRY_INC(i,j) ( ((i+1)<j) ? (++i, 0) : 1 )
|
|
|
|
/********************************************************************
|
|
*
|
|
* file-wide variables obtained from the command line
|
|
*/
|
|
static Command command = NO_COMMAND;
|
|
static char* pwFile = NULL;
|
|
static char* newpwFile = NULL;
|
|
static char* moduleName = NULL;
|
|
static char* moduleSpec = NULL;
|
|
static char* slotName = NULL;
|
|
static char* secmodName = NULL;
|
|
static char* tokenName = NULL;
|
|
static char* libFile = NULL;
|
|
static char* dbdir = NULL;
|
|
static char* dbprefix = "";
|
|
static char* secmodString = NULL;
|
|
static char* mechanisms = NULL;
|
|
static char* ciphers = NULL;
|
|
static char* fipsArg = NULL;
|
|
static char* jarFile = NULL;
|
|
static char* installDir = NULL;
|
|
static char* tempDir = NULL;
|
|
static short force = 0;
|
|
static PRBool nocertdb = PR_FALSE;
|
|
|
|
/*******************************************************************
|
|
*
|
|
* p a r s e _ a r g s
|
|
*/
|
|
static Error
|
|
parse_args(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
char *arg;
|
|
int optionType;
|
|
|
|
/* Loop over all arguments */
|
|
for(i=1; i < argc; i++) {
|
|
arg = argv[i];
|
|
|
|
/* Make sure this is an option and not some floating argument */
|
|
if(arg[0] != '-') {
|
|
PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
|
|
return UNEXPECTED_ARG_ERR;
|
|
}
|
|
|
|
/* Find which option this is */
|
|
for(optionType=0; optionType < NUM_ARGS; optionType++) {
|
|
if(! strcmp(arg, optionStrings[optionType])) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Deal with this specific option */
|
|
switch(optionType) {
|
|
case NUM_ARGS:
|
|
default:
|
|
PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
|
|
return UNKNOWN_OPTION_ERR;
|
|
break;
|
|
case ADD_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = ADD_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleName = argv[i];
|
|
break;
|
|
case CHANGEPW_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = CHANGEPW_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
tokenName = argv[i];
|
|
break;
|
|
case CIPHERS_ARG:
|
|
if(ciphers != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
ciphers = argv[i];
|
|
break;
|
|
case CREATE_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = CREATE_COMMAND;
|
|
break;
|
|
case DBDIR_ARG:
|
|
if(dbdir != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
dbdir = argv[i];
|
|
break;
|
|
case DBPREFIX_ARG:
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
dbprefix = argv[i];
|
|
break;
|
|
case UNDEFAULT_ARG:
|
|
case DEFAULT_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
if(optionType == DEFAULT_ARG) {
|
|
command = DEFAULT_COMMAND;
|
|
} else {
|
|
command = UNDEFAULT_COMMAND;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleName = argv[i];
|
|
break;
|
|
case DELETE_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = DELETE_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleName = argv[i];
|
|
break;
|
|
case DISABLE_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = DISABLE_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleName = argv[i];
|
|
break;
|
|
case ENABLE_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = ENABLE_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleName = argv[i];
|
|
break;
|
|
case FIPS_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = FIPS_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
fipsArg = argv[i];
|
|
break;
|
|
case CHKFIPS_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = CHKFIPS_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
fipsArg = argv[i];
|
|
break;
|
|
case FORCE_ARG:
|
|
force = 1;
|
|
break;
|
|
case NOCERTDB_ARG:
|
|
nocertdb = PR_TRUE;
|
|
break;
|
|
case INSTALLDIR_ARG:
|
|
if(installDir != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
installDir = argv[i];
|
|
break;
|
|
case TEMPDIR_ARG:
|
|
if(tempDir != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
tempDir = argv[i];
|
|
break;
|
|
case JAR_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = JAR_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
jarFile = argv[i];
|
|
break;
|
|
case LIBFILE_ARG:
|
|
if(libFile != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
libFile = argv[i];
|
|
break;
|
|
case LIST_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = LIST_COMMAND;
|
|
/* This option may or may not have an argument */
|
|
if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
|
|
moduleName = argv[++i];
|
|
}
|
|
break;
|
|
case RAW_LIST_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = RAW_LIST_COMMAND;
|
|
/* This option may or may not have an argument */
|
|
if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
|
|
moduleName = argv[++i];
|
|
}
|
|
break;
|
|
case RAW_ADD_ARG:
|
|
if(command != NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
|
|
return MULTIPLE_COMMAND_ERR;
|
|
}
|
|
command = RAW_ADD_COMMAND;
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
moduleSpec = argv[i];
|
|
break;
|
|
case MECHANISMS_ARG:
|
|
if(mechanisms != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
mechanisms = argv[i];
|
|
break;
|
|
case NEWPWFILE_ARG:
|
|
if(newpwFile != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
newpwFile = argv[i];
|
|
break;
|
|
case PWFILE_ARG:
|
|
if(pwFile != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
pwFile = argv[i];
|
|
break;
|
|
case SLOT_ARG:
|
|
if(slotName != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
slotName = argv[i];
|
|
break;
|
|
case SECMOD_ARG:
|
|
if(secmodName != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
secmodName = argv[i];
|
|
break;
|
|
case STRING_ARG:
|
|
if(secmodString != NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
|
|
return DUPLICATE_OPTION_ERR;
|
|
}
|
|
if(TRY_INC(i, argc)) {
|
|
PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
|
|
return OPTION_NEEDS_ARG_ERR;
|
|
}
|
|
secmodString = argv[i];
|
|
break;
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* v e r i f y _ p a r a m s
|
|
*/
|
|
static Error
|
|
verify_params()
|
|
{
|
|
switch(command) {
|
|
case ADD_COMMAND:
|
|
if(libFile == NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
|
|
commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
|
|
return MISSING_PARAM_ERR;
|
|
}
|
|
break;
|
|
case CHANGEPW_COMMAND:
|
|
break;
|
|
case CREATE_COMMAND:
|
|
break;
|
|
case DELETE_COMMAND:
|
|
break;
|
|
case DISABLE_COMMAND:
|
|
break;
|
|
case ENABLE_COMMAND:
|
|
break;
|
|
case FIPS_COMMAND:
|
|
case CHKFIPS_COMMAND:
|
|
if(PL_strcasecmp(fipsArg, "true") &&
|
|
PL_strcasecmp(fipsArg, "false")) {
|
|
PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
|
|
return INVALID_FIPS_ARG;
|
|
}
|
|
break;
|
|
case JAR_COMMAND:
|
|
if(installDir == NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
|
|
commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
|
|
return MISSING_PARAM_ERR;
|
|
}
|
|
break;
|
|
case LIST_COMMAND:
|
|
case RAW_LIST_COMMAND:
|
|
break;
|
|
case RAW_ADD_COMMAND:
|
|
break;
|
|
case UNDEFAULT_COMMAND:
|
|
case DEFAULT_COMMAND:
|
|
if(mechanisms == NULL) {
|
|
PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
|
|
commandNames[command], optionStrings[MECHANISMS_ARG]);
|
|
return MISSING_PARAM_ERR;
|
|
}
|
|
break;
|
|
default:
|
|
/* Ignore this here */
|
|
break;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* i n i t _ c r y p t o
|
|
*
|
|
* Does crypto initialization that all commands will require.
|
|
* If -nocertdb option is specified, don't open key or cert db (we don't
|
|
* need them if we aren't going to be verifying signatures). This is
|
|
* because serverland doesn't always have cert and key database files
|
|
* available.
|
|
*
|
|
* This function is ill advised. Names and locations of databases are
|
|
* private to NSS proper. Such functions only confuse other users.
|
|
*
|
|
*/
|
|
static Error
|
|
check_crypto(PRBool create, PRBool readOnly)
|
|
{
|
|
char *dir;
|
|
char *moddbname=NULL;
|
|
Error retval;
|
|
static const char multiaccess[] = { "multiaccess:" };
|
|
|
|
dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */
|
|
if (dir[0] == '\0') {
|
|
PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
|
|
retval=NO_DBDIR_ERR;
|
|
goto loser;
|
|
}
|
|
if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) {
|
|
/* won't attempt to handle the multiaccess case. */
|
|
return SUCCESS;
|
|
}
|
|
#ifdef notdef
|
|
/* Make sure db directory exists and is readable */
|
|
if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
|
|
retval = DIR_DOESNT_EXIST_ERR;
|
|
goto loser;
|
|
} else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
|
|
retval = DIR_NOT_READABLE_ERR;
|
|
goto loser;
|
|
}
|
|
|
|
if (secmodName == NULL) {
|
|
secmodName = "secmod.db";
|
|
}
|
|
|
|
moddbname = PR_smprintf("%s/%s", dir, secmodName);
|
|
if (!moddbname)
|
|
return OUT_OF_MEM_ERR;
|
|
|
|
/* Check for the proper permissions on databases */
|
|
if(create) {
|
|
/* Make sure dbs don't already exist, and the directory is
|
|
writeable */
|
|
if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
|
|
moddbname);
|
|
retval=FILE_ALREADY_EXISTS_ERR;
|
|
goto loser;
|
|
} else
|
|
if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
|
|
retval=DIR_NOT_WRITEABLE_ERR;
|
|
goto loser;
|
|
}
|
|
} else {
|
|
/* Make sure dbs are readable and writeable */
|
|
if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
|
|
retval=FILE_NOT_READABLE_ERR;
|
|
goto loser;
|
|
}
|
|
|
|
/* Check for write access if we'll be making changes */
|
|
if( !readOnly ) {
|
|
if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
|
|
PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
|
|
moddbname);
|
|
retval=FILE_NOT_WRITEABLE_ERR;
|
|
goto loser;
|
|
}
|
|
}
|
|
PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
|
|
SECU_ConfigDirectory(NULL));
|
|
}
|
|
#endif
|
|
retval=SUCCESS;
|
|
loser:
|
|
if (moddbname) {
|
|
PR_Free(moddbname);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
static Error
|
|
init_crypto(PRBool create, PRBool readOnly)
|
|
{
|
|
|
|
PRUint32 flags = 0;
|
|
SECStatus rv;
|
|
Error retval;
|
|
/* Open/create key database */
|
|
|
|
if (readOnly) flags |= NSS_INIT_READONLY;
|
|
if (nocertdb) flags |= NSS_INIT_NOCERTDB;
|
|
rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
|
|
secmodName, flags);
|
|
if (rv != SECSuccess) {
|
|
SECU_PrintPRandOSError(progName);
|
|
retval=NSS_INITIALIZE_FAILED_ERR;
|
|
} else
|
|
retval=SUCCESS;
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* u s a g e
|
|
*/
|
|
static void
|
|
usage()
|
|
{
|
|
PR_fprintf(PR_STDOUT,
|
|
"\nNetscape Cryptographic Module Utility\n"
|
|
"Usage: modutil [command] [options]\n\n"
|
|
" COMMANDS\n"
|
|
"---------------------------------------------------------------------------\n"
|
|
"-add MODULE_NAME Add the named module to the module database\n"
|
|
" -libfile LIBRARY_FILE The name of the file (.so or .dll)\n"
|
|
" containing the implementation of PKCS #11\n"
|
|
" [-ciphers CIPHER_LIST] Enable the given ciphers on this module\n"
|
|
" [-mechanisms MECHANISM_LIST] Make the module a default provider of the\n"
|
|
" given mechanisms\n"
|
|
" [-string CONFIG_STRING] Pass a configuration string to this module\n"
|
|
"-changepw TOKEN Change the password on the named token\n"
|
|
" [-pwfile FILE] The old password is in this file\n"
|
|
" [-newpwfile FILE] The new password is in this file\n"
|
|
"-chkfips [ true | false ] If true, verify FIPS mode. If false,\n"
|
|
" verify not FIPS mode\n"
|
|
"-create Create a new set of security databases\n"
|
|
"-default MODULE Make the given module a default provider\n"
|
|
" -mechanisms MECHANISM_LIST of the given mechanisms\n"
|
|
" [-slot SLOT] limit change to only the given slot\n"
|
|
"-delete MODULE Remove the named module from the module\n"
|
|
" database\n"
|
|
"-disable MODULE Disable the named module\n"
|
|
" [-slot SLOT] Disable only the named slot on the module\n"
|
|
"-enable MODULE Enable the named module\n"
|
|
" [-slot SLOT] Enable only the named slot on the module\n"
|
|
"-fips [ true | false ] If true, enable FIPS mode. If false,\n"
|
|
" disable FIPS mode\n"
|
|
"-force Do not run interactively\n"
|
|
"-jar JARFILE Install a PKCS #11 module from the given\n"
|
|
" JAR file in the PKCS #11 JAR format\n"
|
|
" -installdir DIR Use DIR as the root directory of the\n"
|
|
" installation\n"
|
|
" [-tempdir DIR] Use DIR as the temporary installation\n"
|
|
" directory. If not specified, the current\n"
|
|
" directory is used\n"
|
|
"-list [MODULE] Lists information about the specified module\n"
|
|
" or about all modules if none is specified\n"
|
|
"-rawadd MODULESPEC Add module spec string to secmod DB\n"
|
|
"-rawlist [MODULE] Display module spec(s) for one or all\n"
|
|
" loadable modules\n"
|
|
"-undefault MODULE The given module is NOT a default provider\n"
|
|
" -mechanisms MECHANISM_LIST of the listed mechanisms\n"
|
|
" [-slot SLOT] limit change to only the given slot\n"
|
|
"---------------------------------------------------------------------------\n"
|
|
"\n"
|
|
" OPTIONS\n"
|
|
"---------------------------------------------------------------------------\n"
|
|
"-dbdir DIR Directory DIR contains the security databases\n"
|
|
"-dbprefix prefix Prefix for the security databases\n"
|
|
"-nocertdb Do not load certificate or key databases. No\n"
|
|
" verification will be performed on JAR files.\n"
|
|
"-secmod secmodName Name of the security modules file\n"
|
|
"---------------------------------------------------------------------------\n"
|
|
"\n"
|
|
"Mechanism lists are colon-separated. The following mechanisms are recognized:\n"
|
|
"RSA, DSA, DH, RC2, RC4, RC5, AES, CAMELLIA, DES, MD2, MD5, SHA1, SHA256, SHA512,\n"
|
|
"SSL, TLS, RANDOM, and FRIENDLY\n"
|
|
"\n"
|
|
"Cipher lists are colon-separated. The following ciphers are recognized:\n"
|
|
"\n"
|
|
"\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n"
|
|
);
|
|
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* m a i n
|
|
*/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int errcode = SUCCESS;
|
|
PRBool createdb, readOnly;
|
|
#define STDINBUF_SIZE 80
|
|
char stdinbuf[STDINBUF_SIZE];
|
|
|
|
progName = strrchr(argv[0], '/');
|
|
progName = progName ? progName+1 : argv[0];
|
|
|
|
|
|
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
|
|
|
|
if(parse_args(argc, argv) != SUCCESS) {
|
|
usage();
|
|
errcode = INVALID_USAGE_ERR;
|
|
goto loser;
|
|
}
|
|
|
|
if(verify_params() != SUCCESS) {
|
|
usage();
|
|
errcode = INVALID_USAGE_ERR;
|
|
goto loser;
|
|
}
|
|
|
|
if(command==NO_COMMAND) {
|
|
PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
|
|
usage();
|
|
errcode = INVALID_USAGE_ERR;
|
|
goto loser;
|
|
}
|
|
|
|
/* Set up crypto stuff */
|
|
createdb = command==CREATE_COMMAND;
|
|
readOnly = ((command == LIST_COMMAND) ||
|
|
(command == CHKFIPS_COMMAND) ||
|
|
(command == RAW_LIST_COMMAND));
|
|
|
|
/* Make sure browser is not running if we're writing to a database */
|
|
/* Do this before initializing crypto */
|
|
if(!readOnly && !force) {
|
|
char *response;
|
|
|
|
PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
|
|
if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
|
|
PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
|
|
errcode = STDIN_READ_ERR;
|
|
goto loser;
|
|
}
|
|
if( (response=strtok(stdinbuf, " \r\n\t")) ) {
|
|
if(!PL_strcasecmp(response, "q")) {
|
|
PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
|
|
errcode = SUCCESS;
|
|
goto loser;
|
|
}
|
|
}
|
|
PR_fprintf(PR_STDOUT, "\n");
|
|
}
|
|
|
|
errcode = check_crypto(createdb, readOnly);
|
|
if( errcode != SUCCESS) {
|
|
goto loser;
|
|
}
|
|
|
|
if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
|
|
if(!moduleName) {
|
|
char *readOnlyStr, *noCertDBStr, *sep;
|
|
if (!secmodName) secmodName="secmod.db";
|
|
if (!dbprefix) dbprefix = "";
|
|
sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
|
|
readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ;
|
|
noCertDBStr = nocertdb ? "noCertDB" : "";
|
|
SECU_ConfigDirectory(dbdir);
|
|
|
|
moduleName=PR_smprintf(
|
|
"name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s "
|
|
"keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,"
|
|
"moduleDBOnly,critical\"",
|
|
SECU_ConfigDirectory(NULL),dbprefix,dbprefix,
|
|
secmodName, readOnlyStr,sep, noCertDBStr);
|
|
}
|
|
if (command == RAW_LIST_COMMAND) {
|
|
errcode = RawListModule(moduleName);
|
|
} else {
|
|
PORT_Assert(moduleSpec);
|
|
errcode = RawAddModule(moduleName,moduleSpec);
|
|
}
|
|
goto loser;
|
|
}
|
|
|
|
errcode = init_crypto(createdb, readOnly);
|
|
if( errcode != SUCCESS) {
|
|
goto loser;
|
|
}
|
|
|
|
errcode = LoadMechanismList();
|
|
if (errcode != SUCCESS) {
|
|
goto loser;
|
|
}
|
|
|
|
/* Execute the command */
|
|
switch(command) {
|
|
case ADD_COMMAND:
|
|
errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
|
|
break;
|
|
case CHANGEPW_COMMAND:
|
|
errcode = ChangePW(tokenName, pwFile, newpwFile);
|
|
break;
|
|
case CREATE_COMMAND:
|
|
/* The work was already done in init_crypto() */
|
|
break;
|
|
case DEFAULT_COMMAND:
|
|
errcode = SetDefaultModule(moduleName, slotName, mechanisms);
|
|
break;
|
|
case DELETE_COMMAND:
|
|
errcode = DeleteModule(moduleName);
|
|
break;
|
|
case DISABLE_COMMAND:
|
|
errcode = EnableModule(moduleName, slotName, PR_FALSE);
|
|
break;
|
|
case ENABLE_COMMAND:
|
|
errcode = EnableModule(moduleName, slotName, PR_TRUE);
|
|
break;
|
|
case FIPS_COMMAND:
|
|
errcode = FipsMode(fipsArg);
|
|
break;
|
|
case CHKFIPS_COMMAND:
|
|
errcode = ChkFipsMode(fipsArg);
|
|
break;
|
|
case JAR_COMMAND:
|
|
Pk11Install_SetErrorHandler(install_error);
|
|
errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
|
|
PR_STDOUT, force, nocertdb);
|
|
break;
|
|
case LIST_COMMAND:
|
|
if(moduleName) {
|
|
errcode = ListModule(moduleName);
|
|
} else {
|
|
errcode = ListModules();
|
|
}
|
|
break;
|
|
case UNDEFAULT_COMMAND:
|
|
errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
|
|
break;
|
|
default:
|
|
PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
|
|
errcode = INVALID_USAGE_ERR;
|
|
break;
|
|
}
|
|
|
|
if (NSS_Shutdown() != SECSuccess) {
|
|
exit(1);
|
|
}
|
|
|
|
loser:
|
|
PR_Cleanup();
|
|
return errcode;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* i n s t a l l _ e r r o r
|
|
*
|
|
* Callback function to handle errors in PK11 JAR file installation.
|
|
*/
|
|
static void
|
|
install_error(char *message)
|
|
{
|
|
PR_fprintf(PR_STDERR, "Install error: %s\n", message);
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* o u t _ o f _ m e m o r y
|
|
*/
|
|
void
|
|
out_of_memory(void)
|
|
{
|
|
PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
|
|
exit(OUT_OF_MEM_ERR);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* P R _ f g e t s
|
|
*
|
|
* fgets implemented with NSPR.
|
|
*/
|
|
static 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;
|
|
}
|