diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/cmd/modutil | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/cmd/modutil')
21 files changed, 8297 insertions, 0 deletions
diff --git a/security/nss/cmd/modutil/Makefile b/security/nss/cmd/modutil/Makefile new file mode 100644 index 0000000000..fc7b4b122b --- /dev/null +++ b/security/nss/cmd/modutil/Makefile @@ -0,0 +1,54 @@ +#! gmake +# +# 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/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk +include $(CORE_DEPTH)/coreconf/zlib.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + +include ../platrules.mk + +# +# Cancel the built-in implicit yacc and lex rules. +# + +%.c: %.y +%.c: %.l diff --git a/security/nss/cmd/modutil/README b/security/nss/cmd/modutil/README new file mode 100644 index 0000000000..12d192c9ff --- /dev/null +++ b/security/nss/cmd/modutil/README @@ -0,0 +1,7 @@ + CRYPTOGRAPHIC MODULE UTILITY (modutil) + VERSION 1.0 + =============================================== + +The file specification.html documentats the software. + +The file pk11jar.html documents the PKCS #11 JAR format. diff --git a/security/nss/cmd/modutil/error.h b/security/nss/cmd/modutil/error.h new file mode 100644 index 0000000000..33ed7bde7d --- /dev/null +++ b/security/nss/cmd/modutil/error.h @@ -0,0 +1,142 @@ +/* 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/. */ + +#ifndef MODUTIL_ERROR_H +#define MODUTIL_ERROR_H + +/* + * The values of these enumerated constants are immutable and must not be + * changed. + */ +typedef enum { + NO_ERR = 0, + INVALID_USAGE_ERR, + UNEXPECTED_ARG_ERR, + UNKNOWN_OPTION_ERR, + MULTIPLE_COMMAND_ERR, + OPTION_NEEDS_ARG_ERR, + DUPLICATE_OPTION_ERR, + MISSING_PARAM_ERR, + INVALID_FIPS_ARG, + NO_COMMAND_ERR, + NO_DBDIR_ERR, + FIPS_SWITCH_FAILED_ERR, + FIPS_ALREADY_ON_ERR, + FIPS_ALREADY_OFF_ERR, + FILE_ALREADY_EXISTS_ERR, + FILE_DOESNT_EXIST_ERR, + FILE_NOT_READABLE_ERR, + FILE_NOT_WRITEABLE_ERR, + DIR_DOESNT_EXIST_ERR, + DIR_NOT_READABLE_ERR, + DIR_NOT_WRITEABLE_ERR, + INVALID_CONSTANT_ERR, + ADD_MODULE_FAILED_ERR, + UNUSED_ERR, /* reserved for future use */ + OUT_OF_MEM_ERR, + DELETE_INTERNAL_ERR, + DELETE_FAILED_ERR, + NO_LIST_LOCK_ERR, + NO_MODULE_LIST_ERR, + NO_SUCH_MODULE_ERR, + MOD_INFO_ERR, + SLOT_INFO_ERR, + TOKEN_INFO_ERR, + NO_SUCH_TOKEN_ERR, + CHANGEPW_FAILED_ERR, + BAD_PW_ERR, + DB_ACCESS_ERR, + AUTHENTICATION_FAILED_ERR, + NO_SUCH_SLOT_ERR, + ENABLE_FAILED_ERR, + UPDATE_MOD_FAILED_ERR, + DEFAULT_FAILED_ERR, + UNDEFAULT_FAILED_ERR, + STDIN_READ_ERR, + UNSPECIFIED_ERR, + NOCERTDB_MISUSE_ERR, + NSS_INITIALIZE_FAILED_ERR, + INITPW_FAILED_ERR, + + LAST_ERR /* must be last */ +} Error; +#define SUCCESS NO_ERR + +/* !!! Should move this into its own .c and un-static it. */ +static char *errStrings[] = { + "Operation completed successfully.\n", + "ERROR: Invalid command line.\n", + "ERROR: Not expecting argument \"%s\".\n", + "ERROR: Unknown option: %s.\n", + "ERROR: %s: multiple commands are not allowed on the command line.\n", + "ERROR: %s: option needs an argument.\n", + "ERROR: %s: option cannot be given more than once.\n", + "ERROR: Command \"%s\" requires parameter \"%s\".\n", + "ERROR: Argument to -fips must be \"true\" or \"false\".\n", + "ERROR: No command was specified.\n", + "ERROR: Cannot determine database directory: use the -dbdir option.\n", + "ERROR: Unable to switch FIPS modes.\n", + "FIPS mode already enabled.\n", + "FIPS mode already disabled.\n", + "ERROR: File \"%s\" already exists.\n", + "ERROR: File \"%s\" does not exist.\n", + "ERROR: File \"%s\" is not readable.\n", + "ERROR: File \"%s\" is not writeable.\n", + "ERROR: Directory \"%s\" does not exist.\n", + "ERROR: Directory \"%s\" is not readable.\n", + "ERROR: Directory \"%s\" is not writeable.\n", + "\"%s\" is not a recognized value.\n", + "ERROR: Failed to add module \"%s\". Probable cause : \"%s\".\n", + "Unused error string", + "ERROR: Out of memory.\n", + "ERROR: Cannot delete internal module.\n", + "ERROR: Failed to delete module \"%s\".\n", + "ERROR: Unable to obtain lock on module list.\n", + "ERROR: Unable to obtain module list.\n", + "ERROR: Module \"%s\" not found in database.\n", + "ERROR: Unable to get information about module \"%s\".\n", + "ERROR: Unable to get information about slot \"%s\".\n", + "ERROR: Unable to get information about token \"%s\".\n", + "ERROR: Token \"%s\" not found.\n", + "ERROR: Unable to change password on token \"%s\".\n", + "ERROR: Incorrect password.\n", + "ERROR: Unable to access database \"%s\".\n", + "ERROR: Unable to authenticate to token \"%s\".\n", + "ERROR: Slot \"%s\" not found.\n", + "ERROR: Failed to %s slot \"%s\".\n", + "ERROR: Failed to update module \"%s\".\n", + "ERROR: Failed to change defaults.\n", + "ERROR: Failed to change default.\n", + "ERROR: Unable to read from standard input.\n", + "ERROR: Unknown error occurred.\n", + "ERROR: -nocertdb option can only be used with the -jar command.\n", + "ERROR: NSS_Initialize() failed.\n", + "ERROR: Unable to set initial password on the database.\n" +}; + +typedef enum { + FIPS_ENABLED_MSG = 0, + FIPS_DISABLED_MSG, + USING_DBDIR_MSG, + CREATING_DB_MSG, + ADD_MODULE_SUCCESS_MSG, + DELETE_SUCCESS_MSG, + CHANGEPW_SUCCESS_MSG, + BAD_PW_MSG, + PW_MATCH_MSG, + DONE_MSG, + ENABLE_SUCCESS_MSG, + DEFAULT_SUCCESS_MSG, + UNDEFAULT_SUCCESS_MSG, + BROWSER_RUNNING_MSG, + ABORTING_MSG, + P11_KIT_ENABLED_MSG, + + LAST_MSG /* must be last */ +} Message; + +/* defined in modutil.c */ +extern char *msgStrings[]; + +#endif /* MODUTIL_ERROR_H */ diff --git a/security/nss/cmd/modutil/install-ds.c b/security/nss/cmd/modutil/install-ds.c new file mode 100644 index 0000000000..d4ea73eda6 --- /dev/null +++ b/security/nss/cmd/modutil/install-ds.c @@ -0,0 +1,1522 @@ +/* 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 "install-ds.h" +#include <prmem.h> +#include <plstr.h> +#include <prprf.h> +#include <string.h> + +#define PORT_Strcasecmp PL_strcasecmp + +#define MODULE_FILE_STRING "ModuleFile" +#define MODULE_NAME_STRING "ModuleName" +#define MECH_FLAGS_STRING "DefaultMechanismFlags" +#define CIPHER_FLAGS_STRING "DefaultCipherFlags" +#define FILES_STRING "Files" +#define FORWARD_COMPATIBLE_STRING "ForwardCompatible" +#define PLATFORMS_STRING "Platforms" +#define RELATIVE_DIR_STRING "RelativePath" +#define ABSOLUTE_DIR_STRING "AbsolutePath" +#define FILE_PERMISSIONS_STRING "FilePermissions" +#define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform" +#define EXECUTABLE_STRING "Executable" + +#define DEFAULT_PERMISSIONS 0777 + +#define PLATFORM_SEPARATOR_CHAR ':' + +/* Error codes */ +enum { + BOGUS_RELATIVE_DIR = 0, + BOGUS_ABSOLUTE_DIR, + BOGUS_FILE_PERMISSIONS, + NO_RELATIVE_DIR, + NO_ABSOLUTE_DIR, + EMPTY_PLATFORM_STRING, + BOGUS_PLATFORM_STRING, + REPEAT_MODULE_FILE, + REPEAT_MODULE_NAME, + BOGUS_MODULE_FILE, + BOGUS_MODULE_NAME, + REPEAT_MECH, + BOGUS_MECH_FLAGS, + REPEAT_CIPHER, + BOGUS_CIPHER_FLAGS, + REPEAT_FILES, + REPEAT_EQUIV, + BOGUS_EQUIV, + EQUIV_TOO_MUCH_INFO, + NO_FILES, + NO_MODULE_FILE, + NO_MODULE_NAME, + NO_PLATFORMS, + EQUIV_LOOP, + UNKNOWN_MODULE_FILE +}; + +/* Indexed by the above error codes */ +static const char* errString[] = { + "%s: Invalid relative directory", + "%s: Invalid absolute directory", + "%s: Invalid file permissions", + "%s: No relative directory specified", + "%s: No absolute directory specified", + "Empty string given for platform name", + "%s: invalid platform string", + "More than one ModuleFile entry given for platform %s", + "More than one ModuleName entry given for platform %s", + "Invalid ModuleFile specification for platform %s", + "Invalid ModuleName specification for platform %s", + "More than one DefaultMechanismFlags entry given for platform %s", + "Invalid DefaultMechanismFlags specification for platform %s", + "More than one DefaultCipherFlags entry given for platform %s", + "Invalid DefaultCipherFlags entry given for platform %s", + "More than one Files entry given for platform %s", + "More than one EquivalentPlatform entry given for platform %s", + "Invalid EquivalentPlatform specification for platform %s", + "Module %s uses an EquivalentPlatform but also specifies its own" + " information", + "No Files specification in module %s", + "No ModuleFile specification in module %s", + "No ModuleName specification in module %s", + "No Platforms specification in installer script", + "Platform %s has an equivalency loop", + "Module file \"%s\" in platform \"%s\" does not exist" +}; + +static char* PR_Strdup(const char* str); + +#define PAD(x) \ + { \ + int pad_i; \ + for (pad_i = 0; pad_i < (x); pad_i++) \ + printf(" "); \ + } +#define PADINC 4 + +Pk11Install_File* +Pk11Install_File_new() +{ + Pk11Install_File* new_this; + new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File)); + Pk11Install_File_init(new_this); + return new_this; +} + +void +Pk11Install_File_init(Pk11Install_File* _this) +{ + _this->jarPath = NULL; + _this->relativePath = NULL; + _this->absolutePath = NULL; + _this->executable = PR_FALSE; + _this->permissions = 0; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: ~Pk11Install_File +// Class: Pk11Install_File +// Notes: Destructor. +*/ +void +Pk11Install_File_delete(Pk11Install_File* _this) +{ + Pk11Install_File_Cleanup(_this); +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Cleanup +// Class: Pk11Install_File +*/ +void +Pk11Install_File_Cleanup(Pk11Install_File* _this) +{ + if (_this->jarPath) { + PR_Free(_this->jarPath); + _this->jarPath = NULL; + } + if (_this->relativePath) { + PR_Free(_this->relativePath); + _this->relativePath = NULL; + } + if (_this->absolutePath) { + PR_Free(_this->absolutePath); + _this->absolutePath = NULL; + } + + _this->permissions = 0; + _this->executable = PR_FALSE; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Generate +// Class: Pk11Install_File +// Notes: Creates a file data structure from a syntax tree. +// Returns: NULL for success, otherwise an error message. +*/ +char* +Pk11Install_File_Generate(Pk11Install_File* _this, + const Pk11Install_Pair* pair) +{ + Pk11Install_ListIter* iter; + Pk11Install_Value* val; + Pk11Install_Pair* subpair; + Pk11Install_ListIter* subiter; + Pk11Install_Value* subval; + char* errStr; + char* endp; + PRBool gotPerms; + + iter = NULL; + subiter = NULL; + errStr = NULL; + gotPerms = PR_FALSE; + + /* Clear out old values */ + Pk11Install_File_Cleanup(_this); + + _this->jarPath = PR_Strdup(pair->key); + + /* Go through all the pairs under this file heading */ + iter = Pk11Install_ListIter_new(pair->list); + for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) { + if (val->type == PAIR_VALUE) { + subpair = val->pair; + + /* Relative directory */ + if (!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) { + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR], + _this->jarPath); + goto loser; + } + _this->relativePath = PR_Strdup(subval->string); + Pk11Install_ListIter_delete(&subiter); + + /* Absolute directory */ + } else if (!PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) { + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR], + _this->jarPath); + goto loser; + } + _this->absolutePath = PR_Strdup(subval->string); + Pk11Install_ListIter_delete(&subiter); + + /* file permissions */ + } else if (!PORT_Strcasecmp(subpair->key, + FILE_PERMISSIONS_STRING)) { + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE) || + !subval->string || !subval->string[0]) { + errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS], + _this->jarPath); + goto loser; + } + _this->permissions = (int)strtol(subval->string, &endp, 8); + if (*endp != '\0') { + errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS], + _this->jarPath); + goto loser; + } + gotPerms = PR_TRUE; + Pk11Install_ListIter_delete(&subiter); + } + } else { + if (!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) { + _this->executable = PR_TRUE; + } + } + } + + /* Default permission value */ + if (!gotPerms) { + _this->permissions = DEFAULT_PERMISSIONS; + } + + /* Make sure we got all the information */ + if (!_this->relativePath && !_this->absolutePath) { + errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath); + goto loser; + } +#if 0 + if(!_this->relativePath ) { + errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath); + goto loser; + } + if(!_this->absolutePath) { + errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath); + goto loser; + } +#endif + +loser: + if (iter) { + Pk11Install_ListIter_delete(&iter); + } + if (subiter) { + Pk11Install_ListIter_delete(&subiter); + } + return errStr; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Print +// Class: Pk11Install_File +*/ +void +Pk11Install_File_Print(Pk11Install_File* _this, int pad) +{ + PAD(pad); + printf("jarPath: %s\n", + _this->jarPath ? _this->jarPath : "<NULL>"); + PAD(pad); + printf("relativePath: %s\n", + _this->relativePath ? _this->relativePath : "<NULL>"); + PAD(pad); + printf("absolutePath: %s\n", + _this->absolutePath ? _this->absolutePath : "<NULL>"); + PAD(pad); + printf("permissions: %o\n", _this->permissions); +} + +Pk11Install_PlatformName* +Pk11Install_PlatformName_new() +{ + Pk11Install_PlatformName* new_this; + new_this = (Pk11Install_PlatformName*) + PR_Malloc(sizeof(Pk11Install_PlatformName)); + Pk11Install_PlatformName_init(new_this); + return new_this; +} + +void +Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this) +{ + _this->OS = NULL; + _this->verString = NULL; + _this->numDigits = 0; + _this->arch = NULL; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: ~Pk11Install_PlatformName +// Class: Pk11Install_PlatformName +*/ +void +Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this) +{ + Pk11Install_PlatformName_Cleanup(_this); +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Cleanup +// Class: Pk11Install_PlatformName +*/ +void +Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this) +{ + if (_this->OS) { + PR_Free(_this->OS); + _this->OS = NULL; + } + if (_this->verString) { + int i; + for (i = 0; i < _this->numDigits; i++) { + PR_Free(_this->verString[i]); + } + PR_Free(_this->verString); + _this->verString = NULL; + } + if (_this->arch) { + PR_Free(_this->arch); + _this->arch = NULL; + } + _this->numDigits = 0; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Generate +// Class: Pk11Install_PlatformName +// Notes: Extracts the information from a platform string. +*/ +char* +Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this, + const char* str) +{ + char* errStr; + char* copy; + char *end, *start; /* start and end of a section (OS, version, arch)*/ + char *pend, *pstart; /* start and end of one portion of version*/ + char* endp; /* used by strtol*/ + int periods, i; + + errStr = NULL; + copy = NULL; + + if (!str) { + errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]); + goto loser; + } + copy = PR_Strdup(str); + + /* + // Get the OS + */ + end = strchr(copy, PLATFORM_SEPARATOR_CHAR); + if (!end || end == copy) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + *end = '\0'; + + _this->OS = PR_Strdup(copy); + + /* + // Get the digits of the version of form: x.x.x (arbitrary number of digits) + */ + + start = end + 1; + end = strchr(start, PLATFORM_SEPARATOR_CHAR); + if (!end) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + *end = '\0'; + + if (end != start) { + /* Find out how many periods*/ + periods = 0; + pstart = start; + while ((pend = strchr(pstart, '.'))) { + periods++; + pstart = pend + 1; + } + _this->numDigits = 1 + periods; + _this->verString = (char**)PR_Malloc(sizeof(char*) * _this->numDigits); + + pstart = start; + i = 0; + /* Get the digits before each period*/ + while ((pend = strchr(pstart, '.'))) { + if (pend == pstart) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + *pend = '\0'; + _this->verString[i] = PR_Strdup(pstart); + endp = pend; + if (endp == pstart || (*endp != '\0')) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + pstart = pend + 1; + i++; + } + /* Last digit comes after the last period*/ + if (*pstart == '\0') { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + _this->verString[i] = PR_Strdup(pstart); + /* + if(endp==pstart || (*endp != '\0')) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + */ + } else { + _this->verString = NULL; + _this->numDigits = 0; + } + + /* + // Get the architecture + */ + start = end + 1; + if (strchr(start, PLATFORM_SEPARATOR_CHAR)) { + errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); + goto loser; + } + _this->arch = PR_Strdup(start); + + if (copy) { + PR_Free(copy); + } + return NULL; +loser: + if (_this->OS) { + PR_Free(_this->OS); + _this->OS = NULL; + } + if (_this->verString) { + for (i = 0; i < _this->numDigits; i++) { + PR_Free(_this->verString[i]); + } + PR_Free(_this->verString); + _this->verString = NULL; + } + _this->numDigits = 0; + if (_this->arch) { + PR_Free(_this->arch); + _this->arch = NULL; + } + if (copy) { + PR_Free(copy); + } + + return errStr; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: operator == +// Class: Pk11Install_PlatformName +// Returns: PR_TRUE if the platform have the same OS, arch, and version +*/ +PRBool +Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp) +{ + int i; + + if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) { + return PR_FALSE; + } + + if (PORT_Strcasecmp(_this->OS, cmp->OS) || + PORT_Strcasecmp(_this->arch, cmp->arch) || + _this->numDigits != cmp->numDigits) { + return PR_FALSE; + } + + for (i = 0; i < _this->numDigits; i++) { + if (PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) { + return PR_FALSE; + } + } + return PR_TRUE; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: operator <= +// Class: Pk11Install_PlatformName +// Returns: PR_TRUE if the platform have the same OS and arch and a lower +// or equal release. +*/ +PRBool +Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp) +{ + return (Pk11Install_PlatformName_equal(_this, cmp) || + Pk11Install_PlatformName_lt(_this, cmp)) + ? PR_TRUE + : PR_FALSE; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: operator < +// Class: Pk11Install_PlatformName +// Returns: PR_TRUE if the platform have the same OS and arch and a greater +// release. +*/ +PRBool +Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp) +{ + int i, scmp; + + if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) { + return PR_FALSE; + } + + if (PORT_Strcasecmp(_this->OS, cmp->OS)) { + return PR_FALSE; + } + if (PORT_Strcasecmp(_this->arch, cmp->arch)) { + return PR_FALSE; + } + + for (i = 0; (i < _this->numDigits) && (i < cmp->numDigits); i++) { + scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]); + if (scmp > 0) { + return PR_FALSE; + } else if (scmp < 0) { + return PR_TRUE; + } + } + /* All the digits they have in common are the same. */ + if (_this->numDigits < cmp->numDigits) { + return PR_TRUE; + } + + return PR_FALSE; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: GetString +// Class: Pk11Install_PlatformName +// Returns: String composed of OS, release, and architecture separated +// by the separator char. Memory is allocated by this function +// but is the responsibility of the caller to de-allocate. +*/ +char* +Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this) +{ + char* ret; + char* ver; + char* OS_; + char* arch_; + + OS_ = NULL; + arch_ = NULL; + + OS_ = _this->OS ? _this->OS : ""; + arch_ = _this->arch ? _this->arch : ""; + + ver = Pk11Install_PlatformName_GetVerString(_this); + ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver, + PLATFORM_SEPARATOR_CHAR, arch_); + + PR_Free(ver); + + return ret; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: GetVerString +// Class: Pk11Install_PlatformName +// Returns: The version string for this platform, in the form x.x.x with an +// arbitrary number of digits. Memory allocated by function, +// must be de-allocated by caller. +*/ +char* +Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this) +{ + char* tmp; + char* ret; + int i; + char buf[80]; + + tmp = (char*)PR_Malloc(80 * _this->numDigits + 1); + tmp[0] = '\0'; + + for (i = 0; i < _this->numDigits - 1; i++) { + snprintf(buf, sizeof(buf), "%s.", _this->verString[i]); + strcat(tmp, buf); + } + if (i < _this->numDigits) { + snprintf(buf, sizeof(buf), "%s", _this->verString[i]); + strcat(tmp, buf); + } + + ret = PR_Strdup(tmp); + free(tmp); + + return ret; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Print +// Class: Pk11Install_PlatformName +*/ +void +Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad) +{ + char* str = NULL; + PAD(pad); + printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>"); + PAD(pad); + printf("Digits: "); + if (_this->numDigits == 0) { + printf("None\n"); + } else { + str = Pk11Install_PlatformName_GetVerString(_this); + printf("%s\n", str); + PR_Free(str); + } + PAD(pad); + printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>"); +} + +Pk11Install_Platform* +Pk11Install_Platform_new() +{ + Pk11Install_Platform* new_this; + new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform)); + Pk11Install_Platform_init(new_this); + return new_this; +} + +void +Pk11Install_Platform_init(Pk11Install_Platform* _this) +{ + Pk11Install_PlatformName_init(&_this->name); + Pk11Install_PlatformName_init(&_this->equivName); + _this->equiv = NULL; + _this->usesEquiv = PR_FALSE; + _this->moduleFile = NULL; + _this->moduleName = NULL; + _this->modFile = -1; + _this->mechFlags = 0; + _this->cipherFlags = 0; + _this->files = NULL; + _this->numFiles = 0; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: ~Pk11Install_Platform +// Class: Pk11Install_Platform +*/ +void +Pk11Install_Platform_delete(Pk11Install_Platform* _this) +{ + Pk11Install_Platform_Cleanup(_this); +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Cleanup +// Class: Pk11Install_Platform +*/ +void +Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this) +{ + int i; + if (_this->moduleFile) { + PR_Free(_this->moduleFile); + _this->moduleFile = NULL; + } + if (_this->moduleName) { + PR_Free(_this->moduleName); + _this->moduleName = NULL; + } + if (_this->files) { + for (i = 0; i < _this->numFiles; i++) { + Pk11Install_File_delete(&_this->files[i]); + } + PR_Free(_this->files); + _this->files = NULL; + } + _this->equiv = NULL; + _this->usesEquiv = PR_FALSE; + _this->modFile = -1; + _this->numFiles = 0; + _this->mechFlags = _this->cipherFlags = 0; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Generate +// Class: Pk11Install_Platform +// Notes: Creates a platform data structure from a syntax tree. +// Returns: NULL for success, otherwise an error message. +*/ +char* +Pk11Install_Platform_Generate(Pk11Install_Platform* _this, + const Pk11Install_Pair* pair) +{ + char* errStr; + char* endptr; + char* tmp; + int i; + Pk11Install_ListIter* iter; + Pk11Install_Value* val; + Pk11Install_Value* subval; + Pk11Install_Pair* subpair; + Pk11Install_ListIter* subiter; + PRBool gotModuleFile, gotModuleName, gotMech, + gotCipher, gotFiles, gotEquiv; + + errStr = NULL; + iter = subiter = NULL; + val = subval = NULL; + subpair = NULL; + gotModuleFile = gotModuleName = gotMech = gotCipher = gotFiles = gotEquiv = PR_FALSE; + Pk11Install_Platform_Cleanup(_this); + + errStr = Pk11Install_PlatformName_Generate(&_this->name, pair->key); + if (errStr) { + tmp = PR_smprintf("%s: %s", pair->key, errStr); + PR_smprintf_free(errStr); + errStr = tmp; + goto loser; + } + + iter = Pk11Install_ListIter_new(pair->list); + for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) { + if (val->type == PAIR_VALUE) { + subpair = val->pair; + + if (!PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) { + if (gotModuleFile) { + errStr = PR_smprintf(errString[REPEAT_MODULE_FILE], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_MODULE_FILE], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + _this->moduleFile = PR_Strdup(subval->string); + Pk11Install_ListIter_delete(&subiter); + gotModuleFile = PR_TRUE; + } else if (!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)) { + if (gotModuleName) { + errStr = PR_smprintf(errString[REPEAT_MODULE_NAME], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_MODULE_NAME], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + _this->moduleName = PR_Strdup(subval->string); + Pk11Install_ListIter_delete(&subiter); + gotModuleName = PR_TRUE; + } else if (!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) { + endptr = NULL; + + if (gotMech) { + errStr = PR_smprintf(errString[REPEAT_MECH], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + _this->mechFlags = strtol(subval->string, &endptr, 0); + if (*endptr != '\0' || (endptr == subval->string)) { + errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + Pk11Install_ListIter_delete(&subiter); + gotMech = PR_TRUE; + } else if (!PORT_Strcasecmp(subpair->key, CIPHER_FLAGS_STRING)) { + endptr = NULL; + + if (gotCipher) { + errStr = PR_smprintf(errString[REPEAT_CIPHER], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + _this->cipherFlags = strtol(subval->string, &endptr, 0); + if (*endptr != '\0' || (endptr == subval->string)) { + errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + Pk11Install_ListIter_delete(&subiter); + gotCipher = PR_TRUE; + } else if (!PORT_Strcasecmp(subpair->key, FILES_STRING)) { + if (gotFiles) { + errStr = PR_smprintf(errString[REPEAT_FILES], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + _this->numFiles = subpair->list->numPairs; + _this->files = (Pk11Install_File*) + PR_Malloc(sizeof(Pk11Install_File) * _this->numFiles); + for (i = 0; i < _this->numFiles; i++, + Pk11Install_ListIter_nextItem(subiter)) { + Pk11Install_File_init(&_this->files[i]); + val = subiter->current; + if (val && (val->type == PAIR_VALUE)) { + errStr = Pk11Install_File_Generate(&_this->files[i], val->pair); + if (errStr) { + tmp = PR_smprintf("%s: %s", + Pk11Install_PlatformName_GetString(&_this->name), errStr); + PR_smprintf_free(errStr); + errStr = tmp; + goto loser; + } + } + } + gotFiles = PR_TRUE; + } else if (!PORT_Strcasecmp(subpair->key, + EQUIVALENT_PLATFORM_STRING)) { + if (gotEquiv) { + errStr = PR_smprintf(errString[REPEAT_EQUIV], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + subiter = Pk11Install_ListIter_new(subpair->list); + subval = subiter->current; + if (!subval || (subval->type != STRING_VALUE)) { + errStr = PR_smprintf(errString[BOGUS_EQUIV], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + errStr = Pk11Install_PlatformName_Generate(&_this->equivName, + subval->string); + if (errStr) { + tmp = PR_smprintf("%s: %s", + Pk11Install_PlatformName_GetString(&_this->name), errStr); + PR_smprintf_free(errStr); + errStr = tmp; + goto loser; + } + _this->usesEquiv = PR_TRUE; + } + } + } + + /* Make sure we either have an EquivalentPlatform or all the other info */ + if (_this->usesEquiv && + (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) { + errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + if (!gotFiles && !_this->usesEquiv) { + errStr = PR_smprintf(errString[NO_FILES], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + if (!gotModuleFile && !_this->usesEquiv) { + errStr = PR_smprintf(errString[NO_MODULE_FILE], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + if (!gotModuleName && !_this->usesEquiv) { + errStr = PR_smprintf(errString[NO_MODULE_NAME], + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + + /* Point the modFile pointer to the correct file */ + if (gotModuleFile) { + for (i = 0; i < _this->numFiles; i++) { + if (!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath)) { + _this->modFile = i; + break; + } + } + if (_this->modFile == -1) { + errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE], + _this->moduleFile, + Pk11Install_PlatformName_GetString(&_this->name)); + goto loser; + } + } + +loser: + if (iter) { + PR_Free(iter); + } + if (subiter) { + PR_Free(subiter); + } + return errStr; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Print +// Class: Pk11Install_Platform +*/ +void +Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad) +{ + int i; + + PAD(pad); + printf("Name:\n"); + Pk11Install_PlatformName_Print(&_this->name, pad + PADINC); + PAD(pad); + printf("equivName:\n"); + Pk11Install_PlatformName_Print(&_this->equivName, pad + PADINC); + PAD(pad); + if (_this->usesEquiv) { + printf("Uses equiv, which points to:\n"); + Pk11Install_Platform_Print(_this->equiv, pad + PADINC); + } else { + printf("Doesn't use equiv\n"); + } + PAD(pad); + printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile : "<NULL>"); + PAD(pad); + printf("mechFlags: %lx\n", _this->mechFlags); + PAD(pad); + printf("cipherFlags: %lx\n", _this->cipherFlags); + PAD(pad); + printf("Files:\n"); + for (i = 0; i < _this->numFiles; i++) { + Pk11Install_File_Print(&_this->files[i], pad + PADINC); + PAD(pad); + printf("--------------------\n"); + } +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Pk11Install_Info +// Class: Pk11Install_Info +*/ +Pk11Install_Info* +Pk11Install_Info_new() +{ + Pk11Install_Info* new_this; + new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info)); + Pk11Install_Info_init(new_this); + return new_this; +} + +void +Pk11Install_Info_init(Pk11Install_Info* _this) +{ + _this->platforms = NULL; + _this->numPlatforms = 0; + _this->forwardCompatible = NULL; + _this->numForwardCompatible = 0; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: ~Pk11Install_Info +// Class: Pk11Install_Info +*/ +void +Pk11Install_Info_delete(Pk11Install_Info* _this) +{ + Pk11Install_Info_Cleanup(_this); +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Cleanup +// Class: Pk11Install_Info +*/ +void +Pk11Install_Info_Cleanup(Pk11Install_Info* _this) +{ + int i; + if (_this->platforms) { + for (i = 0; i < _this->numPlatforms; i++) { + Pk11Install_Platform_delete(&_this->platforms[i]); + } + PR_Free(_this->platforms); + _this->platforms = NULL; + _this->numPlatforms = 0; + } + + if (_this->forwardCompatible) { + for (i = 0; i < _this->numForwardCompatible; i++) { + Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]); + } + PR_Free(_this->forwardCompatible); + _this->numForwardCompatible = 0; + } +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Generate +// Class: Pk11Install_Info +// Takes: Pk11Install_ValueList *list, the top-level list +// resulting from parsing an installer file. +// Returns: char*, NULL if successful, otherwise an error string. +// Caller is responsible for freeing memory. +*/ +char* +Pk11Install_Info_Generate(Pk11Install_Info* _this, + const Pk11Install_ValueList* list) +{ + char* errStr; + Pk11Install_ListIter* iter; + Pk11Install_Value* val; + Pk11Install_Pair* pair; + Pk11Install_ListIter* subiter; + Pk11Install_Value* subval; + Pk11Install_Platform *first, *second; + int i, j; + + errStr = NULL; + iter = subiter = NULL; + Pk11Install_Info_Cleanup(_this); + + iter = Pk11Install_ListIter_new(list); + for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) { + if (val->type == PAIR_VALUE) { + pair = val->pair; + + if (!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) { + subiter = Pk11Install_ListIter_new(pair->list); + _this->numForwardCompatible = pair->list->numStrings; + _this->forwardCompatible = (Pk11Install_PlatformName*) + PR_Malloc(sizeof(Pk11Install_PlatformName) * + _this->numForwardCompatible); + for (i = 0; i < _this->numForwardCompatible; i++, + Pk11Install_ListIter_nextItem(subiter)) { + subval = subiter->current; + if (subval->type == STRING_VALUE) { + errStr = Pk11Install_PlatformName_Generate( + &_this->forwardCompatible[i], subval->string); + if (errStr) { + goto loser; + } + } + } + Pk11Install_ListIter_delete(&subiter); + } else if (!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) { + subiter = Pk11Install_ListIter_new(pair->list); + _this->numPlatforms = pair->list->numPairs; + _this->platforms = (Pk11Install_Platform*) + PR_Malloc(sizeof(Pk11Install_Platform) * + _this->numPlatforms); + for (i = 0; i < _this->numPlatforms; i++, + Pk11Install_ListIter_nextItem(subiter)) { + Pk11Install_Platform_init(&_this->platforms[i]); + subval = subiter->current; + if (subval->type == PAIR_VALUE) { + errStr = Pk11Install_Platform_Generate(&_this->platforms[i], subval->pair); + if (errStr) { + goto loser; + } + } + } + Pk11Install_ListIter_delete(&subiter); + } + } + } + + if (_this->numPlatforms == 0) { + errStr = PR_smprintf(errString[NO_PLATFORMS]); + goto loser; + } + + /* + // + // Now process equivalent platforms + // + + // First the naive pass + */ + for (i = 0; i < _this->numPlatforms; i++) { + if (_this->platforms[i].usesEquiv) { + _this->platforms[i].equiv = NULL; + for (j = 0; j < _this->numPlatforms; j++) { + if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName, + &_this->platforms[j].name)) { + if (i == j) { + errStr = PR_smprintf(errString[EQUIV_LOOP], + Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); + goto loser; + } + _this->platforms[i].equiv = &_this->platforms[j]; + break; + } + } + if (_this->platforms[i].equiv == NULL) { + errStr = PR_smprintf(errString[BOGUS_EQUIV], + Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); + goto loser; + } + } + } + + /* + // Now the intelligent pass, which will also detect loops. + // We will send two pointers through the linked list of equivalent + // platforms. Both start with the current node. "first" traverses + // two nodes for each iteration. "second" lags behind, only traversing + // one node per iteration. Eventually one of two things will happen: + // first will hit the end of the list (a platform that doesn't use + // an equivalency), or first will equal second if there is a loop. + */ + for (i = 0; i < _this->numPlatforms; i++) { + if (_this->platforms[i].usesEquiv) { + second = _this->platforms[i].equiv; + if (!second->usesEquiv) { + /* The first link is the terminal node */ + continue; + } + first = second->equiv; + while (first->usesEquiv) { + if (first == second) { + errStr = PR_smprintf(errString[EQUIV_LOOP], + Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); + goto loser; + } + first = first->equiv; + if (!first->usesEquiv) { + break; + } + if (first == second) { + errStr = PR_smprintf(errString[EQUIV_LOOP], + Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); + goto loser; + } + second = second->equiv; + first = first->equiv; + } + _this->platforms[i].equiv = first; + } + } + +loser: + if (iter) { + Pk11Install_ListIter_delete(&iter); + } + if (subiter) { + Pk11Install_ListIter_delete(&subiter); + } + return errStr; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: GetBestPlatform +// Class: Pk11Install_Info +// Takes: char *myPlatform, the platform we are currently running +// on. +*/ +Pk11Install_Platform* +Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform) +{ + Pk11Install_PlatformName plat; + char* errStr; + int i, j; + + errStr = NULL; + + Pk11Install_PlatformName_init(&plat); + if ((errStr = Pk11Install_PlatformName_Generate(&plat, myPlatform))) { + PR_smprintf_free(errStr); + return NULL; + } + + /* First try real platforms */ + for (i = 0; i < _this->numPlatforms; i++) { + if (Pk11Install_PlatformName_equal(&_this->platforms[i].name, &plat)) { + if (_this->platforms[i].equiv) { + return _this->platforms[i].equiv; + } else { + return &_this->platforms[i]; + } + } + } + + /* Now try forward compatible platforms */ + for (i = 0; i < _this->numForwardCompatible; i++) { + if (Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i], &plat)) { + break; + } + } + if (i == _this->numForwardCompatible) { + return NULL; + } + + /* Got a forward compatible name, find the actual platform. */ + for (j = 0; j < _this->numPlatforms; j++) { + if (Pk11Install_PlatformName_equal(&_this->platforms[j].name, + &_this->forwardCompatible[i])) { + if (_this->platforms[j].equiv) { + return _this->platforms[j].equiv; + } else { + return &_this->platforms[j]; + } + } + } + + return NULL; +} + +/* +////////////////////////////////////////////////////////////////////////// +// Method: Print +// Class: Pk11Install_Info +*/ +void +Pk11Install_Info_Print(Pk11Install_Info* _this, int pad) +{ + int i; + + PAD(pad); + printf("Forward Compatible:\n"); + for (i = 0; i < _this->numForwardCompatible; i++) { + Pk11Install_PlatformName_Print(&_this->forwardCompatible[i], pad + PADINC); + PAD(pad); + printf("-------------------\n"); + } + PAD(pad); + printf("Platforms:\n"); + for (i = 0; i < _this->numPlatforms; i++) { + Pk11Install_Platform_Print(&_this->platforms[i], pad + PADINC); + PAD(pad); + printf("-------------------\n"); + } +} + +/* +////////////////////////////////////////////////////////////////////////// +*/ +static char* +PR_Strdup(const char* str) +{ + char* tmp; + tmp = (char*)PR_Malloc((unsigned int)(strlen(str) + 1)); + strcpy(tmp, str); + return tmp; +} + +/* The global value list, the top of the tree */ +Pk11Install_ValueList* Pk11Install_valueList = NULL; + +/****************************************************************************/ +void +Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this, + Pk11Install_Value* item) +{ + _this->numItems++; + if (item->type == STRING_VALUE) { + _this->numStrings++; + } else { + _this->numPairs++; + } + item->next = _this->head; + _this->head = item; +} + +/****************************************************************************/ +Pk11Install_ListIter* +Pk11Install_ListIter_new_default() +{ + Pk11Install_ListIter* new_this; + new_this = (Pk11Install_ListIter*) + PR_Malloc(sizeof(Pk11Install_ListIter)); + Pk11Install_ListIter_init(new_this); + return new_this; +} + +/****************************************************************************/ +void +Pk11Install_ListIter_init(Pk11Install_ListIter* _this) +{ + _this->list = NULL; + _this->current = NULL; +} + +/****************************************************************************/ +Pk11Install_ListIter* +Pk11Install_ListIter_new(const Pk11Install_ValueList* _list) +{ + Pk11Install_ListIter* new_this; + new_this = (Pk11Install_ListIter*) + PR_Malloc(sizeof(Pk11Install_ListIter)); + new_this->list = _list; + new_this->current = _list->head; + return new_this; +} + +/****************************************************************************/ +void +Pk11Install_ListIter_delete(Pk11Install_ListIter** _this) +{ + (*_this)->list = NULL; + (*_this)->current = NULL; + PR_Free(*_this); + *_this = NULL; +} + +/****************************************************************************/ +void +Pk11Install_ListIter_reset(Pk11Install_ListIter* _this) +{ + if (_this->list) { + _this->current = _this->list->head; + } +} + +/*************************************************************************/ +Pk11Install_Value* +Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this) +{ + if (_this->current) { + _this->current = _this->current->next; + } + + return _this->current; +} + +/****************************************************************************/ +Pk11Install_ValueList* +Pk11Install_ValueList_new() +{ + Pk11Install_ValueList* new_this; + new_this = (Pk11Install_ValueList*) + PR_Malloc(sizeof(Pk11Install_ValueList)); + new_this->numItems = 0; + new_this->numPairs = 0; + new_this->numStrings = 0; + new_this->head = NULL; + return new_this; +} + +/****************************************************************************/ +void +Pk11Install_ValueList_delete(Pk11Install_ValueList* _this) +{ + + Pk11Install_Value* tmp; + Pk11Install_Value* list; + list = _this->head; + + while (list != NULL) { + tmp = list; + list = list->next; + PR_Free(tmp); + } + PR_Free(_this); +} + +/****************************************************************************/ +Pk11Install_Value* +Pk11Install_Value_new_default() +{ + Pk11Install_Value* new_this; + new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value)); + new_this->type = STRING_VALUE; + new_this->string = NULL; + new_this->pair = NULL; + new_this->next = NULL; + return new_this; +} + +/****************************************************************************/ +Pk11Install_Value* +Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr) +{ + Pk11Install_Value* new_this; + new_this = Pk11Install_Value_new_default(); + new_this->type = _type; + if (_type == STRING_VALUE) { + new_this->pair = NULL; + new_this->string = ptr.string; + } else { + new_this->string = NULL; + new_this->pair = ptr.pair; + } + return new_this; +} + +/****************************************************************************/ +void +Pk11Install_Value_delete(Pk11Install_Value* _this) +{ + if (_this->type == STRING_VALUE) { + PR_Free(_this->string); + } else { + PR_Free(_this->pair); + } +} + +/****************************************************************************/ +Pk11Install_Pair* +Pk11Install_Pair_new_default() +{ + return Pk11Install_Pair_new(NULL, NULL); +} + +/****************************************************************************/ +Pk11Install_Pair* +Pk11Install_Pair_new(char* _key, Pk11Install_ValueList* _list) +{ + Pk11Install_Pair* new_this; + new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair)); + new_this->key = _key; + new_this->list = _list; + return new_this; +} + +/****************************************************************************/ +void +Pk11Install_Pair_delete(Pk11Install_Pair* _this) +{ + PR_Free(_this->key); + Pk11Install_ValueList_delete(_this->list); +} + +/*************************************************************************/ +void +Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad) +{ + while (_this) { + /*PAD(pad); printf("**Pair\n"); + PAD(pad); printf("***Key====\n");*/ + PAD(pad); + printf("%s {\n", _this->key); + /*PAD(pad); printf("====\n");*/ + /*PAD(pad); printf("***ValueList\n");*/ + Pk11Install_ValueList_Print(_this->list, pad + PADINC); + PAD(pad); + printf("}\n"); + } +} + +/*************************************************************************/ +void +Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad) +{ + Pk11Install_Value* v; + + /*PAD(pad);printf("**Value List**\n");*/ + for (v = _this->head; v != NULL; v = v->next) { + Pk11Install_Value_Print(v, pad); + } +} + +/*************************************************************************/ +void +Pk11Install_Value_Print(Pk11Install_Value* _this, int pad) +{ + /*PAD(pad); printf("**Value, type=%s\n", + type==STRING_VALUE ? "string" : "pair");*/ + if (_this->type == STRING_VALUE) { + /*PAD(pad+PADINC); printf("====\n");*/ + PAD(pad); + printf("%s\n", _this->string); + /*PAD(pad+PADINC); printf("====\n");*/ + } else { + Pk11Install_Pair_Print(_this->pair, pad + PADINC); + } +} diff --git a/security/nss/cmd/modutil/install-ds.h b/security/nss/cmd/modutil/install-ds.h new file mode 100644 index 0000000000..70813f6030 --- /dev/null +++ b/security/nss/cmd/modutil/install-ds.h @@ -0,0 +1,260 @@ +/* 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/. */ + +#ifndef INSTALL_DS_H +#define INSTALL_DS_H + +#include <stdio.h> +#include <prio.h> +#include <prmem.h> + +extern PRFileDesc* Pk11Install_FD; +extern int Pk11Install_yylex(); +extern int Pk11Install_yylinenum; +extern char* Pk11Install_yyerrstr; + +typedef enum { STRING_VALUE, + PAIR_VALUE } ValueType; + +typedef struct Pk11Install_Pair_str Pk11Install_Pair; +typedef union Pk11Install_Pointer_str Pk11Install_Pointer; +typedef struct Pk11Install_Value_str Pk11Install_Value; +typedef struct Pk11Install_ValueList_str Pk11Install_ValueList; +typedef struct Pk11Install_ListIter_str Pk11Install_ListIter; +typedef struct Pk11Install_File_str Pk11Install_File; +typedef struct Pk11Install_PlatformName_str Pk11Install_PlatformName; +typedef struct Pk11Install_Platform_str Pk11Install_Platform; +typedef struct Pk11Install_Info_str Pk11Install_Info; + +extern Pk11Install_Pointer Pk11Install_yylval; +extern Pk11Install_ValueList* Pk11Install_valueList; + +/* +////////////////////////////////////////////////////////////////////////// +// Pk11Install_Pair +////////////////////////////////////////////////////////////////////////// +*/ + +struct Pk11Install_Pair_str { + char* key; + Pk11Install_ValueList* list; +}; + +Pk11Install_Pair* +Pk11Install_Pair_new_default(); +Pk11Install_Pair* +Pk11Install_Pair_new(char* _key, Pk11Install_ValueList* _list); +void +Pk11Install_Pair_delete(Pk11Install_Pair* _this); +void +Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad); + +/* +////////////////////////////////////////////////////////////////////////// +// Pk11Install_Pointer +////////////////////////////////////////////////////////////////////////// +*/ +union Pk11Install_Pointer_str { + Pk11Install_ValueList* list; + Pk11Install_Value* value; + Pk11Install_Pair* pair; + char* string; +}; + +/* +////////////////////////////////////////////////////////////////////////// +// Pk11Install_Value +////////////////////////////////////////////////////////////////////////// +*/ +struct Pk11Install_Value_str { + + ValueType type; + char* string; + Pk11Install_Pair* pair; + struct Pk11Install_Value_str* next; +}; + +Pk11Install_Value* +Pk11Install_Value_new_default(); +Pk11Install_Value* +Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr); +void +Pk11Install_Value_delete(Pk11Install_Value* _this); +void +Pk11Install_Value_Print(Pk11Install_Value* _this, int pad); + +/* +////////////////////////////////////////////////////////////////////////// +// Pk11Install_ValueList +////////////////////////////////////////////////////////////////////////// +*/ +struct Pk11Install_ValueList_str { + int numItems; + int numPairs; + int numStrings; + Pk11Install_Value* head; +}; + +Pk11Install_ValueList* +Pk11Install_ValueList_new(); +void +Pk11Install_ValueList_delete(Pk11Install_ValueList* _this); +void +Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this, + Pk11Install_Value* item); +void +Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad); + +/* +////////////////////////////////////////////////////////////////////////// +// Pk11Install_ListIter +////////////////////////////////////////////////////////////////////////// +*/ +struct Pk11Install_ListIter_str { + const Pk11Install_ValueList* list; + Pk11Install_Value* current; +}; + +Pk11Install_ListIter* +Pk11Install_ListIter_new_default(); +void +Pk11Install_ListIter_init(Pk11Install_ListIter* _this); +Pk11Install_ListIter* +Pk11Install_ListIter_new(const Pk11Install_ValueList* _list); +void +Pk11Install_ListIter_delete(Pk11Install_ListIter** _this); +void +Pk11Install_ListIter_reset(Pk11Install_ListIter* _this); +Pk11Install_Value* +Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this); + +/************************************************************************ + * + * Pk11Install_File + */ +struct Pk11Install_File_str { + char* jarPath; + char* relativePath; + char* absolutePath; + PRBool executable; + int permissions; +}; + +Pk11Install_File* +Pk11Install_File_new(); +void +Pk11Install_File_init(Pk11Install_File* _this); +void +Pk11Install_file_delete(Pk11Install_File* _this); +/*// Parses a syntax tree to obtain all attributes. +// Returns NULL for success, error message if parse error.*/ +char* +Pk11Install_File_Generate(Pk11Install_File* _this, + const Pk11Install_Pair* pair); +void +Pk11Install_File_Print(Pk11Install_File* _this, int pad); +void +Pk11Install_File_Cleanup(Pk11Install_File* _this); + +/************************************************************************ + * + * Pk11Install_PlatformName + */ +struct Pk11Install_PlatformName_str { + char* OS; + char** verString; + int numDigits; + char* arch; +}; + +Pk11Install_PlatformName* +Pk11Install_PlatformName_new(); +void +Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this); +void +Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this); +char* +Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this, + const char* str); +char* +Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this); +char* +Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this); +void +Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad); +void +Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this); +PRBool +Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp); +PRBool +Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp); +PRBool +Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this, + Pk11Install_PlatformName* cmp); + +/************************************************************************ + * + * Pk11Install_Platform + */ +struct Pk11Install_Platform_str { + Pk11Install_PlatformName name; + Pk11Install_PlatformName equivName; + struct Pk11Install_Platform_str* equiv; + PRBool usesEquiv; + char* moduleFile; + char* moduleName; + int modFile; + unsigned long mechFlags; + unsigned long cipherFlags; + Pk11Install_File* files; + int numFiles; +}; + +Pk11Install_Platform* +Pk11Install_Platform_new(); +void +Pk11Install_Platform_init(Pk11Install_Platform* _this); +void +Pk11Install_Platform_delete(Pk11Install_Platform* _this); +/*// Returns NULL for success, error message if parse error.*/ +char* +Pk11Install_Platform_Generate(Pk11Install_Platform* _this, + const Pk11Install_Pair* pair); +void +Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad); +void +Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this); + +/************************************************************************ + * + * Pk11Install_Info + */ +struct Pk11Install_Info_str { + Pk11Install_Platform* platforms; + int numPlatforms; + Pk11Install_PlatformName* forwardCompatible; + int numForwardCompatible; +}; + +Pk11Install_Info* +Pk11Install_Info_new(); +void +Pk11Install_Info_init(Pk11Install_Info* _this); +void +Pk11Install_Info_delete(Pk11Install_Info* _this); +/*// Returns NULL for success, error message if parse error.*/ +char* +Pk11Install_Info_Generate(Pk11Install_Info* _this, + const Pk11Install_ValueList* list); +/*// Returns NULL if there is no matching platform*/ +Pk11Install_Platform* +Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform); +void +Pk11Install_Info_Print(Pk11Install_Info* _this, int pad); +void +Pk11Install_Info_Cleanup(Pk11Install_Info* _this); + +#endif /* INSTALL_DS_H */ diff --git a/security/nss/cmd/modutil/install.c b/security/nss/cmd/modutil/install.c new file mode 100644 index 0000000000..91bcca928e --- /dev/null +++ b/security/nss/cmd/modutil/install.c @@ -0,0 +1,941 @@ +/* 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 "install.h" +#include "install-ds.h" +#include <prerror.h> +#include <prlock.h> +#include <prio.h> +#include <prmem.h> +#include <prprf.h> +#include <prsystem.h> +#include <prproces.h> + +#ifdef XP_UNIX +/* for chmod */ +#include <sys/types.h> +#include <sys/stat.h> +#endif + +/*extern "C" {*/ +#include <jar.h> +/*}*/ + +extern /*"C"*/ + int + Pk11Install_AddNewModule(char *moduleName, char *dllPath, + unsigned long defaultMechanismFlags, + unsigned long cipherEnableFlags); +extern /*"C"*/ + short + Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out, + PRBool query); +extern /*"C"*/ + const char * + mySECU_ErrorString(PRErrorCode errnum); +extern int Pk11Install_yyparse(); + +#define INSTALL_METAINFO_TAG "Pkcs11_install_script" +#define SCRIPT_TEMP_FILE "pkcs11inst.tmp" +#define ROOT_MARKER "%root%" +#define TEMP_MARKER "%temp%" +#define PRINTF_ROOT_MARKER "%%root%%" +#define TEMPORARY_DIRECTORY_NAME "pk11inst.dir" +#define JAR_BASE_END (JAR_BASE + 100) + +static PRLock *errorHandlerLock = NULL; +static Pk11Install_ErrorHandler errorHandler = NULL; +static char *PR_Strdup(const char *str); +static int rm_dash_r(char *path); +static int make_dirs(char *path, int file_perms); +static int dir_perms(int perms); + +static Pk11Install_Error DoInstall(JAR *jar, const char *installDir, + const char *tempDir, Pk11Install_Platform *platform, + PRFileDesc *feedback, PRBool noverify); + +static char *errorString[] = { + "Operation was successful", /* PK11_INSTALL_NO_ERROR */ + "Directory \"%s\" does not exist", /* PK11_INSTALL_DIR_DOESNT_EXIST */ + "File \"%s\" does not exist", /* PK11_INSTALL_FILE_DOESNT_EXIST */ + "File \"%s\" is not readable", /* PK11_INSTALL_FILE_NOT_READABLE */ + "%s", /* PK11_INSTALL_ERROR_STRING */ + "Error in JAR file %s: %s", /* PK11_INSTALL_JAR_ERROR */ + "No Pkcs11_install_script specified in JAR metainfo file", + /* PK11_INSTALL_NO_INSTALLER_SCRIPT */ + "Could not delete temporary file \"%s\"", + /*PK11_INSTALL_DELETE_TEMP_FILE */ + "Could not open temporary file \"%s\"", /*PK11_INSTALL_OPEN_SCRIPT_FILE*/ + "%s: %s", /* PK11_INSTALL_SCRIPT_PARSE */ + "Error in script: %s", + "Unable to obtain system platform information", + "Installer script has no information about the current platform (%s)", + "Relative directory \"%s\" does not contain " PRINTF_ROOT_MARKER, + "Module File \"%s\" not found", + "Error occurred installing module \"%s\" into database", + "Error extracting \"%s\" from JAR file: %s", + "Directory \"%s\" is not writeable", + "Could not create directory \"%s\"", + "Could not remove directory \"%s\"", + "Unable to execute \"%s\"", + "Unable to wait for process \"%s\"", + "\"%s\" returned error code %d", + "User aborted operation", + "Unspecified error" +}; + +enum { + INSTALLED_FILE_MSG = 0, + INSTALLED_MODULE_MSG, + INSTALLER_SCRIPT_NAME, + MY_PLATFORM_IS, + USING_PLATFORM, + PARSED_INSTALL_SCRIPT, + EXEC_FILE_MSG, + EXEC_SUCCESS, + INSTALLATION_COMPLETE_MSG, + USER_ABORT +}; + +static char *msgStrings[] = { + "Installed file %s to %s\n", + "Installed module \"%s\" into module database\n", + "Using installer script \"%s\"\n", + "Current platform is %s\n", + "Using installation parameters for platform %s\n", + "Successfully parsed installation script\n", + "Executing \"%s\"...\n", + "\"%s\" executed successfully\n", + "\nInstallation completed successfully\n", + "\nAborting...\n" +}; + +/************************************************************************** + * S t r i n g N o d e + */ +typedef struct StringNode_str { + char *str; + struct StringNode_str *next; +} StringNode; + +StringNode * +StringNode_new() +{ + StringNode *new_this; + new_this = (StringNode *)PR_Malloc(sizeof(StringNode)); + PORT_Assert(new_this != NULL); + new_this->str = NULL; + new_this->next = NULL; + return new_this; +} + +void +StringNode_delete(StringNode *s) +{ + if (s->str) { + PR_Free(s->str); + s->str = NULL; + } +} + +/************************************************************************* + * S t r i n g L i s t + */ +typedef struct StringList_str { + StringNode *head; + StringNode *tail; +} StringList; + +void +StringList_new(StringList *list) +{ + list->head = NULL; + list->tail = NULL; +} + +void +StringList_delete(StringList *list) +{ + StringNode *tmp; + while (list->head) { + tmp = list->head; + list->head = list->head->next; + StringNode_delete(tmp); + } +} + +void +StringList_Append(StringList *list, char *str) +{ + if (!str) { + return; + } + + if (!list->tail) { + /* This is the first element */ + list->head = list->tail = StringNode_new(); + } else { + list->tail->next = StringNode_new(); + list->tail = list->tail->next; + } + + list->tail->str = PR_Strdup(str); + list->tail->next = NULL; /* just to be sure */ +} + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r + * + * Sets the error handler to be used by the library. Returns the current + * error handler function. + */ +Pk11Install_ErrorHandler +Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler) +{ + Pk11Install_ErrorHandler old; + + if (!errorHandlerLock) { + errorHandlerLock = PR_NewLock(); + } + + PR_Lock(errorHandlerLock); + + old = errorHandler; + errorHandler = handler; + + PR_Unlock(errorHandlerLock); + + return old; +} + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ I n i t + * + * Does initialization that otherwise would be done on the fly. Only + * needs to be called by multithreaded apps, before they make any calls + * to this library. + */ +void +Pk11Install_Init() +{ + if (!errorHandlerLock) { + errorHandlerLock = PR_NewLock(); + } +} + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ R e l e a s e + * + * Releases static data structures used by the library. Don't use the + * library after calling this, unless you call Pk11Install_Init() + * first. This function doesn't have to be called at all unless you're + * really anal about freeing memory before your program exits. + */ +void +Pk11Install_Release() +{ + if (errorHandlerLock) { + PR_Free(errorHandlerLock); + errorHandlerLock = NULL; + } +} + +/************************************************************************* + * + * e r r o r + * + * Takes an error code and its arguments, creates the error string, + * and sends the string to the handler function if it exists. + */ + +#include <stdarg.h> + +static void +error(PRErrorCode errcode, ...) +{ + + va_list ap; + char *errstr; + Pk11Install_ErrorHandler handler; + + if (!errorHandlerLock) { + errorHandlerLock = PR_NewLock(); + } + + PR_Lock(errorHandlerLock); + + handler = errorHandler; + + PR_Unlock(errorHandlerLock); + + if (handler) { + va_start(ap, errcode); + errstr = PR_vsmprintf(errorString[errcode], ap); + handler(errstr); + PR_smprintf_free(errstr); + va_end(ap); + } +} + +/************************************************************************* + * + * j a r _ c a l l b a c k + */ +static int +jar_callback(int status, JAR *foo, const char *bar, char *pathname, + char *errortext) +{ + char *string; + + string = PR_smprintf("JAR error %d: %s in file %s\n", status, errortext, + pathname); + error(PK11_INSTALL_ERROR_STRING, string); + PR_smprintf_free(string); + return 0; +} + +/************************************************************************* + * + * P k 1 1 I n s t a l l _ D o I n s t a l l + * + * jarFile is the path of a JAR in the PKCS #11 module JAR format. + * installDir is the directory relative to which files will be + * installed. + */ +Pk11Install_Error +Pk11Install_DoInstall(char *jarFile, const char *installDir, + const char *tempDir, PRFileDesc *feedback, short force, PRBool noverify) +{ + JAR *jar; + char *installer; + unsigned long installer_len; + int status; + Pk11Install_Error ret; + PRBool made_temp_file; + Pk11Install_Info installInfo; + Pk11Install_Platform *platform; + char *errMsg; + char sysname[SYS_INFO_BUFFER_LENGTH], release[SYS_INFO_BUFFER_LENGTH], + arch[SYS_INFO_BUFFER_LENGTH]; + char *myPlatform; + + jar = NULL; + ret = PK11_INSTALL_UNSPECIFIED; + made_temp_file = PR_FALSE; + errMsg = NULL; + Pk11Install_Info_init(&installInfo); + + /* + printf("Inside DoInstall, jarFile=%s, installDir=%s, tempDir=%s\n", + jarFile, installDir, tempDir); + */ + + /* + * Check out jarFile and installDir for validity + */ + if (PR_Access(installDir, PR_ACCESS_EXISTS) != PR_SUCCESS) { + error(PK11_INSTALL_DIR_DOESNT_EXIST, installDir); + return PK11_INSTALL_DIR_DOESNT_EXIST; + } + if (!tempDir) { + tempDir = "."; + } + if (PR_Access(tempDir, PR_ACCESS_EXISTS) != PR_SUCCESS) { + error(PK11_INSTALL_DIR_DOESNT_EXIST, tempDir); + return PK11_INSTALL_DIR_DOESNT_EXIST; + } + if (PR_Access(tempDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { + error(PK11_INSTALL_DIR_NOT_WRITEABLE, tempDir); + return PK11_INSTALL_DIR_NOT_WRITEABLE; + } + if ((PR_Access(jarFile, PR_ACCESS_EXISTS) != PR_SUCCESS)) { + error(PK11_INSTALL_FILE_DOESNT_EXIST, jarFile); + return PK11_INSTALL_FILE_DOESNT_EXIST; + } + if (PR_Access(jarFile, PR_ACCESS_READ_OK) != PR_SUCCESS) { + error(PK11_INSTALL_FILE_NOT_READABLE, jarFile); + return PK11_INSTALL_FILE_NOT_READABLE; + } + + /* + * Extract the JAR file + */ + jar = JAR_new(); + JAR_set_callback(JAR_CB_SIGNAL, jar, jar_callback); + + if (noverify) { + status = JAR_pass_archive_unverified(jar, jarArchGuess, jarFile, "url"); + } else { + status = JAR_pass_archive(jar, jarArchGuess, jarFile, "url"); + } + if ((status < 0) || (jar->valid < 0)) { + if (status >= JAR_BASE && status <= JAR_BASE_END) { + error(PK11_INSTALL_JAR_ERROR, jarFile, JAR_get_error(status)); + } else { + error(PK11_INSTALL_JAR_ERROR, jarFile, + mySECU_ErrorString(PORT_GetError())); + } + ret = PK11_INSTALL_JAR_ERROR; + goto loser; + } + /*printf("passed the archive\n");*/ + + /* + * Show the user security information, allow them to abort or continue + */ + if (Pk11Install_UserVerifyJar(jar, PR_STDOUT, + force ? PR_FALSE + : PR_TRUE) && + !force) { + if (feedback) { + PR_fprintf(feedback, msgStrings[USER_ABORT]); + } + ret = PK11_INSTALL_USER_ABORT; + goto loser; + } + + /* + * Get the name of the installation file + */ + if (JAR_get_metainfo(jar, NULL, INSTALL_METAINFO_TAG, (void **)&installer, + (unsigned long *)&installer_len)) { + error(PK11_INSTALL_NO_INSTALLER_SCRIPT); + ret = PK11_INSTALL_NO_INSTALLER_SCRIPT; + goto loser; + } + if (feedback) { + PR_fprintf(feedback, msgStrings[INSTALLER_SCRIPT_NAME], installer); + } + + /* + * Extract the installation file + */ + if (PR_Access(SCRIPT_TEMP_FILE, PR_ACCESS_EXISTS) == PR_SUCCESS) { + if (PR_Delete(SCRIPT_TEMP_FILE) != PR_SUCCESS) { + error(PK11_INSTALL_DELETE_TEMP_FILE, SCRIPT_TEMP_FILE); + ret = PK11_INSTALL_DELETE_TEMP_FILE; + goto loser; + } + } + if (noverify) { + status = JAR_extract(jar, installer, SCRIPT_TEMP_FILE); + } else { + status = JAR_verified_extract(jar, installer, SCRIPT_TEMP_FILE); + } + if (status) { + if (status >= JAR_BASE && status <= JAR_BASE_END) { + error(PK11_INSTALL_JAR_EXTRACT, installer, JAR_get_error(status)); + } else { + error(PK11_INSTALL_JAR_EXTRACT, installer, + mySECU_ErrorString(PORT_GetError())); + } + ret = PK11_INSTALL_JAR_EXTRACT; + goto loser; + } else { + made_temp_file = PR_TRUE; + } + + /* + * Parse the installation file into a syntax tree + */ + Pk11Install_FD = PR_Open(SCRIPT_TEMP_FILE, PR_RDONLY, 0); + if (!Pk11Install_FD) { + error(PK11_INSTALL_OPEN_SCRIPT_FILE, SCRIPT_TEMP_FILE); + ret = PK11_INSTALL_OPEN_SCRIPT_FILE; + goto loser; + } + if (Pk11Install_yyparse()) { + error(PK11_INSTALL_SCRIPT_PARSE, installer, + Pk11Install_yyerrstr ? Pk11Install_yyerrstr : ""); + ret = PK11_INSTALL_SCRIPT_PARSE; + goto loser; + } + +#if 0 + /* for debugging */ + Pk11Install_valueList->Print(0); +#endif + + /* + * From the syntax tree, build a semantic structure + */ + errMsg = Pk11Install_Info_Generate(&installInfo, Pk11Install_valueList); + if (errMsg) { + error(PK11_INSTALL_SEMANTIC, errMsg); + ret = PK11_INSTALL_SEMANTIC; + goto loser; + } +#if 0 + installInfo.Print(0); +#endif + + if (feedback) { + PR_fprintf(feedback, msgStrings[PARSED_INSTALL_SCRIPT]); + } + + /* + * Figure out which platform to use + */ + { + sysname[0] = release[0] = arch[0] = '\0'; + + if ((PR_GetSystemInfo(PR_SI_SYSNAME, sysname, SYS_INFO_BUFFER_LENGTH) != + PR_SUCCESS) || + (PR_GetSystemInfo(PR_SI_RELEASE, release, SYS_INFO_BUFFER_LENGTH) != + PR_SUCCESS) || + (PR_GetSystemInfo(PR_SI_ARCHITECTURE, arch, SYS_INFO_BUFFER_LENGTH) != + PR_SUCCESS)) { + error(PK11_INSTALL_SYSINFO); + ret = PK11_INSTALL_SYSINFO; + goto loser; + } + myPlatform = PR_smprintf("%s:%s:%s", sysname, release, arch); + platform = Pk11Install_Info_GetBestPlatform(&installInfo, myPlatform); + if (!platform) { + error(PK11_INSTALL_NO_PLATFORM, myPlatform); + PR_smprintf_free(myPlatform); + ret = PK11_INSTALL_NO_PLATFORM; + goto loser; + } + if (feedback) { + PR_fprintf(feedback, msgStrings[MY_PLATFORM_IS], myPlatform); + PR_fprintf(feedback, msgStrings[USING_PLATFORM], + Pk11Install_PlatformName_GetString(&platform->name)); + } + PR_smprintf_free(myPlatform); + } + + /* Run the install for that platform */ + ret = DoInstall(jar, installDir, tempDir, platform, feedback, noverify); + if (ret) { + goto loser; + } + + ret = PK11_INSTALL_SUCCESS; +loser: + if (Pk11Install_valueList) { + Pk11Install_ValueList_delete(Pk11Install_valueList); + Pk11Install_valueList = NULL; + } + if (jar) { + JAR_destroy(jar); + } + if (made_temp_file) { + PR_Delete(SCRIPT_TEMP_FILE); + } + if (errMsg) { + PR_smprintf_free(errMsg); + } + return ret; +} + +/* +///////////////////////////////////////////////////////////////////////// +// actually run the installation, copying files to and fro +*/ +static Pk11Install_Error +DoInstall(JAR *jar, const char *installDir, const char *tempDir, + Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify) +{ + Pk11Install_File *file; + Pk11Install_Error ret; + char *modDest; + char *cp; + int i; + int status; + char *tempname, *temp; + StringList executables; + StringNode *execNode; + PRProcessAttr *attr; + PRProcess *proc; + char *argv[2]; + char *envp[1]; + int errcode; + + ret = PK11_INSTALL_UNSPECIFIED; + modDest = NULL; + tempname = NULL; + + StringList_new(&executables); + /* + // Create Temporary directory + */ + tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME); + if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) { + /* Left over from previous run? Delete it. */ + rm_dash_r(tempname); + } + if (PR_MkDir(tempname, 0700) != PR_SUCCESS) { + error(PK11_INSTALL_CREATE_DIR, tempname); + ret = PK11_INSTALL_CREATE_DIR; + goto loser; + } + + /* + // Install all the files + */ + for (i = 0; i < platform->numFiles; i++) { + char *dest; + file = &platform->files[i]; + + if (file->relativePath) { + PRBool foundMarker = PR_FALSE; + char *reldir = PR_Strdup(file->relativePath); + + if (!reldir) { + error(PK11_INSTALL_UNSPECIFIED); + goto loser; + } + + /* Replace all the markers with the directories for which they stand */ + while (1) { + if ((cp = PL_strcasestr(reldir, ROOT_MARKER))) { + /* Has a %root% marker */ + *cp = '\0'; + temp = PR_smprintf("%s%s%s", reldir, installDir, + cp + strlen(ROOT_MARKER)); + PR_Free(reldir); + reldir = temp; + foundMarker = PR_TRUE; + } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER))) { + /* Has a %temp% marker */ + *cp = '\0'; + temp = PR_smprintf("%s%s%s", reldir, tempname, + cp + strlen(TEMP_MARKER)); + PR_Free(reldir); + reldir = temp; + foundMarker = PR_TRUE; + } else { + break; + } + } + if (!foundMarker) { + /* Has no markers...this isn't really a relative directory */ + error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath); + ret = PK11_INSTALL_BOGUS_REL_DIR; + PR_Free(reldir); + goto loser; + } + dest = reldir; + } else if (file->absolutePath) { + dest = PR_Strdup(file->absolutePath); + } else { + error(PK11_INSTALL_UNSPECIFIED); + goto loser; + } + + /* Remember if this is the module file, we'll need to add it later */ + if (i == platform->modFile) { + modDest = PR_Strdup(dest); + } + + /* Remember is this is an executable, we'll need to run it later */ + if (file->executable) { + StringList_Append(&executables, dest); + /*executables.Append(dest);*/ + } + + /* Make sure the directory we are targetting exists */ + if (make_dirs(dest, file->permissions)) { + ret = PK11_INSTALL_CREATE_DIR; + goto loser; + } + + /* Actually extract the file onto the filesystem */ + if (noverify) { + status = JAR_extract(jar, (char *)file->jarPath, dest); + } else { + status = JAR_verified_extract(jar, (char *)file->jarPath, dest); + } + if (status) { + if (status >= JAR_BASE && status <= JAR_BASE_END) { + error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, + JAR_get_error(status)); + } else { + error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, + mySECU_ErrorString(PORT_GetError())); + } + ret = PK11_INSTALL_JAR_EXTRACT; + goto loser; + } + if (feedback) { + PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG], + file->jarPath, dest); + } + +/* no NSPR command to change permissions? */ +#ifdef XP_UNIX + (void)chmod(dest, file->permissions); +#endif + + PR_Free(dest); + } + /* Make sure we found the module file */ + if (!modDest) { + /* Internal problem here, since every platform is supposed to have + a module file */ + error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName); + ret = PK11_INSTALL_NO_MOD_FILE; + goto loser; + } + + /* + // Execute any executable files + */ + { + argv[1] = NULL; + envp[0] = NULL; + for (execNode = executables.head; execNode; execNode = execNode->next) { + attr = PR_NewProcessAttr(); + argv[0] = PR_Strdup(execNode->str); + + /* Announce our intentions */ + if (feedback) { + PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str); + } + + /* start the process */ + if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) { + PR_Free(argv[0]); + PR_DestroyProcessAttr(attr); + error(PK11_INSTALL_EXEC_FILE, execNode->str); + ret = PK11_INSTALL_EXEC_FILE; + goto loser; + } + + /* wait for it to finish */ + if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) { + PR_Free(argv[0]); + PR_DestroyProcessAttr(attr); + error(PK11_INSTALL_WAIT_PROCESS, execNode->str); + ret = PK11_INSTALL_WAIT_PROCESS; + goto loser; + } + + /* What happened? */ + if (errcode) { + /* process returned an error */ + error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode); + } else if (feedback) { + /* process ran successfully */ + PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str); + } + + PR_Free(argv[0]); + PR_DestroyProcessAttr(attr); + } + } + + /* + // Add the module + */ + status = Pk11Install_AddNewModule((char *)platform->moduleName, + (char *)modDest, platform->mechFlags, platform->cipherFlags); + + if (status != SECSuccess) { + error(PK11_INSTALL_ADD_MODULE, platform->moduleName); + ret = PK11_INSTALL_ADD_MODULE; + goto loser; + } + if (feedback) { + PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG], + platform->moduleName); + } + + if (feedback) { + PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]); + } + + ret = PK11_INSTALL_SUCCESS; + +loser: + if (modDest) { + PR_Free(modDest); + } + if (tempname) { + PRFileInfo info; + if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) { + if (info.type == PR_FILE_DIRECTORY) { + /* Recursively remove temporary directory */ + if (rm_dash_r(tempname)) { + error(PK11_INSTALL_REMOVE_DIR, + tempname); + ret = PK11_INSTALL_REMOVE_DIR; + } + } + } + PR_Free(tempname); + } + StringList_delete(&executables); + return ret; +} + +/* +////////////////////////////////////////////////////////////////////////// +*/ +static char * +PR_Strdup(const char *str) +{ + char *tmp = (char *)PR_Malloc(strlen(str) + 1); + strcpy(tmp, str); + return tmp; +} + +/* + * r m _ d a s h _ r + * + * Remove a file, or a directory recursively. + * + */ +static int +rm_dash_r(char *path) +{ + PRDir *dir; + PRDirEntry *entry; + PRFileInfo fileinfo; + char filename[240]; + + 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) { + return -1; + } + + /* Recursively delete all entries in the directory */ + while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) { + snprintf(filename, sizeof(filename), "%s/%s", path, entry->name); + if (rm_dash_r(filename)) { + PR_CloseDir(dir); + return -1; + } + } + + if (PR_CloseDir(dir) != PR_SUCCESS) { + return -1; + } + + /* Delete the directory itself */ + if (PR_RmDir(path) != PR_SUCCESS) { + return -1; + } + } else { + if (PR_Delete(path) != PR_SUCCESS) { + return -1; + } + } + return 0; +} + +/*************************************************************************** + * + * m a k e _ d i r s + * + * Ensure that the directory portion of the path exists. This may require + * making the directory, and its parent, and its parent's parent, etc. + */ +static int +make_dirs(char *path, int file_perms) +{ + char *Path; + char *start; + char *sep; + int ret = 0; + PRFileInfo info; + + if (!path) { + return 0; + } + + Path = PR_Strdup(path); + start = strpbrk(Path, "/\\"); + if (!start) { + return 0; + } + start++; /* start right after first slash */ + + /* Each time through the loop add one more directory. */ + while ((sep = strpbrk(start, "/\\"))) { + *sep = '\0'; + + if (PR_GetFileInfo(Path, &info) != PR_SUCCESS) { + /* No such dir, we have to create it */ + if (PR_MkDir(Path, dir_perms(file_perms)) != PR_SUCCESS) { + error(PK11_INSTALL_CREATE_DIR, Path); + ret = PK11_INSTALL_CREATE_DIR; + goto loser; + } + } else { + /* something exists by this name, make sure it's a directory */ + if (info.type != PR_FILE_DIRECTORY) { + error(PK11_INSTALL_CREATE_DIR, Path); + ret = PK11_INSTALL_CREATE_DIR; + goto loser; + } + } + + /* If this is the lowest directory level, make sure it is writeable */ + if (!strpbrk(sep + 1, "/\\")) { + if (PR_Access(Path, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { + error(PK11_INSTALL_DIR_NOT_WRITEABLE, Path); + ret = PK11_INSTALL_DIR_NOT_WRITEABLE; + goto loser; + } + } + + start = sep + 1; /* start after the next slash */ + *sep = '/'; + } + +loser: + PR_Free(Path); + return ret; +} + +/************************************************************************* + * d i r _ p e r m s + * + * Guesses the desired permissions on a directory based on the permissions + * of a file that will be stored in it. Give read, write, and + * execute to the owner (so we can create the file), read and + * execute to anyone who has read permissions on the file, and write + * to anyone who has write permissions on the file. + */ +static int +dir_perms(int perms) +{ + int ret = 0; + + /* owner */ + ret |= 0700; + + /* group */ + if (perms & 0040) { + /* read on the file -> read and execute on the directory */ + ret |= 0050; + } + if (perms & 0020) { + /* write on the file -> write on the directory */ + ret |= 0020; + } + + /* others */ + if (perms & 0004) { + /* read on the file -> read and execute on the directory */ + ret |= 0005; + } + if (perms & 0002) { + /* write on the file -> write on the directory */ + ret |= 0002; + } + + return ret; +} diff --git a/security/nss/cmd/modutil/install.h b/security/nss/cmd/modutil/install.h new file mode 100644 index 0000000000..5d6d3eabaa --- /dev/null +++ b/security/nss/cmd/modutil/install.h @@ -0,0 +1,100 @@ +/* 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/. */ + +#ifndef PK11INSTALL_H +#define PK11INSTALL_H + +#include <prio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*Pk11Install_ErrorHandler)(char *); + +typedef enum { + PK11_INSTALL_NO_ERROR = 0, + PK11_INSTALL_DIR_DOESNT_EXIST, + PK11_INSTALL_FILE_DOESNT_EXIST, + PK11_INSTALL_FILE_NOT_READABLE, + PK11_INSTALL_ERROR_STRING, + PK11_INSTALL_JAR_ERROR, + PK11_INSTALL_NO_INSTALLER_SCRIPT, + PK11_INSTALL_DELETE_TEMP_FILE, + PK11_INSTALL_OPEN_SCRIPT_FILE, + PK11_INSTALL_SCRIPT_PARSE, + PK11_INSTALL_SEMANTIC, + PK11_INSTALL_SYSINFO, + PK11_INSTALL_NO_PLATFORM, + PK11_INSTALL_BOGUS_REL_DIR, + PK11_INSTALL_NO_MOD_FILE, + PK11_INSTALL_ADD_MODULE, + PK11_INSTALL_JAR_EXTRACT, + PK11_INSTALL_DIR_NOT_WRITEABLE, + PK11_INSTALL_CREATE_DIR, + PK11_INSTALL_REMOVE_DIR, + PK11_INSTALL_EXEC_FILE, + PK11_INSTALL_WAIT_PROCESS, + PK11_INSTALL_PROC_ERROR, + PK11_INSTALL_USER_ABORT, + PK11_INSTALL_UNSPECIFIED +} Pk11Install_Error; +#define PK11_INSTALL_SUCCESS PK11_INSTALL_NO_ERROR + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ I n i t + * + * Does initialization that otherwise would be done on the fly. Only + * needs to be called by multithreaded apps, before they make any calls + * to this library. + */ +void +Pk11Install_Init(); + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r + * + * Sets the error handler to be used by the library. Returns the current + * error handler function. + */ +Pk11Install_ErrorHandler +Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler); + +/************************************************************************** + * + * P k 1 1 I n s t a l l _ R e l e a s e + * + * Releases static data structures used by the library. Don't use the + * library after calling this, unless you call Pk11Install_Init() + * first. This function doesn't have to be called at all unless you're + * really anal about freeing memory before your program exits. + */ +void +Pk11Install_Release(); + +/************************************************************************* + * + * P k 1 1 I n s t a l l _ D o I n s t a l l + * + * jarFile is the path of a JAR in the PKCS #11 module JAR format. + * installDir is the directory relative to which files will be + * installed. + * feedback is a file descriptor to which to write informative (not error) + * status messages: what files are being installed, what modules are being + * installed. If feedback==NULL, no messages will be displayed. + * If force != 0, interactive prompts will be suppressed. + * If noverify == PR_TRUE, signatures won't be checked on the JAR file. + */ +Pk11Install_Error +Pk11Install_DoInstall(char *jarFile, const char *installDir, + const char *tempDir, PRFileDesc *feedback, short force, + PRBool noverify); + +#ifdef __cplusplus +} +#endif + +#endif /*PK11INSTALL_H*/ diff --git a/security/nss/cmd/modutil/installparse.c b/security/nss/cmd/modutil/installparse.c new file mode 100644 index 0000000000..1d8e6cc473 --- /dev/null +++ b/security/nss/cmd/modutil/installparse.c @@ -0,0 +1,479 @@ +/* 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/. */ + +#ifndef lint +char yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90"; +#endif +#line 37 "installparse.y" + +#define yyparse Pk11Install_yyparse +#define yylex Pk11Install_yylex +#define yyerror Pk11Install_yyerror +#define yychar Pk11Install_yychar +#define yyval Pk11Install_yyval +#define yylval Pk11Install_yylval +#define yydebug Pk11Install_yydebug +#define yynerrs Pk11Install_yynerrs +#define yyerrflag Pk11Install_yyerrflag +#define yyss Pk11Install_yyss +#define yyssp Pk11Install_yyssp +#define yyvs Pk11Install_yyvs +#define yyvsp Pk11Install_yyvsp +#define yylhs Pk11Install_yylhs +#define yylen Pk11Install_yylen +#define yydefred Pk11Install_yydefred +#define yydgoto Pk11Install_yydgoto +#define yysindex Pk11Install_yysindex +#define yyrindex Pk11Install_yyrindex +#define yygindex Pk11Install_yygindex +#define yytable Pk11Install_yytable +#define yycheck Pk11Install_yycheck +#define yyname Pk11Install_yyname +#define yyrule Pk11Install_yyrule + +/* C Stuff */ +#include "install-ds.h" +#include <prprf.h> + +#define YYSTYPE Pk11Install_Pointer +extern char *Pk11Install_yytext; +char *Pk11Install_yyerrstr = NULL; + +#line 40 "ytab.c" +#define OPENBRACE 257 +#define CLOSEBRACE 258 +#define STRING 259 +#define YYERRCODE 256 +/* clang-format on */ +short yylhs[] = { + -1, + 0, + 1, + 1, + 2, + 2, + 3, + 4 +}; +short yylen[] = { + 2, + 1, + 2, + 0, + 1, + 1, + 4, + 1 +}; +short yydefred[] = { + 0, + 0, + 0, + 1, + 0, + 4, + 0, + 2, + 0, + 0, + 6 +}; +short yydgoto[] = { + 2, + 3, + 4, + 5, + 6 +}; +short yysindex[] = { + -257, + 0, + 0, + 0, + -257, + 0, + -252, + 0, + -257, + -251, + 0 +}; +short yyrindex[] = { + 6, + 1, + 0, + 0, + 3, + 0, + 0, + 0, + -250, + 0, + 0 +}; +short yygindex[] = { + 0, + -4, + 0, + 0, + 0 +}; +#define YYTABLESIZE 261 +short yytable[] = { + 7, + 5, 1, 3, 9, 8, 3, 10, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 5, 5, + 3 +}; +short yycheck[] = { + 4, + 0, 259, 0, 8, 257, 0, 258, 258, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 257, 258, 259, + 258 +}; +/* clang-format on */ +#define YYFINAL 2 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 259 +#if YYDEBUG +char *yyname[] = { + "end-of-file", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "OPENBRACE", "CLOSEBRACE", "STRING" +}; +char *yyrule[] = { + "$accept : toplist", + "toplist : valuelist", + "valuelist : value valuelist", + "valuelist :", + "value : key_value_pair", + "value : STRING", + "key_value_pair : key OPENBRACE valuelist CLOSEBRACE", + "key : STRING", +}; +#endif +#ifndef YYSTYPE +typedef int YYSTYPE; +#endif +#define yyclearin (yychar = (-1)) +#define yyerrok (yyerrflag = 0) +#ifndef YYSTACKSIZE +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 300 +#endif +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +#define yystacksize YYSTACKSIZE +short yyss[YYSTACKSIZE]; +YYSTYPE yyvs[YYSTACKSIZE]; +#line 118 "installparse.y" +/*----------------------- Program Section --------------------------------*/ + +/*************************************************************************/ +void +Pk11Install_yyerror(char *message) +{ + char *tmp; + if (Pk11Install_yyerrstr) { + tmp = PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr, + Pk11Install_yylinenum, message); + PR_smprintf_free(Pk11Install_yyerrstr); + } else { + tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message); + } + Pk11Install_yyerrstr = tmp; +} +#line 191 "ytab.c" +#define YYABORT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +yyparse() +{ + register int yym, yyn, yystate; +#if YYDEBUG + register char *yys; + extern char *PR_GetEnvSecure(); + + if ((yys = PR_GetEnvSecure("YYDEBUG")) != NULL) { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if ((yyn = yydefred[yystate]) != 0) + goto yyreduce; + if (yychar < 0) { + if ((yychar = yylex()) < 0) + yychar = 0; +#if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) + yys = yyname[yychar]; + if (!yys) + yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", yystate, + yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, shifting to state %d\n", + yystate, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) + --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) + goto yyinrecovery; +#ifdef lint + goto yynewerror; +yynewerror: +#endif + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +yyerrlab: +#endif + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) { + yyerrflag = 3; + for (;;) { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, error recovery shifting\ + to state %d\n", + *yyssp, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } else { +#if YYDEBUG + if (yydebug) + printf("yydebug: error recovery discarding state %d\n", + *yyssp); +#endif + if (yyssp <= yyss) + goto yyabort; + --yyssp; + --yyvsp; + } + } + } else { + if (yychar == 0) + goto yyabort; +#if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) + yys = yyname[yychar]; + if (!yys) + yys = "illegal-symbol"; + printf("yydebug: state %d, error recovery discards token %d (%s)\n", + yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, reducing by rule %d (%s)\n", + yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1 - yym]; + switch (yyn) { + case 1: +#line 84 "installparse.y" + { + Pk11Install_valueList = yyvsp[0].list; + } break; + case 2: +#line 89 "installparse.y" + { + Pk11Install_ValueList_AddItem(yyvsp[0].list, yyvsp[-1].value); + yyval.list = yyvsp[0].list; + } break; + case 3: +#line 94 "installparse.y" + { + yyval.list = Pk11Install_ValueList_new(); + } break; + case 4: +#line 99 "installparse.y" + { + yyval.value = Pk11Install_Value_new(PAIR_VALUE, yyvsp[0]); + } break; + case 5: +#line 103 "installparse.y" + { + yyval.value = Pk11Install_Value_new(STRING_VALUE, yyvsp[0]); + } break; + case 6: +#line 108 "installparse.y" + { + yyval.pair = Pk11Install_Pair_new(yyvsp[-3].string, yyvsp[-1].list); + } break; + case 7: +#line 113 "installparse.y" + { + yyval.string = yyvsp[0].string; + } break; +#line 374 "ytab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) { +#ifdef YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state 0 to\ + state %d\n", + YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) { + if ((yychar = yylex()) < 0) + yychar = 0; +#if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) + yys = yyname[yychar]; + if (!yys) + yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", + YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) + goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#ifdef YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state %d \ +to state %d\n", + *yyssp, yystate); +#endif + if (yyssp >= yyss + yystacksize - 1) { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/security/nss/cmd/modutil/installparse.h b/security/nss/cmd/modutil/installparse.h new file mode 100644 index 0000000000..2c02b57b65 --- /dev/null +++ b/security/nss/cmd/modutil/installparse.h @@ -0,0 +1,7 @@ +/* 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/. */ + +#define OPENBRACE 257 +#define CLOSEBRACE 258 +#define STRING 259 diff --git a/security/nss/cmd/modutil/installparse.l b/security/nss/cmd/modutil/installparse.l new file mode 100644 index 0000000000..71fb56101d --- /dev/null +++ b/security/nss/cmd/modutil/installparse.l @@ -0,0 +1,137 @@ +/* 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/. */ + + +/* lex file for analyzing PKCS #11 Module installation instructions */ + +/*----------------------------- Definitions ---------------------------*/ +%{ +#include <string.h> + +#include "install-ds.h" /* defines tokens and data structures */ +#include "installparse.h" /* produced by yacc -d */ +#include <prprf.h> +static char *putSimpleString(char*); /* return copy of string */ +static char *putComplexString(char*); /* strip out quotes, deal with */ + /* escaped characters */ + +void Pk11Install_yyerror(char *); + +/* Overrides to use NSPR */ +#define malloc PR_Malloc +#define realloc PR_Realloc +#define free PR_Free + +int Pk11Install_yylinenum=1; +static char *err; + +#define YY_NEVER_INTERACTIVE 1 +#define yyunput Pkcs11Install_yyunput + +/* This is the default YY_INPUT modified for NSPR */ +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) { \ + char c; \ + int n; \ + for ( n = 0; n < max_size && \ + PR_Read(Pk11Install_FD, &c, 1)==1 && c != '\n'; ++n ) { \ + buf[n] = c; \ + } \ + if ( c == '\n' ) { \ + buf[n++] = c; \ + } \ + result = n; \ + } else { \ + result = PR_Read(Pk11Install_FD, buf, max_size); \ + } + +%} + +/*** Regular expression definitions ***/ +/* simple_string has no whitespace, quotes, or braces */ +simple_string [^ \t\r\n\""{""}"]+ + +/* complex_string is enclosed in quotes. Inside the quotes, quotes and + backslashes must be backslash-escaped. No newlines or carriage returns + are allowed inside the quotes. Otherwise, anything goes. */ +complex_string \"([^\"\\\r\n]|(\\\")|(\\\\))+\" + +/* Standard whitespace */ +whitespace [ \t\r]+ + +other . + +/*---------------------------- Actions --------------------------------*/ +%% + +"{" return OPENBRACE; +"}" return CLOSEBRACE; +{simple_string} {Pk11Install_yylval.string = + putSimpleString(Pk11Install_yytext); + return STRING;} +{complex_string} {Pk11Install_yylval.string = + putComplexString(Pk11Install_yytext); + return STRING;} + +"\n" Pk11Install_yylinenum++; + +{whitespace} ; + +{other} {err = PR_smprintf("Invalid lexeme: %s",Pk11Install_yytext); + Pk11Install_yyerror(err); + PR_smprintf_free(err); + return 1; + } + +%% +/*------------------------ Program Section ----------------------------*/ + +PRFileDesc *Pk11Install_FD=NULL; + +/*************************************************************************/ +/* dummy function required by lex */ +int Pk11Install_yywrap(void) { return 1;} + +/*************************************************************************/ +/* Return a copy of the given string */ +static char* +putSimpleString(char *str) +{ + char *tmp = (char*) PR_Malloc(strlen(str)+1); + strcpy(tmp, str); + return tmp; +} + +/*************************************************************************/ +/* Strip out quotes, replace escaped characters with what they stand for. + This function assumes that what is passed in is actually a complex + string, so error checking is lax. */ +static char* +putComplexString(char *str) +{ + int size, i,j; + char *tmp; + + if(!str) { + return NULL; + } + size = strlen(str); + + /* Allocate the new space. This string will actually be too big, + since quotes and backslashes will be stripped out. But that's ok. */ + tmp = (char*) PR_Malloc(size+1); + + /* Copy it over */ + for(i=0, j=0; i < size; i++) { + if(str[i]=='\"') { + continue; /* skip un-escaped quotes */ + } else if(str[i]=='\\') { + ++i; /* escaped character. skip the backslash */ + } + tmp[j++] = str[i]; + } + tmp[j] = '\0'; + + return tmp; +} diff --git a/security/nss/cmd/modutil/installparse.y b/security/nss/cmd/modutil/installparse.y new file mode 100644 index 0000000000..b6d701136a --- /dev/null +++ b/security/nss/cmd/modutil/installparse.y @@ -0,0 +1,104 @@ +/* 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/. */ + +/* yacc file for parsing PKCS #11 module installation instructions */ +/*------------------------ Definition Section ---------------------------*/ + +%{ +#define yyparse Pk11Install_yyparse +#define yylex Pk11Install_yylex +#define yyerror Pk11Install_yyerror +#define yychar Pk11Install_yychar +#define yyval Pk11Install_yyval +#define yylval Pk11Install_yylval +#define yydebug Pk11Install_yydebug +#define yynerrs Pk11Install_yynerrs +#define yyerrflag Pk11Install_yyerrflag +#define yyss Pk11Install_yyss +#define yyssp Pk11Install_yyssp +#define yyvs Pk11Install_yyvs +#define yyvsp Pk11Install_yyvsp +#define yylhs Pk11Install_yylhs +#define yylen Pk11Install_yylen +#define yydefred Pk11Install_yydefred +#define yydgoto Pk11Install_yydgoto +#define yysindex Pk11Install_yysindex +#define yyrindex Pk11Install_yyrindex +#define yygindex Pk11Install_yygindex +#define yytable Pk11Install_yytable +#define yycheck Pk11Install_yycheck +#define yyname Pk11Install_yyname +#define yyrule Pk11Install_yyrule + +/* C Stuff */ +#include "install-ds.h" +#include <prprf.h> + +#define YYSTYPE Pk11Install_Pointer +extern char *Pk11Install_yytext; +char *Pk11Install_yyerrstr=NULL; + +%} + +/* Tokens */ +%token OPENBRACE +%token CLOSEBRACE +%token STRING +%start toplist + +%% + +/*--------------------------- Productions -------------------------------*/ + +toplist : valuelist +{ + Pk11Install_valueList = $1.list; +} + +valuelist : value valuelist +{ + Pk11Install_ValueList_AddItem($2.list,$1.value); + $$.list = $2.list; +} +| +{ + $$.list = Pk11Install_ValueList_new(); +}; + +value : key_value_pair +{ + $$.value= Pk11Install_Value_new(PAIR_VALUE,$1); +} +| STRING +{ + $$.value= Pk11Install_Value_new(STRING_VALUE, $1); +}; + +key_value_pair : key OPENBRACE valuelist CLOSEBRACE +{ + $$.pair = Pk11Install_Pair_new($1.string,$3.list); +}; + +key : STRING +{ + $$.string = $1.string; +}; + +%% +/*----------------------- Program Section --------------------------------*/ + +/*************************************************************************/ +void +Pk11Install_yyerror(char *message) +{ + char *tmp; + if(Pk11Install_yyerrstr) { + tmp=PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr, + Pk11Install_yylinenum, message); + PR_smprintf_free(Pk11Install_yyerrstr); + } else { + tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message); + } + Pk11Install_yyerrstr=tmp; +} diff --git a/security/nss/cmd/modutil/instsec.c b/security/nss/cmd/modutil/instsec.c new file mode 100644 index 0000000000..95191e7292 --- /dev/null +++ b/security/nss/cmd/modutil/instsec.c @@ -0,0 +1,153 @@ +/* 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 <plarena.h> +#include <prerror.h> +#include <prio.h> +#include <prprf.h> +#include <seccomon.h> +#include <secmod.h> +#include <jar.h> +#include <secutil.h> + +/* These are installation functions that make calls to the security library. + * We don't want to include security include files in the C++ code too much. + */ + +static char *PR_fgets(char *buf, int size, PRFileDesc *file); + +/*************************************************************************** + * + * P k 1 1 I n s t a l l _ A d d N e w M o d u l e + */ +int +Pk11Install_AddNewModule(char *moduleName, char *dllPath, + unsigned long defaultMechanismFlags, + unsigned long cipherEnableFlags) +{ + return (SECMOD_AddNewModule(moduleName, dllPath, + SECMOD_PubMechFlagstoInternal(defaultMechanismFlags), + SECMOD_PubCipherFlagstoInternal(cipherEnableFlags)) == SECSuccess) + ? 0 + : -1; +} + +/************************************************************************* + * + * P k 1 1 I n s t a l l _ U s e r V e r i f y J a r + * + * Gives the user feedback on the signatures of a JAR files, asks them + * whether they actually want to continue. + * Assumes the jar structure has already been created and is valid. + * Returns 0 if the user wants to continue the installation, nonzero + * if the user wishes to abort. + */ +short +Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out, PRBool query) +{ + JAR_Context *ctx; + JAR_Cert *fing; + JAR_Item *item; + char stdinbuf[80]; + int count = 0; + + CERTCertificate *cert, *prev = NULL; + + PR_fprintf(out, "\nThis installation JAR file was signed by:\n"); + + ctx = JAR_find(jar, NULL, jarTypeSign); + + while (JAR_find_next(ctx, &item) >= 0) { + fing = (JAR_Cert *)item->data; + cert = fing->cert; + if (cert == prev) { + continue; + } + + count++; + PR_fprintf(out, "----------------------------------------------\n"); + if (cert) { + if (cert->nickname) { + PR_fprintf(out, "**NICKNAME**\n%s\n", cert->nickname); + } + if (cert->subjectName) { + PR_fprintf(out, "**SUBJECT NAME**\n%s\n", cert->subjectName); + } + if (cert->issuerName) { + PR_fprintf(out, "**ISSUER NAME**\n%s\n", cert->issuerName); + } + } else { + PR_fprintf(out, "No matching certificate could be found.\n"); + } + PR_fprintf(out, "----------------------------------------------\n\n"); + + prev = cert; + } + + JAR_find_end(ctx); + + if (count == 0) { + PR_fprintf(out, "No signatures found: JAR FILE IS UNSIGNED.\n"); + } + + if (query) { + PR_fprintf(out, + "Do you wish to continue this installation? (y/n) "); + + if (PR_fgets(stdinbuf, 80, PR_STDIN) != NULL) { + char *response; + + if ((response = strtok(stdinbuf, " \t\n\r"))) { + if (!PL_strcasecmp(response, "y") || + !PL_strcasecmp(response, "yes")) { + return 0; + } + } + } + } + + return 1; +} + +/************************************************************************** + * + * 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; +} + +/************************************************************************** + * + * m y S E C U _ E r r o r S t r i n g + * + */ +const char * +mySECU_ErrorString(PRErrorCode errnum) +{ + return SECU_Strerror(errnum); +} diff --git a/security/nss/cmd/modutil/lex.Pk11Install_yy.c b/security/nss/cmd/modutil/lex.Pk11Install_yy.c new file mode 100644 index 0000000000..7dcc1c295d --- /dev/null +++ b/security/nss/cmd/modutil/lex.Pk11Install_yy.c @@ -0,0 +1,1600 @@ +/* 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/. */ + +#define yy_create_buffer Pk11Install_yy_create_buffer +#define yy_delete_buffer Pk11Install_yy_delete_buffer +#define yy_scan_buffer Pk11Install_yy_scan_buffer +#define yy_scan_string Pk11Install_yy_scan_string +#define yy_scan_bytes Pk11Install_yy_scan_bytes +#define yy_flex_debug Pk11Install_yy_flex_debug +#define yy_init_buffer Pk11Install_yy_init_buffer +#define yy_flush_buffer Pk11Install_yy_flush_buffer +#define yy_load_buffer_state Pk11Install_yy_load_buffer_state +#define yy_switch_to_buffer Pk11Install_yy_switch_to_buffer +#define yyin Pk11Install_yyin +#define yyleng Pk11Install_yyleng +#define yylex Pk11Install_yylex +#define yyout Pk11Install_yyout +#define yyrestart Pk11Install_yyrestart +#define yytext Pk11Install_yytext +#define yywrap Pk11Install_yywrap + +#line 20 "lex.Pk11Install_yy.c" +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + +#ifdef __cplusplus + +#include <stdlib.h> +//#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC_VERSION__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC_VERSION__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ +#pragma warn - rch +#pragma warn - use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int)(unsigned char)c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } while (0) + +#define unput(c) yyunput(c, yytext_ptr) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + +struct yy_buffer_state { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 +/* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 +}; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *)0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO((FILE * input_file)); + +void yy_switch_to_buffer YY_PROTO((YY_BUFFER_STATE new_buffer)); +void yy_load_buffer_state YY_PROTO((void)); +YY_BUFFER_STATE yy_create_buffer YY_PROTO((FILE * file, int size)); +void yy_delete_buffer YY_PROTO((YY_BUFFER_STATE b)); +void yy_init_buffer YY_PROTO((YY_BUFFER_STATE b, FILE *file)); +void yy_flush_buffer YY_PROTO((YY_BUFFER_STATE b)); +#define YY_FLUSH_BUFFER yy_flush_buffer(yy_current_buffer) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO((char *base, yy_size_t size)); +YY_BUFFER_STATE yy_scan_string YY_PROTO((yyconst char *yy_str)); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO((yyconst char *bytes, int len)); + +static void *yy_flex_alloc YY_PROTO((yy_size_t)); +static void *yy_flex_realloc YY_PROTO((void *, yy_size_t)); +static void yy_flex_free YY_PROTO((void *)); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if (!yy_current_buffer) \ + yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if (!yy_current_buffer) \ + yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *)0, *yyout = (FILE *)0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO((void)); +static yy_state_type yy_try_NUL_trans YY_PROTO((yy_state_type current_state)); +static int yy_get_next_buffer YY_PROTO((void)); +static void yy_fatal_error YY_PROTO((yyconst char msg[])); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int)(yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 8 +#define YY_END_OF_BUFFER 9 +static yyconst short int yy_accept[16] = { 0, + 0, 0, 9, 3, 6, 5, 7, 1, 2, 3, + 6, 0, 0, 4, 0 }; + +static yyconst int yy_ec[256] = { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 5, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 7, 1, 8, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 }; + +static yyconst int yy_meta[9] = { 0, + 1, 2, 3, 4, 3, 1, 5, 5 }; + +static yyconst short int yy_base[19] = { 0, + 0, 0, 19, 0, 0, 21, 12, 21, 21, 0, + 0, 4, 6, 21, 21, 13, 11, 15 }; + +static yyconst short int yy_def[19] = { 0, + 15, 1, 15, 16, 17, 15, 18, 15, 15, 16, + 17, 18, 15, 15, 0, 15, 15, 15 }; + +static yyconst short int yy_nxt[30] = { 0, + 4, 5, 6, 5, 7, 4, 8, 9, 14, 13, + 12, 12, 11, 10, 11, 12, 12, 13, 15, 12, + 3, 15, 15, 15, 15, 15, 15, 15, 15 }; + +static yyconst short int yy_chk[30] = { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, + 13, 13, 17, 16, 17, 18, 18, 7, 3, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15 }; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "installparse.l" +#define INITIAL 0 +/* lex file for analyzing PKCS #11 Module installation instructions */ +/*----------------------------- Definitions ---------------------------*/ +#line 5 "installparse.l" +#include <string.h> + +#include "install-ds.h" /* defines tokens and data structures */ +#include "installparse.h" /* produced by yacc -d */ +#include <prprf.h> +static char *putSimpleString(char *); /* return copy of string */ +static char *putComplexString(char *); /* strip out quotes, deal with */ + /* escaped characters */ + +void Pk11Install_yyerror(char *); + +/* Overrides to use NSPR */ +#define malloc PR_Malloc +#define realloc PR_Realloc +#define free PR_Free + +int Pk11Install_yylinenum = 1; +static char *err; + +#define YY_NEVER_INTERACTIVE 1 +#define yyunput Pkcs11Install_yyunput + +/* This is the default YY_INPUT modified for NSPR */ +#define YY_INPUT(buf, result, max_size) \ + if (yy_current_buffer->yy_is_interactive) { \ + char c; \ + int n; \ + for (n = 0; n < max_size && \ + PR_Read(Pk11Install_FD, &c, 1) == 1 && c != '\n'; \ + ++n) { \ + buf[n] = c; \ + } \ + if (c == '\n') { \ + buf[n++] = c; \ + } \ + result = n; \ + } else { \ + result = PR_Read(Pk11Install_FD, buf, max_size); \ + } + +/*** Regular expression definitions ***/ +/* simple_string has no whitespace, quotes, or braces */ +/* complex_string is enclosed in quotes. Inside the quotes, quotes and + backslashes must be backslash-escaped. Otherwise, anything goes. */ +/* Standard whitespace */ +/*---------------------------- Actions --------------------------------*/ +#line 437 "lex.Pk11Install_yy.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO((void)); +#else +extern int yywrap YY_PROTO((void)); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO((int c, char *buf_ptr)); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO((char *, yyconst char *, int)); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO((yyconst char *)); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO((void)); +#else +static int input YY_PROTO((void)); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO((int new_state)); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO((void)); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO((void)); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC_VERSION__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void)fwrite(yytext, yyleng, 1, yyout) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf, result, max_size) \ + if (yy_current_buffer->yy_is_interactive) { \ + int c = '*', n; \ + for (n = 0; n < max_size && \ + (c = getc(yyin)) != EOF && c != '\n'; \ + ++n) \ + buf[n] = (char)c; \ + if (c == '\n') \ + buf[n++] = (char)c; \ + if (c == EOF && ferror(yyin)) \ + YY_FATAL_ERROR("input in flex scanner failed"); \ + result = n; \ + } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && \ + ferror(yyin)) \ + YY_FATAL_ERROR("input in flex scanner failed"); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error(msg) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO((void)) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 60 "installparse.l" + +#line 591 "lex.Pk11Install_yy.cpp" + + if (yy_init) { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if (!yy_start) + yy_start = 1; /* first start state */ + + if (!yyin) + yyin = stdin; + + if (!yyout) + yyout = stdout; + + if (!yy_current_buffer) + yy_current_buffer = + yy_create_buffer(yyin, YY_BUF_SIZE); + + yy_load_buffer_state(); + } + + while (1) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_match: + do { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if (yy_accept[yy_current_state]) { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 16) + yy_c = yy_meta[(unsigned int)yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; + ++yy_cp; + } while (yy_base[yy_current_state] != 21); + + yy_find_action: + yy_act = yy_accept[yy_current_state]; + if (yy_act == 0) { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + do_action: /* This label is used only to access EOF actions. */ + + switch (yy_act) { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + + case 1: + YY_RULE_SETUP +#line 62 "installparse.l" + return OPENBRACE; + YY_BREAK + case 2: + YY_RULE_SETUP +#line 63 "installparse.l" + return CLOSEBRACE; + YY_BREAK + case 3: + YY_RULE_SETUP +#line 64 "installparse.l" + { + Pk11Install_yylval.string = + putSimpleString(Pk11Install_yytext); + return STRING; + } + YY_BREAK + case 4: + YY_RULE_SETUP +#line 67 "installparse.l" + { + Pk11Install_yylval.string = + putComplexString(Pk11Install_yytext); + return STRING; + } + YY_BREAK + case 5: + YY_RULE_SETUP +#line 71 "installparse.l" + Pk11Install_yylinenum++; + YY_BREAK + case 6: + YY_RULE_SETUP +#line 73 "installparse.l" + ; + YY_BREAK + case 7: + YY_RULE_SETUP +#line 75 "installparse.l" + { + err = + PR_smprintf("Invalid lexeme: %s", Pk11Install_yytext); + Pk11Install_yyerror(err); + PR_smprintf_free(err); + return 1; + } + YY_BREAK + case 8: + YY_RULE_SETUP +#line 81 "installparse.l" + ECHO; + YY_BREAK +#line 722 "lex.Pk11Install_yy.cpp" + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int)(yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if (yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW) { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if (yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars]) { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans(yy_current_state); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if (yy_next_state) { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else + switch (yy_get_next_buffer()) { + case EOB_ACT_END_OF_FILE: { + yy_did_buffer_switch_on_eof = 0; + + if (yywrap()) { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else { + if (!yy_did_buffer_switch_on_eof) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found"); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int +yy_get_next_buffer() +{ + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if (yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1]) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed"); + + if (yy_current_buffer->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */ + if (yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1) { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int)(yy_c_buf_p - yytext_ptr) - 1; + + for (i = 0; i < number_to_move; ++i) + *(dest++) = *(source++); + + if (yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while (num_to_read <= 0) { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( + "input buffer overflow, can't enlarge buffer because scanner uses REJECT"); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int)(yy_c_buf_p - b->yy_ch_buf); + + if (b->yy_is_our_buffer) { + int new_size = b->yy_buf_size * 2; + + if (new_size <= 0) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc((void *)b->yy_ch_buf, + b->yy_buf_size + 2); + } else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if (!b->yy_ch_buf) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow"); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if (num_to_read > YY_READ_BUF_SIZE) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT((&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if (yy_n_chars == 0) { + if (number_to_move == YY_MORE_ADJ) { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin); + } + + else { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type +yy_get_previous_state() +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for (yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp) { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if (yy_accept[yy_current_state]) { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 16) + yy_c = yy_meta[(unsigned int)yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type +yy_try_NUL_trans(yy_state_type yy_current_state) +#else +static yy_state_type yy_try_NUL_trans(yy_current_state) + yy_state_type yy_current_state; +#endif +{ + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if (yy_accept[yy_current_state]) { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 16) + yy_c = yy_meta[(unsigned int)yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; + yy_is_jam = (yy_current_state == 15); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void +yyunput(int c, register char *yy_bp) +#else +static void yyunput(c, yy_bp) int c; +register char *yy_bp; +#endif +{ + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if (yy_cp < yy_current_buffer->yy_ch_buf + 2) { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size + + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while (source > yy_current_buffer->yy_ch_buf) + *--dest = *--source; + + yy_cp += (int)(dest - source); + yy_bp += (int)(dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if (yy_cp < yy_current_buffer->yy_ch_buf + 2) + YY_FATAL_ERROR("flex scanner push-back overflow"); + } + + *--yy_cp = (char)c; + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; +} +#endif /* ifndef YY_NO_UNPUT */ + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int +yyinput() +#else +static int +input() +#endif +{ + int c; + + *yy_c_buf_p = yy_hold_char; + + if (*yy_c_buf_p == YY_END_OF_BUFFER_CHAR) { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if (yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars]) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch (yy_get_next_buffer()) { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: { + if (yywrap()) + return EOF; + + if (!yy_did_buffer_switch_on_eof) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *)yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +#ifdef YY_USE_PROTOS +void +yyrestart(FILE *input_file) +#else +void yyrestart(input_file) + FILE *input_file; +#endif +{ + if (!yy_current_buffer) + yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); + + yy_init_buffer(yy_current_buffer, input_file); + yy_load_buffer_state(); +} + +#ifdef YY_USE_PROTOS +void +yy_switch_to_buffer(YY_BUFFER_STATE new_buffer) +#else +void yy_switch_to_buffer(new_buffer) + YY_BUFFER_STATE new_buffer; +#endif +{ + if (yy_current_buffer == new_buffer) + return; + + if (yy_current_buffer) { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; +} + +#ifdef YY_USE_PROTOS +void +yy_load_buffer_state(void) +#else +void +yy_load_buffer_state() +#endif +{ + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; +} + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE +yy_create_buffer(FILE *file, int size) +#else +YY_BUFFER_STATE yy_create_buffer(file, size) + FILE *file; +int size; +#endif +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state)); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *)yy_flex_alloc(b->yy_buf_size + 2); + if (!b->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b, file); + + return b; +} + +#ifdef YY_USE_PROTOS +void +yy_delete_buffer(YY_BUFFER_STATE b) +#else +void yy_delete_buffer(b) + YY_BUFFER_STATE b; +#endif +{ + if (!b) + return; + + if (b == yy_current_buffer) + yy_current_buffer = (YY_BUFFER_STATE)0; + + if (b->yy_is_our_buffer) + yy_flex_free((void *)b->yy_ch_buf); + + yy_flex_free((void *)b); +} + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO((int)); +#endif +#endif + +#ifdef YY_USE_PROTOS +void +yy_init_buffer(YY_BUFFER_STATE b, FILE *file) +#else +void yy_init_buffer(b, file) + YY_BUFFER_STATE b; +FILE *file; +#endif + +{ + yy_flush_buffer(b); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty(fileno(file)) > 0) : 0; +#endif +#endif +} + +#ifdef YY_USE_PROTOS +void +yy_flush_buffer(YY_BUFFER_STATE b) +#else +void yy_flush_buffer(b) + YY_BUFFER_STATE b; +#endif + +{ + if (!b) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if (b == yy_current_buffer) + yy_load_buffer_state(); +} + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE +yy_scan_buffer(char *base, yy_size_t size) +#else +YY_BUFFER_STATE yy_scan_buffer(base, size) char *base; +yy_size_t size; +#endif +{ + YY_BUFFER_STATE b; + + if (size < 2 || + base[size - 2] != YY_END_OF_BUFFER_CHAR || + base[size - 1] != YY_END_OF_BUFFER_CHAR) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state)); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b); + + return b; +} +#endif + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE +yy_scan_string(yyconst char *yy_str) +#else +YY_BUFFER_STATE yy_scan_string(yy_str) + yyconst char *yy_str; +#endif +{ + int len; + for (len = 0; yy_str[len]; ++len) + ; + + return yy_scan_bytes(yy_str, len); +} +#endif + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE +yy_scan_bytes(yyconst char *bytes, int len) +#else +YY_BUFFER_STATE yy_scan_bytes(bytes, len) + yyconst char *bytes; +int len; +#endif +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *)yy_flex_alloc(n); + if (!buf) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + + for (i = 0; i < len; ++i) + buf[i] = bytes[i]; + + buf[len] = buf[len + 1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf, n); + if (!b) + YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +#endif + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void +yy_push_state(int new_state) +#else +static void yy_push_state(new_state) int new_state; +#endif +{ + if (yy_start_stack_ptr >= yy_start_stack_depth) { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof(int); + + if (!yy_start_stack) + yy_start_stack = (int *)yy_flex_alloc(new_size); + + else + yy_start_stack = (int *)yy_flex_realloc( + (void *)yy_start_stack, new_size); + + if (!yy_start_stack) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack"); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); +} +#endif + +#ifndef YY_NO_POP_STATE +static void +yy_pop_state() +{ + if (--yy_start_stack_ptr < 0) + YY_FATAL_ERROR("start-condition stack underflow"); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); +} +#endif + +#ifndef YY_NO_TOP_STATE +static int +yy_top_state() +{ + return yy_start_stack[yy_start_stack_ptr - 1]; +} +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void +yy_fatal_error(yyconst char msg[]) +#else +static void yy_fatal_error(msg) char msg[]; +#endif +{ + (void)fprintf(stderr, "%s\n", msg); + exit(YY_EXIT_FAILURE); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } while (0) + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void +yy_flex_strncpy(char *s1, yyconst char *s2, int n) +#else +static void yy_flex_strncpy(s1, s2, n) char *s1; +yyconst char *s2; +int n; +#endif +{ + register int i; + for (i = 0; i < n; ++i) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int +yy_flex_strlen(yyconst char *s) +#else +static int yy_flex_strlen(s) + yyconst char *s; +#endif +{ + register int n; + for (n = 0; s[n]; ++n) + ; + + return n; +} +#endif + +#ifdef YY_USE_PROTOS +static void * +yy_flex_alloc(yy_size_t size) +#else +static void *yy_flex_alloc(size) + yy_size_t size; +#endif +{ + return (void *)malloc(size); +} + +#ifdef YY_USE_PROTOS +static void * +yy_flex_realloc(void *ptr, yy_size_t size) +#else +static void *yy_flex_realloc(ptr, size) void *ptr; +yy_size_t size; +#endif +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *)realloc((char *)ptr, size); +} + +#ifdef YY_USE_PROTOS +static void +yy_flex_free(void *ptr) +#else +static void yy_flex_free(ptr) void *ptr; +#endif +{ + free(ptr); +} + +#if YY_MAIN +int +main() +{ + yylex(); + return 0; +} +#endif +#line 81 "installparse.l" + +/*------------------------ Program Section ----------------------------*/ + +PRFileDesc *Pk11Install_FD = NULL; + +/*************************************************************************/ +/* dummy function required by lex */ +int +Pk11Install_yywrap(void) +{ + return 1; +} + +/*************************************************************************/ +/* Return a copy of the given string */ +static char * +putSimpleString(char *str) +{ + char *tmp = (char *)PR_Malloc(strlen(str) + 1); + strcpy(tmp, str); + return tmp; +} + +/*************************************************************************/ +/* Strip out quotes, replace escaped characters with what they stand for. + This function assumes that what is passed in is actually a complex + string, so error checking is lax. */ +static char * +putComplexString(char *str) +{ + int size, i, j; + char *tmp; + + if (!str) { + return NULL; + } + size = strlen(str); + + /* Allocate the new space. This string will actually be too big, + since quotes and backslashes will be stripped out. But that's ok. */ + tmp = (char *)PR_Malloc(size + 1); + + /* Copy it over */ + for (i = 0, j = 0; i < size; i++) { + if (str[i] == '\"') { + continue; /* skip un-escaped quotes */ + } else if (str[i] == '\\') { + ++i; /* escaped character. skip the backslash */ + } + tmp[j++] = str[i]; + } + tmp[j] = '\0'; + + return tmp; +} diff --git a/security/nss/cmd/modutil/manifest.mn b/security/nss/cmd/modutil/manifest.mn new file mode 100644 index 0000000000..99b5f3f99c --- /dev/null +++ b/security/nss/cmd/modutil/manifest.mn @@ -0,0 +1,32 @@ +# +# 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/. + +CORE_DEPTH = ../.. + +MODULE = sectools + +CSRCS = modutil.c \ + pk11.c \ + instsec.c \ + install.c \ + installparse.c \ + install-ds.c \ + lex.Pk11Install_yy.c \ + $(NULL) + +CPPSRCS = + +PROGRAM = modutil + +REQUIRES = seccmd nss dbm + +DEFINES = -DNSPR20 -DYY_NO_UNPUT -DYY_NO_INPUT + +# sigh +#INCLUDES += -I$(CORE_DEPTH)/nss/lib/pk11wrap + +# USE_STATIC_LIBS = 1 + +EXTRA_LIBS = $(JAR_LIBS) diff --git a/security/nss/cmd/modutil/modutil.c b/security/nss/cmd/modutil/modutil.c new file mode 100644 index 0000000000..f04ad3d925 --- /dev/null +++ b/security/nss/cmd/modutil/modutil.c @@ -0,0 +1,996 @@ +/* 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; +} diff --git a/security/nss/cmd/modutil/modutil.gyp b/security/nss/cmd/modutil/modutil.gyp new file mode 100644 index 0000000000..5d0f87a65c --- /dev/null +++ b/security/nss/cmd/modutil/modutil.gyp @@ -0,0 +1,44 @@ +# 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/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'modutil', + 'type': 'executable', + 'sources': [ + 'install-ds.c', + 'install.c', + 'installparse.c', + 'instsec.c', + 'lex.Pk11Install_yy.c', + 'modutil.c', + 'pk11.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/exports.gyp:dbm_exports', + '<(DEPTH)/lib/jar/jar.gyp:jar', + '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib' + ] + } + ], + 'target_defaults': { + 'include_dirs': [ + '<(nss_private_dist_dir)/nss', + '<(nss_private_dist_dir)/dbm' + ], + 'defines': [ + 'NSPR20', + 'YY_NO_UNPUT', + 'YY_NO_INPUT' + ] + }, + 'variables': { + 'module': 'sectools' + } +} diff --git a/security/nss/cmd/modutil/modutil.h b/security/nss/cmd/modutil/modutil.h new file mode 100644 index 0000000000..1981fec7bc --- /dev/null +++ b/security/nss/cmd/modutil/modutil.h @@ -0,0 +1,42 @@ +/* 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/. */ + +#ifndef MODUTIL_H +#define MODUTIL_H + +#include <stdio.h> +#include <string.h> + +#include <prio.h> +#include <prprf.h> +#include <prinit.h> +#include <prlock.h> +#include <prmem.h> +#include <plarena.h> + +#include "seccomon.h" +#include "secmod.h" +#include "secutil.h" + +#include "error.h" + +Error LoadMechanismList(void); +Error FipsMode(char *arg); +Error ChkFipsMode(char *arg); +Error AddModule(char *moduleName, char *libFile, char *ciphers, + char *mechanisms, char *modparms); +Error DeleteModule(char *moduleName); +Error ListModule(char *moduleName); +Error ListModules(); +Error InitPW(void); +Error ChangePW(char *tokenName, char *pwFile, char *newpwFile); +Error EnableModule(char *moduleName, char *slotName, PRBool enable); +Error RawAddModule(char *dbmodulespec, char *modulespec); +Error RawListModule(char *modulespec); +Error SetDefaultModule(char *moduleName, char *slotName, char *mechanisms); +Error UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms); +PRBool IsP11KitEnabled(void); +void out_of_memory(void); + +#endif /*MODUTIL_H*/ diff --git a/security/nss/cmd/modutil/pk11.c b/security/nss/cmd/modutil/pk11.c new file mode 100644 index 0000000000..6d17a33657 --- /dev/null +++ b/security/nss/cmd/modutil/pk11.c @@ -0,0 +1,1050 @@ +/* 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 "pk11func.h" + +/************************************************************************* + * + * F i p s M o d e + * If arg=="true", enable FIPS mode on the internal module. If arg=="false", + * disable FIPS mode on the internal module. + */ +Error +FipsMode(char *arg) +{ + char *internal_name; + + if (!PORT_Strcasecmp(arg, "true")) { + if (!PK11_IsFIPS()) { + internal_name = PR_smprintf("%s", + SECMOD_GetInternalModule()->commonName); + if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) { + PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError())); + PR_smprintf_free(internal_name); + PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); + return FIPS_SWITCH_FAILED_ERR; + } + PR_smprintf_free(internal_name); + if (!PK11_IsFIPS()) { + PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); + return FIPS_SWITCH_FAILED_ERR; + } + PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); + } else { + PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]); + return FIPS_ALREADY_ON_ERR; + } + } else if (!PORT_Strcasecmp(arg, "false")) { + if (PK11_IsFIPS()) { + internal_name = PR_smprintf("%s", + SECMOD_GetInternalModule()->commonName); + if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) { + PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError())); + PR_smprintf_free(internal_name); + PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); + return FIPS_SWITCH_FAILED_ERR; + } + PR_smprintf_free(internal_name); + if (PK11_IsFIPS()) { + PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); + return FIPS_SWITCH_FAILED_ERR; + } + PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); + } else { + PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]); + return FIPS_ALREADY_OFF_ERR; + } + } else { + PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]); + return INVALID_FIPS_ARG; + } + + return SUCCESS; +} + +/************************************************************************* + * + * C h k F i p s M o d e + * If arg=="true", verify FIPS mode is enabled on the internal module. + * If arg=="false", verify FIPS mode is disabled on the internal module. + */ +Error +ChkFipsMode(char *arg) +{ + if (!PORT_Strcasecmp(arg, "true")) { + if (PK11_IsFIPS()) { + PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); + } else { + PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); + return FIPS_SWITCH_FAILED_ERR; + } + + } else if (!PORT_Strcasecmp(arg, "false")) { + if (!PK11_IsFIPS()) { + PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); + } else { + PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); + return FIPS_SWITCH_FAILED_ERR; + } + } else { + PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]); + return INVALID_FIPS_ARG; + } + + return SUCCESS; +} + +/************************************************************************ + * Cipher and Mechanism name-bitmask translation tables + */ + +typedef struct { + const char *name; + unsigned long mask; +} MaskString; + +static const MaskString cipherStrings[] = { + { "FORTEZZA", PUBLIC_CIPHER_FORTEZZA_FLAG } +}; +static const int numCipherStrings = + sizeof(cipherStrings) / sizeof(cipherStrings[0]); + +/* Initialized by LoadMechanismList */ +static MaskString *mechanismStrings = NULL; +static int numMechanismStrings = 0; +const static PK11DefaultArrayEntry *pk11_DefaultArray = NULL; +static int pk11_DefaultArraySize = 0; + +/* Maximum length of a colon-separated list of all the strings in an + * array. */ +#define MAX_STRING_LIST_LEN 240 /* or less */ + +Error +LoadMechanismList(void) +{ + int i; + + if (pk11_DefaultArray == NULL) { + pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize); + if (pk11_DefaultArray == NULL) { + /* should assert. This shouldn't happen */ + return UNSPECIFIED_ERR; + } + } + if (mechanismStrings != NULL) { + return SUCCESS; + } + + /* build the mechanismStrings array */ + mechanismStrings = PORT_NewArray(MaskString, pk11_DefaultArraySize); + if (mechanismStrings == NULL) { + return OUT_OF_MEM_ERR; + } + numMechanismStrings = pk11_DefaultArraySize; + for (i = 0; i < numMechanismStrings; i++) { + const char *name = pk11_DefaultArray[i].name; + unsigned long flag = pk11_DefaultArray[i].flag; + /* map new name to old */ + switch (flag) { + case SECMOD_FORTEZZA_FLAG: + name = "FORTEZZA"; + break; + case SECMOD_SHA1_FLAG: + name = "SHA1"; + break; + case SECMOD_CAMELLIA_FLAG: + name = "CAMELLIA"; + break; + case SECMOD_RANDOM_FLAG: + name = "RANDOM"; + break; + case SECMOD_FRIENDLY_FLAG: + name = "FRIENDLY"; + break; + default: + break; + } + mechanismStrings[i].name = name; + mechanismStrings[i].mask = SECMOD_InternaltoPubMechFlags(flag); + } + return SUCCESS; +} + +/************************************************************************ + * + * g e t F l a g s F r o m S t r i n g + * + * Parses a mechanism list passed on the command line and converts it + * to an unsigned long bitmask. + * string is a colon-separated string of constants + * array is an array of MaskStrings. + * elements is the number of elements in array. + */ +static unsigned long +getFlagsFromString(char *string, const MaskString array[], int elements) +{ + unsigned long ret = 0; + short i = 0; + char *cp; + char *buf; + char *end; + + if (!string || !string[0]) { + return ret; + } + + /* Make a temporary copy of the string */ + buf = PR_Malloc(strlen(string) + 1); + if (!buf) { + out_of_memory(); + } + strcpy(buf, string); + + /* Look at each element of the list passed in */ + for (cp = buf; cp && *cp; cp = (end ? end + 1 : NULL)) { + /* Look at the string up to the next colon */ + end = strchr(cp, ':'); + if (end) { + *end = '\0'; + } + + /* Find which element this is */ + for (i = 0; i < elements; i++) { + if (!PORT_Strcasecmp(cp, array[i].name)) { + break; + } + } + if (i == elements) { + /* Skip a bogus string, but print a warning message */ + PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp); + continue; + } + ret |= array[i].mask; + } + + PR_Free(buf); + return ret; +} + +/********************************************************************** + * + * g e t S t r i n g F r o m F l a g s + * + * The return string's memory is owned by this function. Copy it + * if you need it permanently or you want to change it. + */ +static char * +getStringFromFlags(unsigned long flags, const MaskString array[], int elements) +{ + static char buf[MAX_STRING_LIST_LEN]; + int i; + int count = 0; + + buf[0] = '\0'; + for (i = 0; i < elements; i++) { + if (flags & array[i].mask) { + ++count; + if (count != 1) { + strcat(buf, ":"); + } + strcat(buf, array[i].name); + } + } + return buf; +} + +static PRBool +IsP11KitProxyModule(SECMODModule *module) +{ + CK_INFO modinfo; + static const char p11KitManufacturerID[33] = + "PKCS#11 Kit "; + static const char p11KitLibraryDescription[33] = + "PKCS#11 Kit Proxy Module "; + + if (PK11_GetModInfo(module, &modinfo) == SECSuccess && + PORT_Memcmp(modinfo.manufacturerID, + p11KitManufacturerID, + sizeof(modinfo.manufacturerID)) == 0 && + PORT_Memcmp(modinfo.libraryDescription, + p11KitLibraryDescription, + sizeof(modinfo.libraryDescription)) == 0) { + return PR_TRUE; + } + + return PR_FALSE; +} + +PRBool +IsP11KitEnabled(void) +{ + SECMODListLock *lock; + SECMODModuleList *mlp; + PRBool found = PR_FALSE; + + lock = SECMOD_GetDefaultModuleListLock(); + if (!lock) { + PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]); + return found; + } + + SECMOD_GetReadLock(lock); + + mlp = SECMOD_GetDefaultModuleList(); + for (; mlp != NULL; mlp = mlp->next) { + if (IsP11KitProxyModule(mlp->module)) { + found = PR_TRUE; + break; + } + } + + SECMOD_ReleaseReadLock(lock); + return found; +} + +/********************************************************************** + * + * A d d M o d u l e + * + * Add the named module, with the given library file, ciphers, and + * default mechanism flags + */ +Error +AddModule(char *moduleName, char *libFile, char *cipherString, + char *mechanismString, char *modparms) +{ + unsigned long ciphers; + unsigned long mechanisms; + SECStatus status; + + mechanisms = + getFlagsFromString(mechanismString, mechanismStrings, + numMechanismStrings); + ciphers = + getFlagsFromString(cipherString, cipherStrings, numCipherStrings); + + status = + SECMOD_AddNewModuleEx(moduleName, libFile, + SECMOD_PubMechFlagstoInternal(mechanisms), + SECMOD_PubCipherFlagstoInternal(ciphers), + modparms, NULL); + + if (status != SECSuccess) { + char *errtxt = NULL; + PRInt32 copied = 0; + if (PR_GetErrorTextLength()) { + errtxt = PR_Malloc(PR_GetErrorTextLength() + 1); + copied = PR_GetErrorText(errtxt); + } + if (copied && errtxt) { + PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR], + moduleName, errtxt); + PR_Free(errtxt); + } else { + PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR], + moduleName, SECU_Strerror(PORT_GetError())); + } + return ADD_MODULE_FAILED_ERR; + } else { + PR_fprintf(PR_STDOUT, msgStrings[ADD_MODULE_SUCCESS_MSG], moduleName); + return SUCCESS; + } +} + +/*********************************************************************** + * + * D e l e t e M o d u l e + * + * Deletes the named module from the database. + */ +Error +DeleteModule(char *moduleName) +{ + SECStatus status; + int type; + + status = SECMOD_DeleteModule(moduleName, &type); + + if (status != SECSuccess) { + if (type == SECMOD_FIPS || type == SECMOD_INTERNAL) { + PR_fprintf(PR_STDERR, errStrings[DELETE_INTERNAL_ERR]); + return DELETE_INTERNAL_ERR; + } else { + PR_fprintf(PR_STDERR, errStrings[DELETE_FAILED_ERR], moduleName); + return DELETE_FAILED_ERR; + } + } + + PR_fprintf(PR_STDOUT, msgStrings[DELETE_SUCCESS_MSG], moduleName); + return SUCCESS; +} + +/************************************************************************ + * + * R a w L i s t M o d u l e s + * + * Lists all the modules in the database, along with their slots and tokens. + */ +Error +RawListModule(char *modulespec) +{ + SECMODModule *module; + char **moduleSpecList; + + module = SECMOD_LoadModule(modulespec, NULL, PR_FALSE); + if (module == NULL) { + /* handle error */ + return NO_SUCH_MODULE_ERR; + } + + moduleSpecList = SECMOD_GetModuleSpecList(module); + if (!moduleSpecList || !moduleSpecList[0]) { + SECU_PrintError("modutil", + "no specs in secmod DB"); + return NO_SUCH_MODULE_ERR; + } + + for (; *moduleSpecList; moduleSpecList++) { + printf("%s\n\n", *moduleSpecList); + } + + return SUCCESS; +} + +Error +RawAddModule(char *dbmodulespec, char *modulespec) +{ + SECMODModule *module; + SECMODModule *dbmodule; + + dbmodule = SECMOD_LoadModule(dbmodulespec, NULL, PR_TRUE); + if (dbmodule == NULL) { + /* handle error */ + return NO_SUCH_MODULE_ERR; + } + + module = SECMOD_LoadModule(modulespec, dbmodule, PR_FALSE); + if (module == NULL) { + /* handle error */ + return NO_SUCH_MODULE_ERR; + } + + if (SECMOD_UpdateModule(module) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec); + return UPDATE_MOD_FAILED_ERR; + } + return SUCCESS; +} + +static void +printModule(SECMODModule *module, int *count) +{ + int slotCount = module->loaded ? module->slotCount : 0; + char *modUri; + int i; + + if ((*count)++) { + PR_fprintf(PR_STDOUT, "\n"); + } + PR_fprintf(PR_STDOUT, "%3d. %s\n", *count, module->commonName); + + if (module->dllName) { + PR_fprintf(PR_STDOUT, "\tlibrary name: %s\n", module->dllName); + } + + modUri = PK11_GetModuleURI(module); + if (modUri) { + PR_fprintf(PR_STDOUT, "\t uri: %s\n", modUri); + PORT_Free(modUri); + } + if (slotCount == 0) { + PR_fprintf(PR_STDOUT, + "\t slots: There are no slots attached to this module\n"); + } else { + PR_fprintf(PR_STDOUT, "\t slots: %d slot%s attached\n", + slotCount, (slotCount == 1 ? "" : "s")); + } + + if (module->loaded == 0) { + PR_fprintf(PR_STDOUT, "\tstatus: Not loaded\n"); + } else { + PR_fprintf(PR_STDOUT, "\tstatus: loaded\n"); + } + + /* Print slot and token names */ + for (i = 0; i < slotCount; i++) { + PK11SlotInfo *slot = module->slots[i]; + char *tokenUri = PK11_GetTokenURI(slot); + PR_fprintf(PR_STDOUT, "\n"); + PR_fprintf(PR_STDOUT, "\t slot: %s\n", PK11_GetSlotName(slot)); + PR_fprintf(PR_STDOUT, "\ttoken: %s\n", PK11_GetTokenName(slot)); + PR_fprintf(PR_STDOUT, "\t uri: %s\n", tokenUri); + PORT_Free(tokenUri); + } + return; +} + +/************************************************************************ + * + * L i s t M o d u l e s + * + * Lists all the modules in the database, along with their slots and tokens. + */ +Error +ListModules() +{ + SECMODListLock *lock; + SECMODModuleList *list; + SECMODModuleList *deadlist; + SECMODModuleList *mlp; + Error ret = UNSPECIFIED_ERR; + int count = 0; + + lock = SECMOD_GetDefaultModuleListLock(); + if (!lock) { + PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]); + return NO_LIST_LOCK_ERR; + } + + SECMOD_GetReadLock(lock); + + list = SECMOD_GetDefaultModuleList(); + deadlist = SECMOD_GetDeadModuleList(); + if (!list && !deadlist) { + PR_fprintf(PR_STDERR, errStrings[NO_MODULE_LIST_ERR]); + ret = NO_MODULE_LIST_ERR; + goto loser; + } + + PR_fprintf(PR_STDOUT, + "\nListing of PKCS #11 Modules\n" + "-----------------------------------------------------------\n"); + + for (mlp = list; mlp != NULL; mlp = mlp->next) { + printModule(mlp->module, &count); + } + for (mlp = deadlist; mlp != NULL; mlp = mlp->next) { + printModule(mlp->module, &count); + } + + PR_fprintf(PR_STDOUT, + "-----------------------------------------------------------\n"); + + ret = SUCCESS; + +loser: + SECMOD_ReleaseReadLock(lock); + return ret; +} + +/* Strings describing PK11DisableReasons */ +static char *disableReasonStr[] = { + "no reason", + "user disabled", + "could not initialize token", + "could not verify token", + "token not present" +}; +static size_t numDisableReasonStr = + sizeof(disableReasonStr) / sizeof(disableReasonStr[0]); + +/*********************************************************************** + * + * L i s t M o d u l e + * + * Lists detailed information about the named module. + */ +Error +ListModule(char *moduleName) +{ + SECMODModule *module = NULL; + PK11SlotInfo *slot; + int slotnum; + CK_INFO modinfo; + CK_SLOT_INFO slotinfo; + CK_TOKEN_INFO tokeninfo; + char *ciphers, *mechanisms; + size_t reasonIdx; + Error rv = SUCCESS; + + if (!moduleName) { + return SUCCESS; + } + + module = SECMOD_FindModule(moduleName); + if (!module) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName); + rv = NO_SUCH_MODULE_ERR; + goto loser; + } + + if ((module->loaded) && + (PK11_GetModInfo(module, &modinfo) != SECSuccess)) { + PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName); + rv = MOD_INFO_ERR; + goto loser; + } + + /* Module info */ + PR_fprintf(PR_STDOUT, + "\n-----------------------------------------------------------\n"); + PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName); + if (module->internal || !module->dllName) { + PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n"); + } else { + PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName); + } + + if (module->loaded) { + PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID); + PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription); + PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n", + modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor); + PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n", + modinfo.libraryVersion.major, modinfo.libraryVersion.minor); + } else { + PR_fprintf(PR_STDOUT, "* Module not loaded\n"); + } + /* Get cipher and mechanism flags */ + ciphers = getStringFromFlags(module->ssl[0], cipherStrings, + numCipherStrings); + if (ciphers[0] == '\0') { + ciphers = "None"; + } + PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers); + mechanisms = NULL; + if (module->slotCount > 0) { + mechanisms = getStringFromFlags( + PK11_GetDefaultFlags(module->slots[0]), + mechanismStrings, numMechanismStrings); + } + if ((mechanisms == NULL) || (mechanisms[0] == '\0')) { + mechanisms = "None"; + } + PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms); + +#define PAD " " + + /* Loop over each slot */ + for (slotnum = 0; slotnum < module->slotCount; slotnum++) { + slot = module->slots[slotnum]; + if (PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR], + PK11_GetSlotName(slot)); + rv = SLOT_INFO_ERR; + continue; + } + + /* Slot Info */ + PR_fprintf(PR_STDOUT, "\n" PAD "Slot: %s\n", PK11_GetSlotName(slot)); + mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot), + mechanismStrings, numMechanismStrings); + if (mechanisms[0] == '\0') { + mechanisms = "None"; + } + PR_fprintf(PR_STDOUT, PAD "Slot Mechanism Flags: %s\n", mechanisms); + PR_fprintf(PR_STDOUT, PAD "Manufacturer: %.32s\n", + slotinfo.manufacturerID); + if (PK11_IsHW(slot)) { + PR_fprintf(PR_STDOUT, PAD "Type: Hardware\n"); + } else { + PR_fprintf(PR_STDOUT, PAD "Type: Software\n"); + } + PR_fprintf(PR_STDOUT, PAD "Version Number: %d.%d\n", + slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor); + PR_fprintf(PR_STDOUT, PAD "Firmware Version: %d.%d\n", + slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor); + if (PK11_IsDisabled(slot)) { + reasonIdx = PK11_GetDisabledReason(slot); + if (reasonIdx < numDisableReasonStr) { + PR_fprintf(PR_STDOUT, PAD "Status: DISABLED (%s)\n", + disableReasonStr[reasonIdx]); + } else { + PR_fprintf(PR_STDOUT, PAD "Status: DISABLED\n"); + } + } else { + PR_fprintf(PR_STDOUT, PAD "Status: Enabled\n"); + } + + if (PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR], + PK11_GetTokenName(slot)); + rv = TOKEN_INFO_ERR; + continue; + } + + /* Token Info */ + PR_fprintf(PR_STDOUT, PAD "Token Name: %.32s\n", + tokeninfo.label); + PR_fprintf(PR_STDOUT, PAD "Token Manufacturer: %.32s\n", + tokeninfo.manufacturerID); + PR_fprintf(PR_STDOUT, PAD "Token Model: %.16s\n", tokeninfo.model); + PR_fprintf(PR_STDOUT, PAD "Token Serial Number: %.16s\n", + tokeninfo.serialNumber); + PR_fprintf(PR_STDOUT, PAD "Token Version: %d.%d\n", + tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor); + PR_fprintf(PR_STDOUT, PAD "Token Firmware Version: %d.%d\n", + tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor); + if (tokeninfo.flags & CKF_WRITE_PROTECTED) { + PR_fprintf(PR_STDOUT, PAD "Access: Write Protected\n"); + } else { + PR_fprintf(PR_STDOUT, PAD "Access: NOT Write Protected\n"); + } + if (tokeninfo.flags & CKF_LOGIN_REQUIRED) { + PR_fprintf(PR_STDOUT, PAD "Login Type: Login required\n"); + } else { + PR_fprintf(PR_STDOUT, PAD + "Login Type: Public (no login required)\n"); + } + if (tokeninfo.flags & CKF_USER_PIN_INITIALIZED) { + PR_fprintf(PR_STDOUT, PAD "User Pin: Initialized\n"); + } else { + PR_fprintf(PR_STDOUT, PAD "User Pin: NOT Initialized\n"); + } + } + PR_fprintf(PR_STDOUT, + "\n-----------------------------------------------------------\n"); +loser: + if (module) { + SECMOD_DestroyModule(module); + } + return rv; +} + +/************************************************************************ + * + * I n i t P W + */ +Error +InitPW(void) +{ + PK11SlotInfo *slot; + Error ret = UNSPECIFIED_ERR; + + slot = PK11_GetInternalKeySlot(); + if (!slot) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], "internal"); + return NO_SUCH_TOKEN_ERR; + } + + /* Set the initial password to empty */ + if (PK11_NeedUserInit(slot)) { + if (PK11_InitPin(slot, NULL, "") != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[INITPW_FAILED_ERR]); + ret = INITPW_FAILED_ERR; + goto loser; + } + } + + ret = SUCCESS; + +loser: + PK11_FreeSlot(slot); + + return ret; +} + +/************************************************************************ + * + * C h a n g e P W + */ +Error +ChangePW(char *tokenName, char *pwFile, char *newpwFile) +{ + char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL; + PK11SlotInfo *slot; + Error ret = UNSPECIFIED_ERR; + PRBool matching; + + slot = PK11_FindSlotByName(tokenName); + if (!slot) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName); + return NO_SUCH_TOKEN_ERR; + } + + /* Get old password */ + if (!PK11_NeedUserInit(slot)) { + if (pwFile) { + oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile); + if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]); + ret = BAD_PW_ERR; + goto loser; + } + } else if (PK11_NeedLogin(slot)) { + for (matching = PR_FALSE; !matching;) { + oldpw = SECU_GetPasswordString(NULL, "Enter old password: "); + if (PK11_CheckUserPassword(slot, oldpw) == SECSuccess) { + matching = PR_TRUE; + } else { + PR_fprintf(PR_STDOUT, msgStrings[BAD_PW_MSG]); + } + } + } + } + + /* Get new password */ + if (newpwFile) { + newpw = SECU_FilePasswd(NULL, PR_FALSE, newpwFile); + } else { + for (matching = PR_FALSE; !matching;) { + newpw = SECU_GetPasswordString(NULL, "Enter new password: "); + newpw2 = SECU_GetPasswordString(NULL, "Re-enter new password: "); + if (strcmp(newpw, newpw2)) { + PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]); + PORT_ZFree(newpw, strlen(newpw)); + PORT_ZFree(newpw2, strlen(newpw2)); + } else { + matching = PR_TRUE; + } + } + } + + /* Change the password */ + if (PK11_NeedUserInit(slot)) { + if (PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName); + ret = CHANGEPW_FAILED_ERR; + goto loser; + } + } else { + if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName); + ret = CHANGEPW_FAILED_ERR; + goto loser; + } + } + + PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName); + ret = SUCCESS; + +loser: + if (oldpw) { + PORT_ZFree(oldpw, strlen(oldpw)); + } + if (newpw) { + PORT_ZFree(newpw, strlen(newpw)); + } + if (newpw2) { + PORT_ZFree(newpw2, strlen(newpw2)); + } + PK11_FreeSlot(slot); + + return ret; +} + +/*********************************************************************** + * + * E n a b l e M o d u l e + * + * If enable==PR_TRUE, enables the module or slot. + * If enable==PR_FALSE, disables the module or slot. + * moduleName is the name of the module. + * slotName is the name of the slot. It is optional. + */ +Error +EnableModule(char *moduleName, char *slotName, PRBool enable) +{ + int i; + SECMODModule *module = NULL; + PK11SlotInfo *slot = NULL; + PRBool found = PR_FALSE; + Error rv; + + module = SECMOD_FindModule(moduleName); + if (!module) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName); + rv = NO_SUCH_MODULE_ERR; + goto loser; + } + + for (i = 0; i < module->slotCount; i++) { + slot = module->slots[i]; + if (slotName && strcmp(PK11_GetSlotName(slot), slotName)) { + /* Not the right slot */ + continue; + } + if (enable) { + if (!PK11_UserEnableSlot(slot)) { + PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR], + "enable", PK11_GetSlotName(slot)); + rv = ENABLE_FAILED_ERR; + goto loser; + } else { + found = PR_TRUE; + PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG], + PK11_GetSlotName(slot), "enabled"); + } + } else { + if (!PK11_UserDisableSlot(slot)) { + PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR], + "disable", PK11_GetSlotName(slot)); + rv = ENABLE_FAILED_ERR; + goto loser; + } else { + found = PR_TRUE; + PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG], + PK11_GetSlotName(slot), "disabled"); + } + } + } + + if (slotName && !found) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName); + rv = NO_SUCH_SLOT_ERR; + goto loser; + } + + /* Delete and re-add module to save changes */ + if (SECMOD_UpdateModule(module) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], moduleName); + rv = UPDATE_MOD_FAILED_ERR; + goto loser; + } + + rv = SUCCESS; +loser: + if (module) { + SECMOD_DestroyModule(module); + } + return rv; +} + +/************************************************************************* + * + * S e t D e f a u l t M o d u l e + * + */ +Error +SetDefaultModule(char *moduleName, char *slotName, char *mechanisms) +{ + SECMODModule *module = NULL; + PK11SlotInfo *slot; + int s, i; + unsigned long mechFlags = getFlagsFromString(mechanisms, mechanismStrings, + numMechanismStrings); + PRBool found = PR_FALSE; + Error errcode = UNSPECIFIED_ERR; + + mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags); + + module = SECMOD_FindModule(moduleName); + if (!module) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName); + errcode = NO_SUCH_MODULE_ERR; + goto loser; + } + + /* Go through each slot */ + for (s = 0; s < module->slotCount; s++) { + slot = module->slots[s]; + + if ((slotName != NULL) && + !((strcmp(PK11_GetSlotName(slot), slotName) == 0) || + (strcmp(PK11_GetTokenName(slot), slotName) == 0))) { + /* we are only interested in changing the one slot */ + continue; + } + + found = PR_TRUE; + + /* Go through each mechanism */ + for (i = 0; i < pk11_DefaultArraySize; i++) { + if (pk11_DefaultArray[i].flag & mechFlags) { + /* Enable this default mechanism */ + PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]), + PR_TRUE); + } + } + } + if (slotName && !found) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName); + errcode = NO_SUCH_SLOT_ERR; + goto loser; + } + + /* Delete and re-add module to save changes */ + if (SECMOD_UpdateModule(module) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[DEFAULT_FAILED_ERR], + moduleName); + errcode = DEFAULT_FAILED_ERR; + goto loser; + } + + PR_fprintf(PR_STDOUT, msgStrings[DEFAULT_SUCCESS_MSG]); + + errcode = SUCCESS; +loser: + if (module) { + SECMOD_DestroyModule(module); + } + return errcode; +} + +/************************************************************************ + * + * U n s e t D e f a u l t M o d u l e + */ +Error +UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms) +{ + SECMODModule *module = NULL; + PK11SlotInfo *slot; + int s, i; + unsigned long mechFlags = getFlagsFromString(mechanisms, + mechanismStrings, numMechanismStrings); + PRBool found = PR_FALSE; + Error rv; + + mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags); + + module = SECMOD_FindModule(moduleName); + if (!module) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName); + rv = NO_SUCH_MODULE_ERR; + goto loser; + } + + for (s = 0; s < module->slotCount; s++) { + slot = module->slots[s]; + if ((slotName != NULL) && + !((strcmp(PK11_GetSlotName(slot), slotName) == 0) || + (strcmp(PK11_GetTokenName(slot), slotName) == 0))) { + /* we are only interested in changing the one slot */ + continue; + } + for (i = 0; i < pk11_DefaultArraySize; i++) { + if (pk11_DefaultArray[i].flag & mechFlags) { + PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]), + PR_FALSE); + } + } + } + if (slotName && !found) { + PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName); + rv = NO_SUCH_SLOT_ERR; + goto loser; + } + + /* Delete and re-add module to save changes */ + if (SECMOD_UpdateModule(module) != SECSuccess) { + PR_fprintf(PR_STDERR, errStrings[UNDEFAULT_FAILED_ERR], + moduleName); + rv = UNDEFAULT_FAILED_ERR; + goto loser; + } + + PR_fprintf(PR_STDOUT, msgStrings[UNDEFAULT_SUCCESS_MSG]); + rv = SUCCESS; +loser: + if (module) { + SECMOD_DestroyModule(module); + } + return rv; +} diff --git a/security/nss/cmd/modutil/pk11jar.html b/security/nss/cmd/modutil/pk11jar.html new file mode 100644 index 0000000000..bb50b8f3e4 --- /dev/null +++ b/security/nss/cmd/modutil/pk11jar.html @@ -0,0 +1,279 @@ +<html> +<!-- 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/. --> +<head> +<title>PKCS #11 JAR Format</title> +</head> +<body bgcolor=white text=black link=blue vlink=purple alink=red> +<center><h1>PKCS #11 JAR Format</h1></center> + +<p>PKCS #11 modules can be packaged into JAR files that support automatic +installation onto the filesystem and into the security module database. +The JAR file should contain: +<ul> +<li>All files that will be installed onto the target machine. This will +include at least the PKCS #11 module library file (.DLL or .so), and +may also include any other file that should be installed (such as +documentation). +<li>A script to perform the installation. +</ul> +The script can be in one of two forms. If the JAR file is to be +run by Communicator (or any program that interprets Javascript), the +instructions will be in the form of a SmartUpdate script. +<a href="http://devedge/library/documentation/security/jmpkcs/">Documentation +</a> on creating this script can be found on DevEdge. + +<p>If the +JAR file is to be run by a server, modutil, or any other program that +doesn't interpret Javascript, a special information file must be included +in the format described in this document. + +<h2>Declaring the Script in the Manifest File</h2> +The script can have any name, but it must be declared in the manifest file +of the JAR archive. The metainfo tag for this is +<code>Pkcs11_install_script</code>. Meta-information is put in the manifest +file by putting it in a file which is passed to +<a href="http://developer.netscape.com/software/index_frame.html?content=signedobj/jarpack.html#signtool1.3">Signtool</a>. For example, +suppose the PKCS #11 installer script is in the file <code>pk11install</code>. +In Signtool's metainfo file, you would have a line like this: +<blockquote><pre> ++ Pkcs11_install_script: pk11install +</pre></blockquote> + +<h2>Sample Script File</h2> +<blockquote><pre> +ForwardCompatible { IRIX:6.2:mips Solaris:5.5.1:sparc } +Platforms { + WINNT::x86 { + ModuleName { "Fortezza Module" } + ModuleFile { win32/fort32.dll } + DefaultMechanismFlags{0x0001} + DefaultCipherFlags{0x0001} + Files { + win32/setup.exe { + Executable + RelativePath { %temp%/setup.exe } + } + win32/setup.hlp { + RelativePath { %temp%/setup.hlp } + } + win32/setup.cab { + RelativePath { %temp%/setup.cab } + } + } + } + WIN95::x86 { + EquivalentPlatform {WINNT::x86} + } + Solaris:5.5.1:sparc { + ModuleName { "Fortezza UNIX Module" } + ModuleFile { unix/fort.so } + DefaultMechanismFlags{0x0001} + CipherEnableFlags{0x0001} + Files { + unix/fort.so { + RelativePath{%root%/lib/fort.so} + AbsolutePath{/usr/local/netscape/lib/fort.so} + FilePermissions{555} + } + xplat/instr.html { + RelativePath{%root%/docs/inst.html} + AbsolutePath{/usr/local/netscape/docs/inst.html} + FilePermissions{555} + } + } + } + IRIX:6.2:mips { + EquivalentPlatform { Solaris:5.5.1:sparc } + } +} +</pre></blockquote> + +<hr> + +<h2>Script File Grammar</h2> +<blockquote><pre> +--> <i>valuelist</i> + +<i>valuelist</i> --> <i>value</i> <i>valuelist</i> +<i> </i> <i><null></i> + +<i>value</i> --> <i>key_value_pair</i> +<i> </i> <i>string</i> + +<i>key_value_pair</i> --> <i>key</i> { <i>valuelist</i> } + +<i>key</i> --> <i>string</i> + +<i>string</i> --> <i>simple_string</i> +<i> </i> "<i>complex_string</i>" + +<i>simple_string</i> --> [^ \t\n\""{""}"]+ <font size=-1><i>(no whitespace, quotes, or braces)</i></font> + +<i>complex_string</i> --> ([^\"\\\r\n]|(\\\")|(\\\\))+ <font size=-1><i>(quotes and backslashes must be escaped with a backslash, no newlines or carriage returns are allowed in the string)</i></font> +</pre></blockquote> +Outside of complex strings, all whitespace (space, tab, newline) is considered +equal and is used only to delimit tokens. + +<hr> + +<h2>Keys</h2> +Keys are case-insensitive. +<h3>Global Keys</h3> +<dl> +<dt><code>ForwardCompatible</code> +<dd>Gives a list of platforms that are forward compatible. If the current +platform cannot be found in the list of supported platforms, then the +ForwardCompatible list will be checked for any platforms that have the same +OS and architecture and an earlier version. If one is found, its +attributes will be used for the current platform. +<dt><code>Platforms</code> (<i>required</i>) +<dd>Gives a list of platforms. Each entry in the list is itself a key-value +pair: +the key is the name of the platform, and the valuelist contains various +attributes of the platform. The ModuleName, ModuleFile, and Files attributes +must be specified, unless an EquivalentPlatform attribute is specified. +The platform string is in the following +format: <u><i>system name</i></u>:<u><i>os release</i></u>:<u><i>architecture</i></u>. The installer +will obtain these values from NSPR. <u><i>os release</i></u> is an empty +string on non-UNIX operating systems. The following system names and platforms +are currently defined by NSPR:<code> +<ul> +<li>AIX (rs6000) +<li>BSDI (x86) +<li>FREEBSD (x86) +<li>HPUX (hppa1.1) +<li>IRIX (mips) +<li>LINUX (ppc, alpha, x86) +<li>MacOS (PowerPC) </code>(<i>Note: NSPR actually defines the OS as +"</i><code>Mac OS</code><i>". The +space makes the name unsuitable for being embedded in identifiers. Until +NSPR changes, you will have to add some special code to deal with this case. +</i>)<code> +<li>NCR (x86) +<li>NEC (mips) +<li>OS2 (x86) +<li>OSF (alpha) +<li>ReliantUNIX (mips) +<li>SCO (x86) +<li>SOLARIS (sparc) +<li>SONY (mips) +<li>SUNOS (sparc) +<li>UnixWare (x86) +<li>WIN95 (x86) +<li>WINNT (x86) +</ul> +</code> +Examples of valid platform strings: <code>IRIX:6.2:mips, Solaris:5.5.1:sparc, +Linux:2.0.32:x86, WIN95::x86</code>. +</dl> + +<h3>Per-Platform Keys</h3> +These keys only have meaning within the value list of an entry in +the <code>Platforms</code> list. +<dl> +<dt><code>ModuleName</code> (<i>required</i>) +<dd>Gives the common name for the module. This name will be used to +reference the module from Communicator, modutil, servers, or any other +program that uses the Netscape security module database. +<dt><code>ModuleFile</code> (<i>required</i>) +<dd>Names the PKCS #11 module file (DLL or .so) for this platform. The name +is given as the relative path of the file within the JAR archive. +<dt><code>Files</code> (<i>required</i>) +<dd>Lists the files that should be installed for this module. Each entry +in the file list is a key-value pair: the key is the path of the file in +the JAR archive, and +the valuelist contains attributes of the file. At least RelativePath and +AbsoluteDir must be specified in this valuelist. +<dt><code>DefaultMechanismFlags</code> +<dd>This key-value pair specifies +of which mechanisms this module will be a default provider. It is a bitstring +specified in hexadecimal (0x) format. It is constructed as a bitwise OR +of the following constants. If the <code>DefaultMechanismFlags</code> +entry is omitted, the value will default to 0x0. +<blockquote><pre> +RSA: 0x0000 0001 +DSA: 0x0000 0002 +RC2: 0x0000 0004 +RC4: 0x0000 0008 +DES: 0x0000 0010 +DH: 0x0000 0020 +FORTEZZA: 0x0000 0040 +RC5: 0x0000 0080 +SHA1: 0x0000 0100 +MD5: 0x0000 0200 +MD2: 0x0000 0400 +RANDOM: 0x0800 0000 +FRIENDLY: 0x1000 0000 +OWN_PW_DEFAULTS: 0x2000 0000 +DISABLE: 0x4000 0000 +</pre></blockquote> +<dt><code>CipherEnableFlags</code> +<dd>This key-value pair specifies +which SSL ciphers will be enabled. It is a bitstring specified in +hexadecimal (0x) format. It is constructed as a bitwise OR of the following +constants. If the <code>CipherEnableFlags</code> entry is omitted, the +value will default to 0x0. +<blockquote><pre> +FORTEZZA: 0x0000 0001 +</pre></blockquote> +<dt><code>EquivalentPlatform</code> +<dd>Specifies that the attributes of the named platform should also be used +for the current platform. Saves typing when there is more than one platform +that uses the same settings. +</dl> + +<h3>Per-File Keys</h3> +These keys only have meaning within the valuelist of an entry in a +<code>Files</code> list. At least one of <code>RelativePath</code> and +<code>AbsolutePath</code> must be specified. If both are specified, the +relative path will be tried first and the absolute path used only if no +relative root directory is provided by the installer program. +<dl> +<dt><code>RelativePath</code> +<dd>Specifies the destination directory of the file, relative to some directory +decided at install-time. Two variables can be used in the relative +path, "%root%" and "%temp%". "%root%" will be replaced at run-time with +the directory relative to which files should be installed; for +example, it may be the server's root directory or Communicator's root +directory. "%temp%" is a directory that will be created at the beginning +of the installation and destroyed at the end of the installation. Its purpose +is to hold executable files (such as setup programs), or files that are +used by these programs. For example, a Windows installation might consist +of a <code>setup.exe</code> installation program, a help file, and a .cab file +containing compressed information. All these files could be installed into the +temporary directory. Files destined for the temporary directory are guaranteed +to be in place before any executable file is run, and will not be deleted +until all executable files have finished. +<dt><code>AbsoluteDir</code> +<dd>Specifies the destination directory of the file as an absolute path. +This will only be used if the installer is unable to determine a +relative directory. +<dt><code>Executable</code> +<dd>This string specifies that the file is to be executed during the +course of the +installation. Typically this would be used for a setup program provided +by a module vendor, such as a self-extracting <code>setup.exe</code>. +More than one file can be specified as executable, in which case they will +be run in the order they are specified in the script file. +<dt><code>FilePermissions</code> +<dd>This string is interpreted as a string of octal digits, according to the +standard UNIX format. It is a bitwise OR of the following constants: +<blockquote><pre> +user read: 400 +user write: 200 +user execute: 100 +group read: 040 +group write: 020 +group execute: 010 +other read: 004 +other write: 002 +other execute: 001 +</pre></blockquote> +Some platforms may not understand these permissions. They will only be +applied insofar as makes sense for the current platform. If this attribute +is omitted, a default of 777 is assumed. + +</body> +</html> diff --git a/security/nss/cmd/modutil/rules.mk b/security/nss/cmd/modutil/rules.mk new file mode 100644 index 0000000000..3ad6a97f1e --- /dev/null +++ b/security/nss/cmd/modutil/rules.mk @@ -0,0 +1,26 @@ +# +# 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/. + +# +# Some versions of yacc generate files that include platform-specific +# system headers. For example, the yacc in Solaris 2.6 inserts +# #include <values.h> +# which does not exist on NT. For portability, always use Berkeley +# yacc (such as the yacc in Linux) to generate files. +# + +generate: installparse.c installparse.l + +installparse.c: + yacc -p Pk11Install_yy -d installparse.y + mv y.tab.c installparse.c + mv y.tab.h installparse.h + +installparse.l: + lex -olex.Pk11Install_yy.c -PPk11Install_yy installparse.l + @echo + @echo "**YOU MUST COMMENT OUT UNISTD.H FROM lex.Pk11Install_yy.cpp**" + +install.c: install-ds.h install.h diff --git a/security/nss/cmd/modutil/specification.html b/security/nss/cmd/modutil/specification.html new file mode 100644 index 0000000000..6477a37cef --- /dev/null +++ b/security/nss/cmd/modutil/specification.html @@ -0,0 +1,322 @@ +<html> +<!-- 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/. --> +<head> +<title>Modutil Specification</title> +</head> +<body bgcolor=white fgcolor=black> +<center><h1>PKCS #11 Module Management Utility +<br><i>Specification</i></h1></center> + +<!----------------------------------------------------------------------> +<!-------------------------- capabilities ------------------------------> +<!----------------------------------------------------------------------> +<h2>Capabilities</h2> +<ul> +<li>Add a PKCS #11 module, specifying a name and library file. +(<a href="#add">-add</a>) +<li>Add a PKCS #11 module from a server-formatted JAR file. +(<a href="#jar">-jar</a>) +<li>Change the password on or initialize a token. +(<a href="#changepw">-changepw</a>) +<li>Create databases (secmod[ule].db, key3.db, cert7.db) from scratch. +(<a href="#create">-create</a>) +<li>Switch to and from FIPS-140 compliant mode. +(<a href="#fips">-fips</a>) +<li>Delete a PKCS #11 module. (<a href="#delete">-delete</a>) +<li>List installed PKCS #11 modules. (<a href="#list">-list</a>) +<li>List detailed info on a particular module and its tokens, including +whether needs login, is hardware, needs user init +(<a href="#list">-list</a>) +<li>Specify which modules should be the default provider of various +cryptographic operations.(<a href="#default">-default</a>, +<a href="#undefault">-undefault</a>) +<li>Disable and enable slots, find out whether and why they are disabled. +(<a href="#disable">-disable</a>, <a href="#enable">-enable</a>, +<a href="#list">-list</a>) +</ul> + +<hr> + +<!----------------------------------------------------------------------> +<!-------------------------- Usage -------------------------------------> +<!----------------------------------------------------------------------> +<h2>Usage</h2> +<code>modutil [<i>command</i>] [<i>options</i>]</code> +<p>At most one command can be specified. With no arguments, +<code>modutil</code> prints a usage message. +<h3>Commands:</h3> +<table border> +<tr bgcolor="#cccccc"> +<th>Command</th><th>Description</th> +</tr> + +<!---------------------------- -add ------------------------------> +<tr> +<td> <a name="add"></a> +<code>-add <u><i>module name</i></u> -libfile <u><i>library file</i></u> + [-ciphers <u><i>cipher enable list</i></u>] + [-mechanisms <u><i>default mechanism list</i></u>] +</code></td> +<td>Adds a new module to the database with the given name. + +<p><u><i>library file</i></u> is the path of the DLL or other library file +containing the module's implementation of the PKCS #11 interface. + +<p><u><i>cipher enable flags</i></u> is a colon-separated list of ciphers +that will be enabled on this module. The list should be enclosed within quotes +if necessary to prevent shell interpretation. The following ciphers are +currently available: +<ul> +<li>FORTEZZA +</ul> + +<p><u><i>default mechanism flags</i></u> is a colon-separated list of +mechanisms for which this module should be the default provider. The +list should be enclosed within quotes if necessary to prevent shell +interpretation. <b>This +list does not enable the mechanisms; it only specifies that this module +will be a default provider for the listed mechanisms.</b> If more than +one module claims to be a default provider for a given mechanism, it is +undefined which will actually be chosen to provide that mechanism. The +following mechanisms are currently available: +<ul> +<li>RSA +<li>DSA +<li>RC2 +<li>RC4 +<li>RC5 +<li>DES +<li>DH +<li>FORTEZZA +<li>SHA1 +<li>MD5 +<li>MD2 +<li>RANDOM <i>(random number generation)</i> +<li>FRIENDLY <i>(certificates are publicly-readable)</i> +</ul> +</td> +</tr> + +<!-------------------------- -changepw -------------------------------------> +<tr> +<td><a name="changepw"></a><code>-changepw <u><i>token name</i></u> +[-pwfile <u><i>old password file</i></u>] +[-newpwfile <u><i>new password file</i></u>]</code></td> +<td>Changes the password on the named token. If the token has not been +initialized, this command will initialize the PIN. +If a password file is given, the password will be read from that file; +otherwise, the password will be obtained interactively. +<b>Storing passwords in a file is much less secure than supplying them +interactively.</b> +<p>The password on the Netscape internal module cannot be changed if +the <code>-nocertdb</code> option is specified. +</td> +</tr> + +<!-------------------------- -create -------------------------------------> +<tr> +<td><a name="create"></a><code>-create</code></td> +<td>Creates a new secmod[ule].db, key3.db, and cert7.db in the directory +specified with the +<code>-dbdir</code> option, if one is specified. If no directory is +specified, UNIX systems will use the user's .netscape directory, while other +systems will return with an error message. If any of these databases already +exist in the chosen directory, an error message is returned. +<p>If used with <code>-nocertdb</code>, only secmod[ule].db will be created; +cert7.db and key3.db will not be created. +</td> +</tr> + +<!------------------------------ -default --------------------------------> +<tr> +<td> <a name="default"></a> <code>-default <u><i>module name</i></u> +-mechanisms <u><i>mechanism list</i></u></code> +</td> +<td>Specifies that the given module will be a default provider of the +listed mechanisms. The mechanism list is the same as in the <code>-add</code> +command. +</td> +</tr> + +<!-------------------------- -delete -------------------------------------> +<tr> +<td><a name="delete"></a><code>-delete <u><i>module name</i></u></code></td> +<td>Deletes the named module from the database</td> +</tr> + +<!-------------------------- -disable -------------------------------------> +<tr> +<td> <a name="disable"></a> <code>-disable <u><i>module name</i></u> +[-slot <u><i>slot name</i></u>]</code></td> +<td>Disables the named slot. If no slot is specified, all slots on +the module are disabled.</td> +</tr> + +<!-------------------------- -enable -------------------------------------> +<tr> +<td> <a name="enable"></a> <code>-enable <u><i>module name</i></u> +[-slot <u><i>slot name</i></u>]</code></td> +<td>Enables the named slot. If no slot is specified, all slots on +the module are enabled.</td> +</tr> + +<!-------------------------- -fips -------------------------------------> +<tr> +<td><a name="fips"></a><code>-fips [true | false]</code></td> +<td>Enables or disables FIPS mode on the internal module. Passing +<code>true</code> enables FIPS mode, passing <code>false</code> disables +FIPS mode.</td> +</tr> + +<!-------------------------- -force -------------------------------------> +<tr> +<td><a name="force"></a><code>-force</code></td> +<td>Disables interactive prompts, so modutil can be run in a script. +Should only be used by experts, since the prompts may relate to security +or database integrity. Before using this option, test the command +interactively once to see the warnings that are produced.</td> +</tr> + +<!-------------------------- -jar -------------------------------------> +<tr> +<td><a name="jar"></a><code>-jar <u><i>JAR file</i></u> +-installdir <u><i>root installation directory</i></u> +[-tempdir <u><i>temporary directory</i></u>]</code></td> +<td>Adds a new module from the given JAR file. The JAR file uses the +server <a href="pk11jar.html">PKCS #11 JAR format</a> to describe the names of +any files that need to be installed, the name of the module, mechanism flags, +and cipher flags. The <u><i>root installation directory</i></u> +is the directory relative to which files will be installed. This should be a + directory +under which it would be natural to store dynamic library files, such as +a server's root directory, or Communicator's root directory. +The <u><i>temporary directory</i></u> is where temporary modutil files +will be created in the course of the installation. If no temporary directory +is specified, the current directory will be used. +<p>If used with the <code>-nocertdb</code> option, the signatures on the JAR +file will not be checked.</td> +</tr> + +<!----------------------------- -list ------------------------------> +<tr> +<td><a name="list"></a><code>-list [<u><i>module name</i></u>]</code></td> +<td>Without an argument, lists the PKCS #11 modules present in the module +database. +<blockquote> +<pre> +% <b>modutil -list</b> +Using database directory /u/nicolson/.netscape... + +Listing of PKCS #11 Modules +----------------------------------------------------------- + 1. Netscape Internal PKCS #11 Module + slots: 2 slots attached + status: loaded + + slot: Communicator Internal Cryptographic Services Version 4.0 + token: Communicator Generic Crypto Svcs + + slot: Communicator User Private Key and Certificate Services + token: Communicator Certificate DB +----------------------------------------------------------- +</pre> +</blockquote> +<p>With an argument, provides a detailed description of the named module +and its slots and tokens. +<blockquote> +<pre> +% <b>modutil -list "Netscape Internal PKCS #11 Module"</b> +Using database directory /u/nicolson/.netscape... + +----------------------------------------------------------- +Name: Netscape Internal PKCS #11 Module +Library file: **Internal ONLY module** +Manufacturer: Netscape Communications Corp +Description: Communicator Internal Crypto Svc +PKCS #11 Version 2.0 +Library Version: 4.0 +Cipher Enable Flags: None +Default Mechanism Flags: RSA:DSA:RC2:RC4:DES:SHA1:MD5:MD2 + + Slot: Communicator Internal Cryptographic Services Version 4.0 + Manufacturer: Netscape Communications Corp + Type: Software + Version Number: 4.1 + Firmware Version: 0.0 + Status: Enabled + Token Name: Communicator Generic Crypto Svcs + Token Manufacturer: Netscape Communications Corp + Token Model: Libsec 4.0 + Token Serial Number: 0000000000000000 + Token Version: 4.0 + Token Firmware Version: 0.0 + Access: Write Protected + Login Type: Public (no login required) + User Pin: NOT Initialized + + Slot: Communicator User Private Key and Certificate Services + Manufacturer: Netscape Communications Corp + Type: Software + Version Number: 3.0 + Firmware Version: 0.0 + Status: Enabled + Token Name: Communicator Certificate DB + Token Manufacturer: Netscape Communications Corp + Token Model: Libsec 4.0 + Token Serial Number: 0000000000000000 + Token Version: 7.0 + Token Firmware Version: 0.0 + Access: NOT Write Protected + Login Type: Login required + User Pin: Initialized + +----------------------------------------------------------- +</pre> +</blockquote> +</td> +</tr> + +<!------------------------------ Undefault -------------------------------> +<tr> +<td><a name="undefault"></a><code>-undefault <u><i>module name</i></u> +-mechanisms <u><i>mechanism list</i></u></code></td> +<td>Specifies that the given module will NOT be a default provider of +the listed mechanisms. This command clears the default mechanism flags +for the given module.</td> +</tr> + +</table> + +<!------------------------------------------------------------------------> +<!------------------------------ Options ---------------------------------> +<!------------------------------------------------------------------------> +<h3>Options:</h3> +<table border> +<tr bgcolor="#cccccc"><th>Option</th><th>Description</th> </tr> + +<!------------------------------ -dbdir ----------------------------------> +<tr> +<td><code>-dbdir <u><i>directory</i></u></code></td> +<td>Specifies which directory holds the module database. On UNIX systems, +the user's netscape directory is the default. On other systems, there is +no default, and this option must be used.</td> +</tr> + +<!------------------------------ -dbdir ----------------------------------> +<tr> +<td><code>-nocertdb</code></td> +<td>Do not open the certificate or key databases. This has several effects. +With the <code>-create</code> command, this means that only a secmod.db file +will be created; cert7.db and key3.db will not be created. With the +<code>-jar</code> command, signatures on the JAR file will not be checked. +With the <code>-changepw</code> command, the password on the Netscape internal +module cannot be set or changed, since this password is stored in key3.db. +</td> +</tr> + +</table> + +</body> +</html> |