/* 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 #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 ' to abort, or to continue: ", "\nAborting...\n", "\nWARNING: Manually adding a module while p11-kit is enabled could cause" "\nduplicate module registration in your security database. It is suggested " "\nto configure the module through p11-kit configuration file instead.\n" "\nType 'q ' to abort, or to continue: " }; /* 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; } /* Warn if we are adding a module while p11-kit is enabled in the * database. */ if ((command == ADD_COMMAND || command == RAW_ADD_COMMAND) && IsP11KitEnabled()) { char* response; PR_fprintf(PR_STDOUT, msgStrings[P11_KIT_ENABLED_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"); } /* 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: errcode = InitPW(); 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; }