diff options
Diffstat (limited to 'security/nss/lib/sysinit')
-rw-r--r-- | security/nss/lib/sysinit/Makefile | 48 | ||||
-rw-r--r-- | security/nss/lib/sysinit/config.mk | 80 | ||||
-rw-r--r-- | security/nss/lib/sysinit/manifest.mn | 15 | ||||
-rw-r--r-- | security/nss/lib/sysinit/nsssysinit.c | 403 | ||||
-rw-r--r-- | security/nss/lib/sysinit/sysinit.gyp | 31 |
5 files changed, 577 insertions, 0 deletions
diff --git a/security/nss/lib/sysinit/Makefile b/security/nss/lib/sysinit/Makefile new file mode 100644 index 000000000..fe59954df --- /dev/null +++ b/security/nss/lib/sysinit/Makefile @@ -0,0 +1,48 @@ +#! gmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +#include ../platlibs.mk +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + +#include ../platrules.mk + diff --git a/security/nss/lib/sysinit/config.mk b/security/nss/lib/sysinit/config.mk new file mode 100644 index 000000000..037641b11 --- /dev/null +++ b/security/nss/lib/sysinit/config.mk @@ -0,0 +1,80 @@ +# +# 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/. + +# +# Override TARGETS variable so that only static libraries +# are specifed as dependencies within rules.mk. +# + +# can't do this in manifest.mn because OS_TARGET isn't defined there. +ifeq (,$(filter-out WIN%,$(OS_TARGET))) + +# don't want the 32 in the shared library name +SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) +IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX) + +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = $(LIBRARY_NAME).rc + +ifdef NS_USE_GCC +EXTRA_SHARED_LIBS += \ + -L$(DIST)/lib \ + -L$(NSSUTIL_LIB_DIR) \ + -lnssutil3 \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4\ + $(NULL) +else # ! NS_USE_GCC +EXTRA_SHARED_LIBS += \ + $(DIST)/lib/nssutil3.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NULL) +endif # NS_USE_GCC + +else + +# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) +# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. +EXTRA_SHARED_LIBS += \ + -L$(DIST)/lib \ + -L$(NSSUTIL_LIB_DIR) \ + -lnssutil3 \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ + $(NULL) + +endif + + +# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) + +ifeq ($(OS_TARGET),SunOS) +ifeq ($(BUILD_SUN_PKG), 1) +# The -R '$ORIGIN' linker option instructs this library to search for its +# dependencies in the same directory where it resides. +ifeq ($(USE_64), 1) +MKSHLIB += -R '$$ORIGIN:/usr/lib/mps/secv1/64:/usr/lib/mps/64' +else +MKSHLIB += -R '$$ORIGIN:/usr/lib/mps/secv1:/usr/lib/mps' +endif +else +MKSHLIB += -R '$$ORIGIN' +endif +endif + +ifeq ($(OS_ARCH), HP-UX) +ifneq ($(OS_TEST), ia64) +# pa-risc +ifeq ($(USE_64), 1) +MKSHLIB += +b '$$ORIGIN' +endif +endif +endif diff --git a/security/nss/lib/sysinit/manifest.mn b/security/nss/lib/sysinit/manifest.mn new file mode 100644 index 000000000..822f4fcbd --- /dev/null +++ b/security/nss/lib/sysinit/manifest.mn @@ -0,0 +1,15 @@ +# +# 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 public and private header directories are implicitly REQUIRED. +MODULE = nss + +CSRCS = nsssysinit.c + +LIBRARY_NAME = nsssysinit +#LIBRARY_VERSION = 3 + diff --git a/security/nss/lib/sysinit/nsssysinit.c b/security/nss/lib/sysinit/nsssysinit.c new file mode 100644 index 000000000..39e2ad7a1 --- /dev/null +++ b/security/nss/lib/sysinit/nsssysinit.c @@ -0,0 +1,403 @@ +/* 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 "seccomon.h" +#include "prio.h" +#include "prprf.h" +#include "plhash.h" +#include "prenv.h" + +/* + * The following provides a default example for operating systems to set up + * and manage applications loading NSS on their OS globally. + * + * This code hooks in to the system pkcs11.txt, which controls all the loading + * of pkcs11 modules common to all applications. + */ + +/* + * OS Specific function to get where the NSS user database should reside. + */ + +#ifdef XP_UNIX +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> + +static int +testdir(char *dir) +{ + struct stat buf; + memset(&buf, 0, sizeof(buf)); + + if (stat(dir, &buf) < 0) { + return 0; + } + + return S_ISDIR(buf.st_mode); +} + +#define NSS_USER_PATH1 "/.pki" +#define NSS_USER_PATH2 "/nssdb" +static char * +getUserDB(void) +{ + char *userdir = PR_GetEnvSecure("HOME"); + char *nssdir = NULL; + + if (userdir == NULL) { + return NULL; + } + + nssdir = PORT_Alloc(strlen(userdir) + sizeof(NSS_USER_PATH1) + sizeof(NSS_USER_PATH2)); + if (nssdir == NULL) { + return NULL; + } + PORT_Strcpy(nssdir, userdir); + /* verify it exists */ + if (!testdir(nssdir)) { + PORT_Free(nssdir); + return NULL; + } + PORT_Strcat(nssdir, NSS_USER_PATH1); + if (!testdir(nssdir) && mkdir(nssdir, 0760)) { + PORT_Free(nssdir); + return NULL; + } + PORT_Strcat(nssdir, NSS_USER_PATH2); + if (!testdir(nssdir) && mkdir(nssdir, 0760)) { + PORT_Free(nssdir); + return NULL; + } + return nssdir; +} + +#define NSS_DEFAULT_SYSTEM "/etc/pki/nssdb" +static char * +getSystemDB(void) +{ + return PORT_Strdup(NSS_DEFAULT_SYSTEM); +} + +static PRBool +userIsRoot() +{ + /* this works for linux and all unixes that we know off + though it isn't stated as such in POSIX documentation */ + return getuid() == 0; +} + +static PRBool +userCanModifySystemDB() +{ + return (access(NSS_DEFAULT_SYSTEM, W_OK) == 0); +} + +#else +#ifdef XP_WIN +static char * +getUserDB(void) +{ + /* use the registry to find the user's NSS_DIR. if no entry exists, create + * one in the users Appdir location */ + return NULL; +} + +static char * +getSystemDB(void) +{ + /* use the registry to find the system's NSS_DIR. if no entry exists, create + * one based on the windows system data area */ + return NULL; +} + +static PRBool +userIsRoot() +{ + /* use the registry to find if the user is the system administrator. */ + return PR_FALSE; +} + +static PRBool +userCanModifySystemDB() +{ + /* use the registry to find if the user has administrative privilege + * to modify the system's nss database. */ + return PR_FALSE; +} + +#else +#error "Need to write getUserDB, SystemDB, userIsRoot, and userCanModifySystemDB functions" +#endif +#endif + +static PRBool +getFIPSEnv(void) +{ + char *fipsEnv = PR_GetEnvSecure("NSS_FIPS"); + if (!fipsEnv) { + return PR_FALSE; + } + if ((strcasecmp(fipsEnv, "fips") == 0) || + (strcasecmp(fipsEnv, "true") == 0) || + (strcasecmp(fipsEnv, "on") == 0) || + (strcasecmp(fipsEnv, "1") == 0)) { + return PR_TRUE; + } + return PR_FALSE; +} +#ifdef XP_LINUX + +static PRBool +getFIPSMode(void) +{ + FILE *f; + char d; + size_t size; + + f = fopen("/proc/sys/crypto/fips_enabled", "r"); + if (!f) { + /* if we don't have a proc flag, fall back to the + * environment variable */ + return getFIPSEnv(); + } + + size = fread(&d, 1, 1, f); + fclose(f); + if (size != 1) + return PR_FALSE; + if (d != '1') + return PR_FALSE; + return PR_TRUE; +} + +#else +static PRBool +getFIPSMode(void) +{ + return getFIPSEnv(); +} +#endif + +#define NSS_DEFAULT_FLAGS "flags=readonly" + +/* configuration flags according to + * https://developer.mozilla.org/en/PKCS11_Module_Specs + * As stated there the slotParams start with a slot name which is a slotID + * Slots 1 through 3 are reserved for the nss internal modules as follows: + * 1 for crypto operations slot non-fips, + * 2 for the key slot, and + * 3 for the crypto operations slot fips + */ +#define CIPHER_ORDER_FLAGS "cipherOrder=100" +#define SLOT_FLAGS \ + "[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,RANDOM" \ + " askpw=any timeout=30 ]" + +static const char *nssDefaultFlags = + CIPHER_ORDER_FLAGS " slotParams={0x00000001=" SLOT_FLAGS " } "; + +static const char *nssDefaultFIPSFlags = + CIPHER_ORDER_FLAGS " slotParams={0x00000003=" SLOT_FLAGS " } "; + +/* + * This function builds the list of databases and modules to load, and sets + * their configuration. For the sample we have a fixed set. + * 1. We load the user's home nss database. + * 2. We load the user's custom PKCS #11 modules. + * 3. We load the system nss database readonly. + * + * Any space allocated in get_list must be freed in release_list. + * This function can use whatever information is available to the application. + * it is running in the process of the application for which it is making + * decisions, so it's possible to acquire the application name as part of + * the decision making process. + * + */ +static char ** +get_list(char *filename, char *stripped_parameters) +{ + char **module_list = PORT_ZNewArray(char *, 5); + char *userdb, *sysdb; + int isFIPS = getFIPSMode(); + const char *nssflags = isFIPS ? nssDefaultFIPSFlags : nssDefaultFlags; + int next = 0; + + /* can't get any space */ + if (module_list == NULL) { + return NULL; + } + + sysdb = getSystemDB(); + userdb = getUserDB(); + + /* Don't open root's user DB */ + if (userdb != NULL && !userIsRoot()) { + /* return a list of databases to open. First the user Database */ + module_list[next++] = PR_smprintf( + "library= " + "module=\"NSS User database\" " + "parameters=\"configdir='sql:%s' %s tokenDescription='NSS user database'\" " + "NSS=\"trustOrder=75 %sflags=internal%s\"", + userdb, stripped_parameters, nssflags, + isFIPS ? ",FIPS" : ""); + + /* now open the user's defined PKCS #11 modules */ + /* skip the local user DB entry */ + module_list[next++] = PR_smprintf( + "library= " + "module=\"NSS User database\" " + "parameters=\"configdir='sql:%s' %s\" " + "NSS=\"flags=internal,moduleDBOnly,defaultModDB,skipFirst\"", + userdb, stripped_parameters); + } + + /* now the system database (always read only unless it's root) */ + if (sysdb) { + const char *readonly = userCanModifySystemDB() ? "" : "flags=readonly"; + module_list[next++] = PR_smprintf( + "library= " + "module=\"NSS system database\" " + "parameters=\"configdir='sql:%s' tokenDescription='NSS system database' %s\" " + "NSS=\"trustOrder=80 %sflags=internal,critical\"", + sysdb, readonly, nssflags); + } + + /* that was the last module */ + module_list[next] = 0; + + PORT_Free(userdb); + PORT_Free(sysdb); + + return module_list; +} + +static char ** +release_list(char **arg) +{ + static char *success = "Success"; + int next; + + for (next = 0; arg[next]; next++) { + free(arg[next]); + } + PORT_Free(arg); + return &success; +} + +#include "utilpars.h" + +#define TARGET_SPEC_COPY(new, start, end) \ + if (end > start) { \ + int _cnt = end - start; \ + PORT_Memcpy(new, start, _cnt); \ + new += _cnt; \ + } + +/* + * According the strcpy man page: + * + * The strings may not overlap, and the destination string dest must be + * large enough to receive the copy. + * + * This implementation allows target to overlap with src. + * It does not allow the src to overlap the target. + * example: overlapstrcpy(string, string+4) is fine + * overlapstrcpy(string+4, string) is not. + */ +static void +overlapstrcpy(char *target, char *src) +{ + while (*src) { + *target++ = *src++; + } + *target = 0; +} + +/* determine what options the user was trying to open this database with */ +/* filename is the directory pointed to by configdir= */ +/* stripped is the rest of the parameters with configdir= stripped out */ +static SECStatus +parse_parameters(const char *parameters, char **filename, char **stripped) +{ + const char *sourcePrev; + const char *sourceCurr; + char *targetCurr; + char *newStripped; + *filename = NULL; + *stripped = NULL; + + newStripped = PORT_Alloc(PORT_Strlen(parameters) + 2); + targetCurr = newStripped; + sourcePrev = parameters; + sourceCurr = NSSUTIL_ArgStrip(parameters); + TARGET_SPEC_COPY(targetCurr, sourcePrev, sourceCurr); + + while (*sourceCurr) { + int next; + sourcePrev = sourceCurr; + NSSUTIL_HANDLE_STRING_ARG(sourceCurr, *filename, "configdir=", + sourcePrev = sourceCurr;) + NSSUTIL_HANDLE_FINAL_ARG(sourceCurr); + TARGET_SPEC_COPY(targetCurr, sourcePrev, sourceCurr); + } + *targetCurr = 0; + if (*filename == NULL) { + PORT_Free(newStripped); + return SECFailure; + } + /* strip off any directives from the filename */ + if (strncmp("sql:", *filename, 4) == 0) { + overlapstrcpy(*filename, (*filename) + 4); + } else if (strncmp("dbm:", *filename, 4) == 0) { + overlapstrcpy(*filename, (*filename) + 4); + } else if (strncmp("extern:", *filename, 7) == 0) { + overlapstrcpy(*filename, (*filename) + 7); + } + *stripped = newStripped; + return SECSuccess; +} + +/* entry point */ +char ** +NSS_ReturnModuleSpecData(unsigned long function, char *parameters, void *args) +{ + char *filename = NULL; + char *stripped = NULL; + char **retString = NULL; + SECStatus rv; + + rv = parse_parameters(parameters, &filename, &stripped); + if (rv != SECSuccess) { + /* use defaults */ + filename = getSystemDB(); + if (!filename) { + return NULL; + } + stripped = PORT_Strdup(NSS_DEFAULT_FLAGS); + if (!stripped) { + free(filename); + return NULL; + } + } + switch (function) { + case SECMOD_MODULE_DB_FUNCTION_FIND: + retString = get_list(filename, stripped); + break; + case SECMOD_MODULE_DB_FUNCTION_RELEASE: + retString = release_list((char **)args); + break; + /* can't add or delete from this module DB */ + case SECMOD_MODULE_DB_FUNCTION_ADD: + case SECMOD_MODULE_DB_FUNCTION_DEL: + retString = NULL; + break; + default: + retString = NULL; + break; + } + + PORT_Free(filename); + PORT_Free(stripped); + return retString; +} diff --git a/security/nss/lib/sysinit/sysinit.gyp b/security/nss/lib/sysinit/sysinit.gyp new file mode 100644 index 000000000..e961325f6 --- /dev/null +++ b/security/nss/lib/sysinit/sysinit.gyp @@ -0,0 +1,31 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'nsssysinit_static', + 'type': 'static_library', + 'sources': [ + 'nsssysinit.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/lib/util/util.gyp:nssutil3' + ] + }, + { + 'target_name': 'nsssysinit', + 'type': 'shared_library', + 'dependencies': [ + 'nsssysinit_static' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file |