| /* 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", |
| "\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 <enter>' to abort, or <enter> 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; |
| } |