summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/sysinit
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/sysinit')
-rw-r--r--security/nss/lib/sysinit/Makefile44
-rw-r--r--security/nss/lib/sysinit/config.mk73
-rw-r--r--security/nss/lib/sysinit/manifest.mn17
-rw-r--r--security/nss/lib/sysinit/nsssysinit.c418
-rw-r--r--security/nss/lib/sysinit/nsssysinit.def26
-rw-r--r--security/nss/lib/sysinit/sysinit.gyp34
6 files changed, 612 insertions, 0 deletions
diff --git a/security/nss/lib/sysinit/Makefile b/security/nss/lib/sysinit/Makefile
new file mode 100644
index 0000000000..3803142fd6
--- /dev/null
+++ b/security/nss/lib/sysinit/Makefile
@@ -0,0 +1,44 @@
+#! 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 config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
diff --git a/security/nss/lib/sysinit/config.mk b/security/nss/lib/sysinit/config.mk
new file mode 100644
index 0000000000..33ef6e8740
--- /dev/null
+++ b/security/nss/lib/sysinit/config.mk
@@ -0,0 +1,73 @@
+#
+# 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)))
+
+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 0000000000..d188b0a51c
--- /dev/null
+++ b/security/nss/lib/sysinit/manifest.mn
@@ -0,0 +1,17 @@
+#
+# 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 = nss
+
+CSRCS = \
+ nsssysinit.c \
+ $(NULL)
+
+LIBRARY_NAME = nsssysinit
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def
+
+# This part of the code, including all sub-dirs, can be optimized for size
+export ALLOW_OPT_CODE_SIZE = 1
diff --git a/security/nss/lib/sysinit/nsssysinit.c b/security/nss/lib/sysinit/nsssysinit.c
new file mode 100644
index 0000000000..8793bf5593
--- /dev/null
+++ b/security/nss/lib/sysinit/nsssysinit.c
@@ -0,0 +1,418 @@
+/* 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.
+ */
+
+#ifndef LINUX
+#error __FILE__ only builds on Linux.
+#endif
+
+#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);
+}
+
+/**
+ * Append given @dir to @path and creates the directory with mode @mode.
+ * Returns 0 if successful, -1 otherwise.
+ * Assumes that the allocation for @path has sufficient space for @dir
+ * to be added.
+ */
+static int
+appendDirAndCreate(char *path, char *dir, mode_t mode)
+{
+ PORT_Strcat(path, dir);
+ if (!testdir(path)) {
+ if (mkdir(path, mode)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+#define XDG_NSS_USER_PATH1 "/.local"
+#define XDG_NSS_USER_PATH2 "/share"
+#define XDG_NSS_USER_PATH3 "/pki"
+
+#define NSS_USER_PATH1 "/.pki"
+#define NSS_USER_PATH2 "/nssdb"
+
+/**
+ * Return the path to user's NSS database.
+ * We search in the following dirs in order:
+ * (1) $HOME/.pki/nssdb;
+ * (2) $XDG_DATA_HOME/pki/nssdb if XDG_DATA_HOME is set;
+ * (3) $HOME/.local/share/pki/nssdb (default XDG_DATA_HOME value).
+ * If (1) does not exist, then the returned dir will be set to either
+ * (2) or (3), depending if XDG_DATA_HOME is set.
+ */
+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));
+ PORT_Strcpy(nssdir, userdir);
+ PORT_Strcat(nssdir, NSS_USER_PATH1 NSS_USER_PATH2);
+ if (testdir(nssdir)) {
+ /* $HOME/.pki/nssdb exists */
+ return nssdir;
+ } else {
+ /* either $HOME/.pki or $HOME/.pki/nssdb does not exist */
+ PORT_Free(nssdir);
+ }
+ int size = 0;
+ char *xdguserdatadir = PR_GetEnvSecure("XDG_DATA_HOME");
+ if (xdguserdatadir) {
+ size = strlen(xdguserdatadir);
+ } else {
+ size = strlen(userdir) + sizeof(XDG_NSS_USER_PATH1) + sizeof(XDG_NSS_USER_PATH2);
+ }
+ size += sizeof(XDG_NSS_USER_PATH3) + sizeof(NSS_USER_PATH2);
+
+ nssdir = PORT_Alloc(size);
+ if (nssdir == NULL) {
+ return NULL;
+ }
+
+ if (xdguserdatadir) {
+ PORT_Strcpy(nssdir, xdguserdatadir);
+ if (!testdir(nssdir)) {
+ PORT_Free(nssdir);
+ return NULL;
+ }
+
+ } else {
+ PORT_Strcpy(nssdir, userdir);
+ if (appendDirAndCreate(nssdir, XDG_NSS_USER_PATH1, 0755) ||
+ appendDirAndCreate(nssdir, XDG_NSS_USER_PATH2, 0755)) {
+ PORT_Free(nssdir);
+ return NULL;
+ }
+ }
+ /* ${XDG_DATA_HOME:-$HOME/.local/share}/pki/nssdb */
+ if (appendDirAndCreate(nssdir, XDG_NSS_USER_PATH3, 0760) ||
+ appendDirAndCreate(nssdir, NSS_USER_PATH2, 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);
+}
+
+#ifndef NSS_FIPS_DISABLED
+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;
+}
+#endif /* NSS_FIPS_DISABLED */
+
+static PRBool
+getFIPSMode(void)
+{
+#ifndef NSS_FIPS_DISABLED
+ 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
+ return PR_FALSE;
+#endif /* NSS_FIPS_DISABLED */
+}
+
+#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/nsssysinit.def b/security/nss/lib/sysinit/nsssysinit.def
new file mode 100644
index 0000000000..2e272be064
--- /dev/null
+++ b/security/nss/lib/sysinit/nsssysinit.def
@@ -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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+
+;+NSS_3.15 { # NSS 3.15 release
+;+ global:
+LIBRARY nsssysiniit ;-
+EXPORTS ;-
+NSS_ReturnModuleSpecData;
+;+ local:
+;+*;
+;+};
diff --git a/security/nss/lib/sysinit/sysinit.gyp b/security/nss/lib/sysinit/sysinit.gyp
new file mode 100644
index 0000000000..d76c27598c
--- /dev/null
+++ b/security/nss/lib/sysinit/sysinit.gyp
@@ -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/.
+{
+ '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': {
+ 'mapfile': 'nsssysinit.def',
+ },
+ }
+ ],
+ 'variables': {
+ 'module': 'nss',
+ }
+}