diff options
Diffstat (limited to 'nss/cmd/modutil')
-rw-r--r-- | nss/cmd/modutil/Makefile | 58 | ||||
-rw-r--r-- | nss/cmd/modutil/README | 7 | ||||
-rw-r--r-- | nss/cmd/modutil/error.h | 139 | ||||
-rw-r--r-- | nss/cmd/modutil/install-ds.c | 1515 | ||||
-rw-r--r-- | nss/cmd/modutil/install-ds.h | 261 | ||||
-rw-r--r-- | nss/cmd/modutil/install.c | 961 | ||||
-rw-r--r-- | nss/cmd/modutil/install.h | 101 | ||||
-rw-r--r-- | nss/cmd/modutil/installparse.c | 433 | ||||
-rw-r--r-- | nss/cmd/modutil/installparse.h | 7 | ||||
-rw-r--r-- | nss/cmd/modutil/installparse.l | 137 | ||||
-rw-r--r-- | nss/cmd/modutil/installparse.y | 104 | ||||
-rw-r--r-- | nss/cmd/modutil/instsec.c | 150 | ||||
-rw-r--r-- | nss/cmd/modutil/lex.Pk11Install_yy.c | 1660 | ||||
-rw-r--r-- | nss/cmd/modutil/manifest.mn | 34 | ||||
-rw-r--r-- | nss/cmd/modutil/modutil.c | 973 | ||||
-rw-r--r-- | nss/cmd/modutil/modutil.h | 40 | ||||
-rw-r--r-- | nss/cmd/modutil/pk11.c | 964 | ||||
-rw-r--r-- | nss/cmd/modutil/pk11jar.html | 279 | ||||
-rw-r--r-- | nss/cmd/modutil/rules.mk | 26 | ||||
-rw-r--r-- | nss/cmd/modutil/specification.html | 322 |
20 files changed, 8171 insertions, 0 deletions
diff --git a/nss/cmd/modutil/Makefile b/nss/cmd/modutil/Makefile new file mode 100644 index 0000000..1a64b47 --- /dev/null +++ b/nss/cmd/modutil/Makefile @@ -0,0 +1,58 @@ +#! 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 + +ifdef USE_SYSTEM_ZLIB +OS_LIBS += $(ZLIB_LIBS) +else +EXTRA_LIBS += $(ZLIB_LIBS) +endif + +####################################################################### +# (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/nss/cmd/modutil/README b/nss/cmd/modutil/README new file mode 100644 index 0000000..12d192c --- /dev/null +++ b/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/nss/cmd/modutil/error.h b/nss/cmd/modutil/error.h new file mode 100644 index 0000000..ba42264 --- /dev/null +++ b/nss/cmd/modutil/error.h @@ -0,0 +1,139 @@ +/* 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, + + 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" +}; + +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, + + LAST_MSG /* must be last */ +} Message; + +/* defined in modutil.c */ +extern char *msgStrings[]; + +#endif /* MODUTIL_ERROR_H */ diff --git a/nss/cmd/modutil/install-ds.c b/nss/cmd/modutil/install-ds.c new file mode 100644 index 0000000..2ae376d --- /dev/null +++ b/nss/cmd/modutil/install-ds.c @@ -0,0 +1,1515 @@ +/* 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 i; for(i=0;i<x;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); + subiter = NULL; + + /* 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); + subiter = NULL; + + /* 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); + subiter = NULL; + } + } 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); + PR_Free(iter); + } + if(subiter) { + Pk11Install_ListIter_delete(subiter); + PR_Free(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++) { + sprintf(buf, "%s.", _this->verString[i]); + strcat(tmp, buf); + } + if(i < _this->numDigits) { + sprintf(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) +{ + PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>"); + PAD(pad); printf("Digits: "); + if(_this->numDigits == 0) { + printf("None\n"); + } else { + printf("%s\n", Pk11Install_PlatformName_GetVerString(_this)); + } + 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); + PR_Free(subiter); + subiter = NULL; + 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); + PR_Free(subiter); + subiter = NULL; + 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); + PR_Free(subiter); + subiter=NULL; + 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); + PR_Free(subiter); + subiter=NULL; + 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); + 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); + PR_Free(subiter); + subiter = NULL; + } 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); + PR_Free(subiter); + subiter = NULL; + } + } + } + + 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); + PR_Free(iter); + iter = NULL; + } + if(subiter) { + Pk11Install_ListIter_delete(subiter); + PR_Free(subiter); + subiter = NULL; + } + 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; +} + +/****************************************************************************/ +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/nss/cmd/modutil/install-ds.h b/nss/cmd/modutil/install-ds.h new file mode 100644 index 0000000..3a3afb3 --- /dev/null +++ b/nss/cmd/modutil/install-ds.h @@ -0,0 +1,261 @@ +/* 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(); +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/nss/cmd/modutil/install.c b/nss/cmd/modutil/install.c new file mode 100644 index 0000000..bcc7c7e --- /dev/null +++ b/nss/cmd/modutil/install.c @@ -0,0 +1,961 @@ +/* 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. + */ + +#ifdef OSF1 +/* stdarg has already been pulled in from NSPR */ +#undef va_start +#undef va_end +#undef va_arg +#include <varargs.h> +#else +#include <stdarg.h> +#endif + +#ifdef OSF1 +static void +error(long va_alist, ...) +#else +static void +error(Pk11Install_Error errcode, ...) +#endif +{ + + va_list ap; + char *errstr; + Pk11Install_ErrorHandler handler; + + if(!errorHandlerLock) { + errorHandlerLock = PR_NewLock(); + } + + PR_Lock(errorHandlerLock); + + handler = errorHandler; + + PR_Unlock(errorHandlerLock); + + if(handler) { +#ifdef OSF1 + va_start(ap); + errstr = PR_vsmprintf(errorString[va_arg(ap, Pk11Install_Error)], ap); +#else + va_start(ap, errcode); + errstr = PR_vsmprintf(errorString[errcode], ap); +#endif + 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); + PR_Free(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 *reldir; + char *dest; + 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; + reldir=NULL; + dest=NULL; + 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++) { + file = &platform->files[i]; + + if(file->relativePath) { + PRBool foundMarker = PR_FALSE; + reldir = PR_Strdup(file->relativePath); + + /* 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; + goto loser; + } + dest = reldir; + reldir = NULL; + } else if(file->absolutePath) { + dest = PR_Strdup(file->absolutePath); + } + + /* 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 + chmod(dest, file->permissions); +#endif + + /* Memory clean-up tasks */ + if(reldir) { + PR_Free(reldir); + reldir = NULL; + } + if(dest) { + PR_Free(dest); + dest = NULL; + } + } + /* 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(reldir) { + PR_Free(reldir); + } + if(dest) { + PR_Free(dest); + } + 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) { + sprintf(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/nss/cmd/modutil/install.h b/nss/cmd/modutil/install.h new file mode 100644 index 0000000..d946118 --- /dev/null +++ b/nss/cmd/modutil/install.h @@ -0,0 +1,101 @@ +/* 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/nss/cmd/modutil/installparse.c b/nss/cmd/modutil/installparse.c new file mode 100644 index 0000000..3691c63 --- /dev/null +++ b/nss/cmd/modutil/installparse.c @@ -0,0 +1,433 @@ +/* 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 +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, +}; +#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 *getenv(); + + if ((yys = getenv("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/nss/cmd/modutil/installparse.h b/nss/cmd/modutil/installparse.h new file mode 100644 index 0000000..2c02b57 --- /dev/null +++ b/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/nss/cmd/modutil/installparse.l b/nss/cmd/modutil/installparse.l new file mode 100644 index 0000000..71fb561 --- /dev/null +++ b/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/nss/cmd/modutil/installparse.y b/nss/cmd/modutil/installparse.y new file mode 100644 index 0000000..b6d7011 --- /dev/null +++ b/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/nss/cmd/modutil/instsec.c b/nss/cmd/modutil/instsec.c new file mode 100644 index 0000000..284e489 --- /dev/null +++ b/nss/cmd/modutil/instsec.c @@ -0,0 +1,150 @@ +/* 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/nss/cmd/modutil/lex.Pk11Install_yy.c b/nss/cmd/modutil/lex.Pk11Install_yy.c new file mode 100644 index 0000000..4533e0c --- /dev/null +++ b/nss/cmd/modutil/lex.Pk11Install_yy.c @@ -0,0 +1,1660 @@ +/* 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__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#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__ +#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/nss/cmd/modutil/manifest.mn b/nss/cmd/modutil/manifest.mn new file mode 100644 index 0000000..a92ca68 --- /dev/null +++ b/nss/cmd/modutil/manifest.mn @@ -0,0 +1,34 @@ +# +# 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 + +EXPORTS = + +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/nss/cmd/modutil/modutil.c b/nss/cmd/modutil/modutil.c new file mode 100644 index 0000000..6421202 --- /dev/null +++ b/nss/cmd/modutil/modutil.c @@ -0,0 +1,973 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* To edit this file, set TABSTOPS to 4 spaces. + * This is not the normal NSS convention. + */ + +#include "modutil.h" +#include "install.h" +#include <plstr.h> +#include "certdb.h" /* for CERT_DB_FILE_VERSION */ +#include "nss.h" + +static void install_error(char *message); +static char* PR_fgets(char *buf, int size, PRFileDesc *file); +static char *progName; + + +/* This enum must be kept in sync with the commandNames list */ +typedef enum { + NO_COMMAND, + ADD_COMMAND, + CHANGEPW_COMMAND, + CREATE_COMMAND, + DEFAULT_COMMAND, + DELETE_COMMAND, + DISABLE_COMMAND, + ENABLE_COMMAND, + FIPS_COMMAND, + JAR_COMMAND, + LIST_COMMAND, + RAW_LIST_COMMAND, + RAW_ADD_COMMAND, + CHKFIPS_COMMAND, + UNDEFAULT_COMMAND +} Command; + +/* This list must be kept in sync with the Command enum */ +static char *commandNames[] = { + "(no command)", + "-add", + "-changepw", + "-create", + "-default", + "-delete", + "-disable", + "-enable", + "-fips", + "-jar", + "-list", + "-rawlist", + "-rawadd", + "-chkfips", + "-undefault" +}; + + +/* this enum must be kept in sync with the optionStrings list */ +typedef enum { + ADD_ARG=0, + RAW_ADD_ARG, + CHANGEPW_ARG, + CIPHERS_ARG, + CREATE_ARG, + DBDIR_ARG, + DBPREFIX_ARG, + DEFAULT_ARG, + DELETE_ARG, + DISABLE_ARG, + ENABLE_ARG, + FIPS_ARG, + FORCE_ARG, + JAR_ARG, + LIBFILE_ARG, + LIST_ARG, + RAW_LIST_ARG, + MECHANISMS_ARG, + NEWPWFILE_ARG, + PWFILE_ARG, + SLOT_ARG, + UNDEFAULT_ARG, + INSTALLDIR_ARG, + TEMPDIR_ARG, + SECMOD_ARG, + NOCERTDB_ARG, + STRING_ARG, + CHKFIPS_ARG, + + NUM_ARGS /* must be last */ +} Arg; + +/* This list must be kept in sync with the Arg enum */ +static char *optionStrings[] = { + "-add", + "-rawadd", + "-changepw", + "-ciphers", + "-create", + "-dbdir", + "-dbprefix", + "-default", + "-delete", + "-disable", + "-enable", + "-fips", + "-force", + "-jar", + "-libfile", + "-list", + "-rawlist", + "-mechanisms", + "-newpwfile", + "-pwfile", + "-slot", + "-undefault", + "-installdir", + "-tempdir", + "-secmod", + "-nocertdb", + "-string", + "-chkfips", +}; + +char *msgStrings[] = { + "FIPS mode enabled.\n", + "FIPS mode disabled.\n", + "Using database directory %s...\n", + "Creating \"%s\"...", + "Module \"%s\" added to database.\n", + "Module \"%s\" deleted from database.\n", + "Token \"%s\" password changed successfully.\n", + "Incorrect password, try again...\n", + "Passwords do not match, try again...\n", + "done.\n", + "Slot \"%s\" %s.\n", + "Successfully changed defaults.\n", + "Successfully changed defaults.\n", +"\nWARNING: Performing this operation while the browser is running could cause" +"\ncorruption of your security databases. If the browser is currently running," +"\nyou should exit browser before continuing this operation. Type " +"\n'q <enter>' to abort, or <enter> to continue: ", + "\nAborting...\n" +}; + +/* Increment i if doing so would have i still be less than j. If you + are able to do this, return 0. Otherwise return 1. */ +#define TRY_INC(i,j) ( ((i+1)<j) ? (++i, 0) : 1 ) + +/******************************************************************** + * + * file-wide variables obtained from the command line + */ +static Command command = NO_COMMAND; +static char* pwFile = NULL; +static char* newpwFile = NULL; +static char* moduleName = NULL; +static char* moduleSpec = NULL; +static char* slotName = NULL; +static char* secmodName = NULL; +static char* tokenName = NULL; +static char* libFile = NULL; +static char* dbdir = NULL; +static char* dbprefix = ""; +static char* secmodString = NULL; +static char* mechanisms = NULL; +static char* ciphers = NULL; +static char* fipsArg = NULL; +static char* jarFile = NULL; +static char* installDir = NULL; +static char* tempDir = NULL; +static short force = 0; +static PRBool nocertdb = PR_FALSE; + +/******************************************************************* + * + * p a r s e _ a r g s + */ +static Error +parse_args(int argc, char *argv[]) +{ + int i; + char *arg; + int optionType; + + /* Loop over all arguments */ + for(i=1; i < argc; i++) { + arg = argv[i]; + + /* Make sure this is an option and not some floating argument */ + if(arg[0] != '-') { + PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]); + return UNEXPECTED_ARG_ERR; + } + + /* Find which option this is */ + for(optionType=0; optionType < NUM_ARGS; optionType++) { + if(! strcmp(arg, optionStrings[optionType])) { + break; + } + } + + /* Deal with this specific option */ + switch(optionType) { + case NUM_ARGS: + default: + PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg); + return UNKNOWN_OPTION_ERR; + break; + case ADD_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = ADD_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleName = argv[i]; + break; + case CHANGEPW_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = CHANGEPW_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + tokenName = argv[i]; + break; + case CIPHERS_ARG: + if(ciphers != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + ciphers = argv[i]; + break; + case CREATE_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = CREATE_COMMAND; + break; + case DBDIR_ARG: + if(dbdir != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + dbdir = argv[i]; + break; + case DBPREFIX_ARG: + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + dbprefix = argv[i]; + break; + case UNDEFAULT_ARG: + case DEFAULT_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + if(optionType == DEFAULT_ARG) { + command = DEFAULT_COMMAND; + } else { + command = UNDEFAULT_COMMAND; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleName = argv[i]; + break; + case DELETE_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = DELETE_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleName = argv[i]; + break; + case DISABLE_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = DISABLE_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleName = argv[i]; + break; + case ENABLE_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = ENABLE_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleName = argv[i]; + break; + case FIPS_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = FIPS_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + fipsArg = argv[i]; + break; + case CHKFIPS_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = CHKFIPS_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + fipsArg = argv[i]; + break; + case FORCE_ARG: + force = 1; + break; + case NOCERTDB_ARG: + nocertdb = PR_TRUE; + break; + case INSTALLDIR_ARG: + if(installDir != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + installDir = argv[i]; + break; + case TEMPDIR_ARG: + if(tempDir != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + tempDir = argv[i]; + break; + case JAR_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = JAR_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + jarFile = argv[i]; + break; + case LIBFILE_ARG: + if(libFile != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + libFile = argv[i]; + break; + case LIST_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = LIST_COMMAND; + /* This option may or may not have an argument */ + if( (i+1 < argc) && (argv[i+1][0] != '-') ) { + moduleName = argv[++i]; + } + break; + case RAW_LIST_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = RAW_LIST_COMMAND; + /* This option may or may not have an argument */ + if( (i+1 < argc) && (argv[i+1][0] != '-') ) { + moduleName = argv[++i]; + } + break; + case RAW_ADD_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = RAW_ADD_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleSpec = argv[i]; + break; + case MECHANISMS_ARG: + if(mechanisms != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + mechanisms = argv[i]; + break; + case NEWPWFILE_ARG: + if(newpwFile != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + newpwFile = argv[i]; + break; + case PWFILE_ARG: + if(pwFile != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + pwFile = argv[i]; + break; + case SLOT_ARG: + if(slotName != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + slotName = argv[i]; + break; + case SECMOD_ARG: + if(secmodName != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + secmodName = argv[i]; + break; + case STRING_ARG: + if(secmodString != NULL) { + PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); + return DUPLICATE_OPTION_ERR; + } + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + secmodString = argv[i]; + break; + } + } + return SUCCESS; +} + +/************************************************************************ + * + * v e r i f y _ p a r a m s + */ +static Error +verify_params() +{ + switch(command) { + case ADD_COMMAND: + if(libFile == NULL) { + PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR], + commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]); + return MISSING_PARAM_ERR; + } + break; + case CHANGEPW_COMMAND: + break; + case CREATE_COMMAND: + break; + case DELETE_COMMAND: + break; + case DISABLE_COMMAND: + break; + case ENABLE_COMMAND: + break; + case FIPS_COMMAND: + case CHKFIPS_COMMAND: + if(PL_strcasecmp(fipsArg, "true") && + PL_strcasecmp(fipsArg, "false")) { + PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]); + return INVALID_FIPS_ARG; + } + break; + case JAR_COMMAND: + if(installDir == NULL) { + PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR], + commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]); + return MISSING_PARAM_ERR; + } + break; + case LIST_COMMAND: + case RAW_LIST_COMMAND: + break; + case RAW_ADD_COMMAND: + break; + case UNDEFAULT_COMMAND: + case DEFAULT_COMMAND: + if(mechanisms == NULL) { + PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR], + commandNames[command], optionStrings[MECHANISMS_ARG]); + return MISSING_PARAM_ERR; + } + break; + default: + /* Ignore this here */ + break; + } + + return SUCCESS; +} + +/******************************************************************** + * + * i n i t _ c r y p t o + * + * Does crypto initialization that all commands will require. + * If -nocertdb option is specified, don't open key or cert db (we don't + * need them if we aren't going to be verifying signatures). This is + * because serverland doesn't always have cert and key database files + * available. + * + * This function is ill advised. Names and locations of databases are + * private to NSS proper. Such functions only confuse other users. + * + */ +static Error +check_crypto(PRBool create, PRBool readOnly) +{ + char *dir; + char *moddbname=NULL; + Error retval; + static const char multiaccess[] = { "multiaccess:" }; + + dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */ + if (dir[0] == '\0') { + PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]); + retval=NO_DBDIR_ERR; + goto loser; + } + if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) { + /* won't attempt to handle the multiaccess case. */ + return SUCCESS; + } +#ifdef notdef + /* Make sure db directory exists and is readable */ + if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir); + retval = DIR_DOESNT_EXIST_ERR; + goto loser; + } else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir); + retval = DIR_NOT_READABLE_ERR; + goto loser; + } + + if (secmodName == NULL) { + secmodName = "secmod.db"; + } + + moddbname = PR_smprintf("%s/%s", dir, secmodName); + if (!moddbname) + return OUT_OF_MEM_ERR; + + /* Check for the proper permissions on databases */ + if(create) { + /* Make sure dbs don't already exist, and the directory is + writeable */ + if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR], + moddbname); + retval=FILE_ALREADY_EXISTS_ERR; + goto loser; + } else + if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir); + retval=DIR_NOT_WRITEABLE_ERR; + goto loser; + } + } else { + /* Make sure dbs are readable and writeable */ + if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname); + retval=FILE_NOT_READABLE_ERR; + goto loser; + } + + /* Check for write access if we'll be making changes */ + if( !readOnly ) { + if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { + PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR], + moddbname); + retval=FILE_NOT_WRITEABLE_ERR; + goto loser; + } + } + PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG], + SECU_ConfigDirectory(NULL)); + } +#endif + retval=SUCCESS; +loser: + if (moddbname) { + PR_Free(moddbname); + } + return retval; +} + +static Error +init_crypto(PRBool create, PRBool readOnly) +{ + + PRUint32 flags = 0; + SECStatus rv; + Error retval; + /* Open/create key database */ + + if (readOnly) flags |= NSS_INIT_READONLY; + if (nocertdb) flags |= NSS_INIT_NOCERTDB; + rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix, + secmodName, flags); + if (rv != SECSuccess) { + SECU_PrintPRandOSError(progName); + retval=NSS_INITIALIZE_FAILED_ERR; + } else + retval=SUCCESS; + + return retval; +} + +/************************************************************************* + * + * u s a g e + */ +static void +usage() +{ + PR_fprintf(PR_STDOUT, +"\nNetscape Cryptographic Module Utility\n" +"Usage: modutil [command] [options]\n\n" +" COMMANDS\n" +"---------------------------------------------------------------------------\n" +"-add MODULE_NAME Add the named module to the module database\n" +" -libfile LIBRARY_FILE The name of the file (.so or .dll)\n" +" containing the implementation of PKCS #11\n" +" [-ciphers CIPHER_LIST] Enable the given ciphers on this module\n" +" [-mechanisms MECHANISM_LIST] Make the module a default provider of the\n" +" given mechanisms\n" +" [-string CONFIG_STRING] Pass a configuration string to this module\n" +"-changepw TOKEN Change the password on the named token\n" +" [-pwfile FILE] The old password is in this file\n" +" [-newpwfile FILE] The new password is in this file\n" +"-chkfips [ true | false ] If true, verify FIPS mode. If false,\n" +" verify not FIPS mode\n" +"-create Create a new set of security databases\n" +"-default MODULE Make the given module a default provider\n" +" -mechanisms MECHANISM_LIST of the given mechanisms\n" +" [-slot SLOT] limit change to only the given slot\n" +"-delete MODULE Remove the named module from the module\n" +" database\n" +"-disable MODULE Disable the named module\n" +" [-slot SLOT] Disable only the named slot on the module\n" +"-enable MODULE Enable the named module\n" +" [-slot SLOT] Enable only the named slot on the module\n" +"-fips [ true | false ] If true, enable FIPS mode. If false,\n" +" disable FIPS mode\n" +"-force Do not run interactively\n" +"-jar JARFILE Install a PKCS #11 module from the given\n" +" JAR file in the PKCS #11 JAR format\n" +" -installdir DIR Use DIR as the root directory of the\n" +" installation\n" +" [-tempdir DIR] Use DIR as the temporary installation\n" +" directory. If not specified, the current\n" +" directory is used\n" +"-list [MODULE] Lists information about the specified module\n" +" or about all modules if none is specified\n" +"-rawadd MODULESPEC Add module spec string to secmod DB\n" +"-rawlist [MODULE] Display module spec(s) for one or all\n" +" loadable modules\n" +"-undefault MODULE The given module is NOT a default provider\n" +" -mechanisms MECHANISM_LIST of the listed mechanisms\n" +" [-slot SLOT] limit change to only the given slot\n" +"---------------------------------------------------------------------------\n" +"\n" +" OPTIONS\n" +"---------------------------------------------------------------------------\n" +"-dbdir DIR Directory DIR contains the security databases\n" +"-dbprefix prefix Prefix for the security databases\n" +"-nocertdb Do not load certificate or key databases. No\n" +" verification will be performed on JAR files.\n" +"-secmod secmodName Name of the security modules file\n" +"---------------------------------------------------------------------------\n" +"\n" +"Mechanism lists are colon-separated. The following mechanisms are recognized:\n" +"RSA, DSA, DH, RC2, RC4, RC5, AES, CAMELLIA, DES, MD2, MD5, SHA1, SHA256, SHA512,\n" +"SSL, TLS, RANDOM, and FRIENDLY\n" +"\n" +"Cipher lists are colon-separated. The following ciphers are recognized:\n" +"\n" +"\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n" +); + +} + +/************************************************************************* + * + * m a i n + */ +int +main(int argc, char *argv[]) +{ + int errcode = SUCCESS; + PRBool createdb, readOnly; +#define STDINBUF_SIZE 80 + char stdinbuf[STDINBUF_SIZE]; + + progName = strrchr(argv[0], '/'); + progName = progName ? progName+1 : argv[0]; + + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + + if(parse_args(argc, argv) != SUCCESS) { + usage(); + errcode = INVALID_USAGE_ERR; + goto loser; + } + + if(verify_params() != SUCCESS) { + usage(); + errcode = INVALID_USAGE_ERR; + goto loser; + } + + if(command==NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]); + usage(); + errcode = INVALID_USAGE_ERR; + goto loser; + } + + /* Set up crypto stuff */ + createdb = command==CREATE_COMMAND; + readOnly = ((command == LIST_COMMAND) || + (command == CHKFIPS_COMMAND) || + (command == RAW_LIST_COMMAND)); + + /* Make sure browser is not running if we're writing to a database */ + /* Do this before initializing crypto */ + if(!readOnly && !force) { + char *response; + + PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]); + if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) { + PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]); + errcode = STDIN_READ_ERR; + goto loser; + } + if( (response=strtok(stdinbuf, " \r\n\t")) ) { + if(!PL_strcasecmp(response, "q")) { + PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]); + errcode = SUCCESS; + goto loser; + } + } + PR_fprintf(PR_STDOUT, "\n"); + } + + errcode = check_crypto(createdb, readOnly); + if( errcode != SUCCESS) { + goto loser; + } + + if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) { + if(!moduleName) { + char *readOnlyStr, *noCertDBStr, *sep; + if (!secmodName) secmodName="secmod.db"; + if (!dbprefix) dbprefix = ""; + sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " "; + readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ; + noCertDBStr = nocertdb ? "noCertDB" : ""; + SECU_ConfigDirectory(dbdir); + + moduleName=PR_smprintf( + "name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s " + "keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB," + "moduleDBOnly,critical\"", + SECU_ConfigDirectory(NULL),dbprefix,dbprefix, + secmodName, readOnlyStr,sep, noCertDBStr); + } + if (command == RAW_LIST_COMMAND) { + errcode = RawListModule(moduleName); + } else { + PORT_Assert(moduleSpec); + errcode = RawAddModule(moduleName,moduleSpec); + } + goto loser; + } + + errcode = init_crypto(createdb, readOnly); + if( errcode != SUCCESS) { + goto loser; + } + + errcode = LoadMechanismList(); + if (errcode != SUCCESS) { + goto loser; + } + + /* Execute the command */ + switch(command) { + case ADD_COMMAND: + errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString); + break; + case CHANGEPW_COMMAND: + errcode = ChangePW(tokenName, pwFile, newpwFile); + break; + case CREATE_COMMAND: + /* The work was already done in init_crypto() */ + break; + case DEFAULT_COMMAND: + errcode = SetDefaultModule(moduleName, slotName, mechanisms); + break; + case DELETE_COMMAND: + errcode = DeleteModule(moduleName); + break; + case DISABLE_COMMAND: + errcode = EnableModule(moduleName, slotName, PR_FALSE); + break; + case ENABLE_COMMAND: + errcode = EnableModule(moduleName, slotName, PR_TRUE); + break; + case FIPS_COMMAND: + errcode = FipsMode(fipsArg); + break; + case CHKFIPS_COMMAND: + errcode = ChkFipsMode(fipsArg); + break; + case JAR_COMMAND: + Pk11Install_SetErrorHandler(install_error); + errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir, + PR_STDOUT, force, nocertdb); + break; + case LIST_COMMAND: + if(moduleName) { + errcode = ListModule(moduleName); + } else { + errcode = ListModules(); + } + break; + case UNDEFAULT_COMMAND: + errcode = UnsetDefaultModule(moduleName, slotName, mechanisms); + break; + default: + PR_fprintf(PR_STDERR, "This command is not supported yet.\n"); + errcode = INVALID_USAGE_ERR; + break; + } + + if (NSS_Shutdown() != SECSuccess) { + exit(1); + } + +loser: + PR_Cleanup(); + return errcode; +} + +/************************************************************************ + * + * i n s t a l l _ e r r o r + * + * Callback function to handle errors in PK11 JAR file installation. + */ +static void +install_error(char *message) +{ + PR_fprintf(PR_STDERR, "Install error: %s\n", message); +} + +/************************************************************************* + * + * o u t _ o f _ m e m o r y + */ +void +out_of_memory(void) +{ + PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]); + exit(OUT_OF_MEM_ERR); +} + + +/************************************************************************** + * + * P R _ f g e t s + * + * fgets implemented with NSPR. + */ +static char* +PR_fgets(char *buf, int size, PRFileDesc *file) +{ + int i; + int status; + char c; + + i=0; + while(i < size-1) { + status = PR_Read(file, (void*) &c, 1); + if(status==-1) { + return NULL; + } else if(status==0) { + break; + } + buf[i++] = c; + if(c=='\n') { + break; + } + } + buf[i]='\0'; + + return buf; +} diff --git a/nss/cmd/modutil/modutil.h b/nss/cmd/modutil/modutil.h new file mode 100644 index 0000000..529d60e --- /dev/null +++ b/nss/cmd/modutil/modutil.h @@ -0,0 +1,40 @@ +/* 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 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); +void out_of_memory(void); + +#endif /*MODUTIL_H*/ diff --git a/nss/cmd/modutil/pk11.c b/nss/cmd/modutil/pk11.c new file mode 100644 index 0000000..c0a6ccb --- /dev/null +++ b/nss/cmd/modutil/pk11.c @@ -0,0 +1,964 @@ +/* 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; +} + +/********************************************************************** + * + * 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; + 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); + } + + 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]; + + 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)); + } + 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 int 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; + PK11DisableReasons reason; + 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)) { + reason = PK11_GetDisabledReason(slot); + if(reason < numDisableReasonStr) { + PR_fprintf(PR_STDOUT, PAD"Status: DISABLED (%s)\n", + disableReasonStr[reason]); + } 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; +} + +/************************************************************************ + * + * 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 { + 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/nss/cmd/modutil/pk11jar.html b/nss/cmd/modutil/pk11jar.html new file mode 100644 index 0000000..bb50b8f --- /dev/null +++ b/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/nss/cmd/modutil/rules.mk b/nss/cmd/modutil/rules.mk new file mode 100644 index 0000000..3ad6a97 --- /dev/null +++ b/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/nss/cmd/modutil/specification.html b/nss/cmd/modutil/specification.html new file mode 100644 index 0000000..6477a37 --- /dev/null +++ b/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> |