rpms/nss/devel newargs.patch,NONE,1.1 sysinit.patch,NONE,1.1

Elio Maldonado emaldonado at fedoraproject.org
Wed Sep 9 21:49:24 UTC 2009


Author: emaldonado

Update of /cvs/extras/rpms/nss/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv17968

Added Files:
	newargs.patch sysinit.patch 
Log Message:
Patches to enable the nss sysinit module

newargs.patch:
 pk11pars.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 pk11util.c |    5 +++
 secmod.h   |    4 +++
 3 files changed, 85 insertions(+), 4 deletions(-)

--- NEW FILE newargs.patch ---
Index: mozilla/security/nss/lib/pk11wrap/pk11pars.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11pars.c,v
retrieving revision 1.21
diff -u -p -r1.21 pk11pars.c
--- ./mozilla/security/nss/lib/pk11wrap/pk11pars.c	12 Nov 2005 00:14:25 -0000	1.21
+++ ./mozilla/security/nss/lib/pk11wrap/pk11pars.c	1 Sep 2009 21:55:18 -0000
@@ -107,6 +107,41 @@ secmod_NewModule(void)
     
 }
 
+/* private flags. */
+/* The meaing of these flags is as follows:
+ *
+ * SECMOD_FLAG_IS_MODULE_DB - This is a module that accesses the database of
+ *   other modules to load. Module DBs are loadable modules that tells
+ *   NSS which PKCS #11 modules to load and when. These module DBs are 
+ *   chainable. That is, one module DB can load another one. NSS system init 
+ *   design takes advantage of this feature. In system NSS, a fixed system 
+ *   module DB loads the system defined libraries, then chains out to the 
+ *   traditional module DBs to load any system or user configured modules 
+ *   (like smart cards). This bit is the same as the already existing meaning 
+ *   of  isModuleDB = PR_TRUE. None of the other flags should be set if this
+ *   flag isn't on.
+ *
+ * SECMOD_FLAG_SKIP_FIRST - This flag tells NSS to skip the first 
+ *   PKCS #11 module presented by a module DB. This allows the OS to load a 
+ *   softoken from the system module, then ask the existing module DB code to 
+ *   load the other PKCS #11 modules in that module DB (skipping it's request 
+ *   to load softoken). This gives the system init finer control over the 
+ *   configuration of that softoken module.
+ *
+ * SECMOD_FLAG_DEFAULT_MODDB - This flag allows system init to mark a 
+ *   different module DB as the 'default' module DB (the one in which 
+ *   'Add module' changes will go). Without this flag NSS takes the first 
+ *   module as the default Module DB, but in system NSS, that first module 
+ *   is the system module, which is likely read only (at least to the user).
+ *   This  allows system NSS to delegate those changes to the user's module DB, 
+ *   preserving the user's ability to load new PKCS #11 modules (which only 
+ *   affect him), from existing applications like Firefox.
+ */
+#define SECMOD_FLAG_IS_MODULE_DB  0x01 /* must be set if any of the other flags
+                                        * are set */
+#define SECMOD_FLAG_SKIP_FIRST    0x02
+#define SECMOD_FLAG_DEFAULT_MODDB 0x04
+
 /*
  * for 3.4 we continue to use the old SECMODModule structure
  */
@@ -137,15 +172,33 @@ SECMOD_CreateModule(const char *library,
     if (slotParams) PORT_Free(slotParams);
     /* new field */
     mod->trustOrder  = secmod_argReadLong("trustOrder",nssc,
-						SECMOD_DEFAULT_TRUST_ORDER,NULL);
+					SECMOD_DEFAULT_TRUST_ORDER,NULL);
     /* new field */
     mod->cipherOrder = secmod_argReadLong("cipherOrder",nssc,
-						SECMOD_DEFAULT_CIPHER_ORDER,NULL);
+					SECMOD_DEFAULT_CIPHER_ORDER,NULL);
     /* new field */
     mod->isModuleDB   = secmod_argHasFlag("flags","moduleDB",nssc);
     mod->moduleDBOnly = secmod_argHasFlag("flags","moduleDBOnly",nssc);
     if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE;
 
+    /* we need more bits, but we also want to preserve binary compatibility 
+     * so we overload the isModuleDB PRBool with additional flags. 
+     * These flags are only valid if mod->isModuleDB is already set.
+     * NOTE: this depends on the fact that PRBool is at least a char on 
+     * all platforms. These flags are only valid if moduleDB is set, so 
+     * code checking if (mod->isModuleDB) will continue to work correctly. */
+    if (mod->isModuleDB) {
+	char flags = SECMOD_FLAG_IS_MODULE_DB;
+	if (secmod_argHasFlag("flags","skipFirst",nssc)) {
+	    flags |= SECMOD_FLAG_SKIP_FIRST;
+	}
+	if (secmod_argHasFlag("flags","defaultModDB",nssc)) {
+	    flags |= SECMOD_FLAG_DEFAULT_MODDB;
+	}
+	/* additional moduleDB flags could be added here in the future */
+	mod->isModuleDB = (PRBool) flags;
+    }
+
     ciphers = secmod_argGetParamValue("ciphers",nssc);
     secmod_argSetNewCipherFlags(&mod->ssl[0],ciphers);
     if (ciphers) PORT_Free(ciphers);
@@ -155,6 +208,22 @@ SECMOD_CreateModule(const char *library,
     return mod;
 }
 
+PRBool
+SECMOD_GetSkipFirstFlag(SECMODModule *mod)
+{
+   char flags = (char) mod->isModuleDB;
+
+   return (flags & SECMOD_FLAG_SKIP_FIRST) ? PR_TRUE : PR_FALSE;
+}
+
+PRBool
+SECMOD_GetDefaultModDBFlag(SECMODModule *mod)
+{
+   char flags = (char) mod->isModuleDB;
+
+   return (flags & SECMOD_FLAG_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;
+}
+
 static char *
 secmod_mkModuleSpec(SECMODModule * module)
 {
@@ -333,7 +402,12 @@ SECMOD_LoadModule(char *modulespec,SECMO
 	if (moduleSpecList) {
 	    char **index;
 
-	    for (index = moduleSpecList; *index; index++) {
+	    index = moduleSpecList;
+	    if (*index && SECMOD_GetSkipFirstFlag(module)) {
+		index++;
+	    }
+
+	    for (; *index; index++) {
 		SECMODModule *child;
 		child = SECMOD_LoadModule(*index,module,PR_TRUE);
 		if (!child) break;
Index: mozilla/security/nss/lib/pk11wrap/pk11util.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11util.c,v
retrieving revision 1.55
diff -u -p -r1.55 pk11util.c
--- ./mozilla/security/nss/lib/pk11wrap/pk11util.c	30 Jul 2009 00:29:35 -0000	1.55
+++ ./mozilla/security/nss/lib/pk11wrap/pk11util.c	1 Sep 2009 21:55:18 -0000
@@ -179,7 +179,10 @@ SECMOD_AddModuleToList(SECMODModule *new
 SECStatus
 SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
 {
-    if (defaultDBModule == NULL) {
+    if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) {
+	SECMOD_DestroyModule(defaultDBModule);
+	defaultDBModule = SECMOD_ReferenceModule(newModule);
+    } else if (defaultDBModule == NULL) {
 	defaultDBModule = SECMOD_ReferenceModule(newModule);
     }
     return secmod_AddModuleToList(&modulesDB,newModule);
Index: mozilla/security/nss/lib/pk11wrap/secmod.h
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/secmod.h,v
retrieving revision 1.26
diff -u -p -r1.26 secmod.h
--- ./mozilla/security/nss/lib/pk11wrap/secmod.h	17 Dec 2008 06:09:16 -0000	1.26
+++ ./mozilla/security/nss/lib/pk11wrap/secmod.h	1 Sep 2009 21:55:18 -0000
@@ -151,6 +151,10 @@ extern PK11SlotInfo *SECMOD_FindSlot(SEC
 /* of modType has been installed */
 PRBool SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags );
 
+/* accessors */
+PRBool SECMOD_GetSkipFirstFlag(SECMODModule *mod);
+PRBool SECMOD_GetDefaultModDBFlag(SECMODModule *mod);
+
 /* Functions used to convert between internal & public representation
  * of Mechanism Flags and Cipher Enable Flags */
 extern unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags);

sysinit.patch:
 cmd/manifest.mn          |    1 
 cmd/sysinit/Makefile     |   80 +++++++++
 cmd/sysinit/config.mk    |  121 ++++++++++++++
 cmd/sysinit/manifest.mn  |   50 +++++
 cmd/sysinit/nsssysinit.c |  329 +++++++++++++++++++++++++++++++++++++++
 lib/pk11wrap/pk11load.c  |  133 +++++++++++++--
 lib/pk11wrap/pk11pars.c  |  394 ++++++++++++++++++++++++++++++++++++++++++++++-
 lib/pk11wrap/pk11util.c  |   82 +++------
 lib/pk11wrap/secmodi.h   |   21 ++
 lib/pki/pki3hack.c       |   10 +
 10 files changed, 1142 insertions(+), 79 deletions(-)

--- NEW FILE sysinit.patch ---
Index: ./mozilla/security/nss/cmd/manifest.mn
===================================================================
RCS file: /cvsroot/mozilla/security/nss/cmd/manifest.mn,v
retrieving revision 1.27
diff -u -p -r1.27 manifest.mn
--- ./mozilla/security/nss/cmd/manifest.mn	4 Sep 2008 22:15:21 -0000	1.27
+++ ./mozilla/security/nss/cmd/manifest.mn	9 Sep 2009 03:40:50 -0000
@@ -75,6 +75,7 @@ DIRS = lib  \
  ssltap  \
  strsclnt \
  symkeyutil \
+ sysinit \
  tests \
  tstclnt  \
  vfychain \
Index: mozilla/security/nss/cmd/sysinit/Makefile
===================================================================
RCS file: security/nss/cmd/sysinit/Makefile
diff -N security/nss/cmd/sysinit/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ./mozilla/security/nss/cmd/sysinit/Makefile	1 Sep 2009 22:47:51 -0000
@@ -0,0 +1,80 @@
+#! gmake
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#######################################################################
+# (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
+
Index: mozilla/security/nss/cmd/sysinit/config.mk
===================================================================
RCS file: security/nss/cmd/sysinit/config.mk
diff -N security/nss/cmd/sysinit/config.mk
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ./mozilla/security/nss/cmd/sysinit/config.mk	1 Sep 2009 22:47:51 -0000
@@ -0,0 +1,121 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+#  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
+
+ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET)))
+ifndef NS_USE_GCC
+# Export 'mktemp' to be backward compatible with NSS 3.2.x and 3.3.x
+# but do not put it in the import library.  See bug 142575.
+DEFINES += -DWIN32_NSS3_DLL_COMPAT
+DLLFLAGS += -EXPORT:mktemp=nss_mktemp,PRIVATE
+endif
+endif
Index: mozilla/security/nss/cmd/sysinit/manifest.mn
===================================================================
RCS file: security/nss/cmd/sysinit/manifest.mn
diff -N security/nss/cmd/sysinit/manifest.mn
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ./mozilla/security/nss/cmd/sysinit/manifest.mn	1 Sep 2009 22:47:51 -0000
@@ -0,0 +1,50 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+CORE_DEPTH	= ../../..
+
+# MODULE public and private header  directories are implicitly REQUIRED.
+MODULE = nss 
+
+DEFINES = -DNSPR20
+
+CSRCS = nsssysinit.c
+
+LIBRARY = nsssysinit
+LIBRARY_NAME = nsssysinit
+#LIBRARY_VERSION = 3
+
Index: mozilla/security/nss/cmd/sysinit/nsssysinit.c
===================================================================
RCS file: security/nss/cmd/sysinit/nsssysinit.c
diff -N security/nss/cmd/sysinit/nsssysinit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ./mozilla/security/nss/cmd/sysinit/nsssysinit.c	1 Sep 2009 22:47:51 -0000
@@ -0,0 +1,329 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Red Hat, Inc
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "seccomon.h"
+#include "prio.h"
+#include "prprf.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 <sys/stat.h>
+#include <sys/types.h>
+
+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"
+char *getUserDB(void)
+{
+   char *userdir = getenv("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_Memcpy(nssdir, userdir, strlen(userdir)+1);
+   /* 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"
+char *getSystemDB(void) {
+   return PORT_Strdup(NSS_DEFAULT_SYSTEM);
+}
+
+#else
+#ifdef XP_WIN
+char *getUserDB(void)
+{
+   /* use the registry to find the user's NSS_DIR. if no entry exists, creaate
+    * one in the users Appdir location */
+}
+
+char *getSystemDB(void)
+{
+   /* use the registry to find the system's NSS_DIR. if no entry exists, creaate
+    * one based on the windows system data area */
+}
+
+#else
+#error "Need to write getUserDB and get SystemDB functions"
+#endif
+#endif
+
+#ifdef XP_LINUX
+PRBool getFIPSMode()
+{
+}
+
+#else
+PRBool getFIPSMode()
+{
+    char *fipsEnv = getenv("NSS_FIPS");
+    if (!fipsEnv) {
+	return 0;
+    }
+    if ((strcasecmp(fipsEnv,"fips") == 0) ||
+	(strcasecmp(fipsEnv,"true") == 0) ||
+	(strcasecmp(fipsEnv,"on") == 0) ||
+	(strcasecmp(fipsEnv,"1") == 0)) {
+	 return 1;
+    }
+    return 0;
+}
+#endif
+
+
+#define NSS_DEFAULT_FLAGS "flags=readonly"
+
+/*
+ * 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 *, 4);
+    char *userdb;
+    int next = 0;
+
+    /* can't get any space */
+    if (module_list == NULL) {
+	return NULL;
+    }
+
+    userdb  = getUserDB();
+    if (userdb != NULL) {
+	/* 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\" "
+	    "NSS=\"flags=internal%s\"", 
+		userdb, stripped_parameters, getFIPSMode() ? ",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) */
+    module_list[next++] = PR_smprintf(
+	"library= "
+	"module=\"NSS system database\" "
+	"parameters=\"configdir='sql:%s' tokenDescription='NSS system database' flags=readonly\" "
+	"NSS=\"flags=internal,critical\"",filename);
+
+    /* that was the last module */
+    module_list[next] = 0;
+
+    PORT_Free(userdb);
+
+    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 "pk11pars.h"
+
+#define TARGET_SPEC_COPY(new, start, end)    \
+  if (end > start) {                         \
+        int _cnt = end - start;              \
+        PORT_Memcpy(new, start, _cnt);       \
+        new += _cnt;                         \
+  }
+
+static void
+safestrcpy(char *target, char *src)
+{
+    while (*src) {
+	*target++ = *src++;
+    }
+    *target = 0;
+}
+
+static SECStatus
+parse_paramters(char *parameters, char **filename, char **stripped)
+{
+    char *sourcePrev;
+    char *sourceCurr;
+    char *targetCurr;
+    char *newStripped;
+    *filename = NULL;
+    *stripped = NULL;
+
+    newStripped = PORT_Alloc(PORT_Strlen(parameters)+2);
+    targetCurr = newStripped;
+    sourcePrev = parameters;
+    sourceCurr = secmod_argStrip(parameters);
+    TARGET_SPEC_COPY(targetCurr, sourcePrev, sourceCurr);
+
+    while (*sourceCurr) {
+	int next;
+	sourcePrev = sourceCurr;
+	SECMOD_HANDLE_STRING_ARG(sourceCurr, *filename, "configdir=",
+		sourcePrev = sourceCurr; )
+	SECMOD_HANDLE_FINAL_ARG(sourceCurr);
+	TARGET_SPEC_COPY(targetCurr, sourcePrev, sourceCurr);
+    }
+    *targetCurr = 0;
+    if (*filename == NULL) {
+	PORT_Free(newStripped);
+	return SECFailure;
+    }
+    if (strncmp("sql:", *filename, 4) == 0) {
+	safestrcpy(*filename, (*filename)+4);
+    } else if (strncmp("dbm:", *filename, 4) == 0) {
+	safestrcpy(*filename, (*filename)+4);
+    } else if (strncmp("extern:", *filename, 7) == 0) {
+	safestrcpy(*filename, (*filename)+7);
+    }
+    *stripped = newStripped;
+    return SECSuccess;
+}
+
+/* entry point */
+char **
+NSS_ReturnModuleSpecData(unsigned long function, char *parameters, void *args)
+{
+    static char *chain = "Chain";
+    char *filename = NULL;
+    char *stripped = NULL;
+    char **retString = NULL;
+    SECStatus rv;
+
+    rv = parse_paramters(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;
+    /* forward add/del to child */
+    case SECMOD_MODULE_DB_FUNCTION_ADD:
+    case SECMOD_MODULE_DB_FUNCTION_DEL:
+	retString = &chain;
+	break;
+    default:
+	retString = NULL;
+	break;
+    }
+
+    if (filename) PORT_Free(filename);
+    if (stripped) PORT_Free(stripped);
+    return retString;
+}
Index: mozilla/security/nss/lib/pk11wrap/pk11load.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11load.c,v
retrieving revision 1.25
diff -u -p -r1.25 pk11load.c
--- ./mozilla/security/nss/lib/pk11wrap/pk11load.c	2 Oct 2008 00:56:15 -0000	1.25
+++ ./mozilla/security/nss/lib/pk11wrap/pk11load.c	1 Sep 2009 22:47:51 -0000
@@ -120,15 +120,83 @@ PRBool pk11_getFinalizeModulesOption(voi
 }
 
 /*
+ * Allow specification loading the same module more than once at init time.
+ * This enables 2 things.
+ *
+ *    1) we can load additional databases by manipulating secmod.db/pkcs11.txt.
+ *    2) we can handle the case where some library has already initialized NSS
+ *    before the main application.
+ *
+ * oldModule is the module we have already initialized.
+ * char *modulespec is the full module spec for the library we want to
+ * initialize.
+ */
+static SECStatus
+secmod_HandleReload(SECMODModule *oldModule, char *modulespec)
+{
+    PK11SlotInfo *slot;
+    char *newModuleSpec;
+    char **children;
+    CK_SLOT_ID *ids;
+    SECStatus rv;
+
+    /* first look for token= key words from the module spec */
+    newModuleSpec = secmod_ParseModuleSpecForTokens(modulespec,&children,&ids);
+    if (!newModuleSpec) {
+	return SECFailure;
+    }
+    slot = SECMOD_OpenNewSlot(oldModule, newModuleSpec);
+    if (slot) {
+	int newID;
+	char **thisChild;
+	CK_SLOT_ID *thisID;
+	char *oldModuleSpec;
+
+	newID = slot->slotID;
+	PK11_FreeSlot(slot);
+	for (thisChild=children, thisID=ids; thisChild && *thisChild; 
+						thisChild++,thisID++) {
+	    slot = SECMOD_OpenNewSlot(oldModule, *thisChild);
+	    if (slot) {
+		*thisID = slot->slotID;
+		PK11_FreeSlot(slot);
+	    } else {
+		*thisID = (CK_SLOT_ID) -1;
+	    }
+	}
+
+	/* update the old module initialization string in case we need to
+	 * shutdown and reinit the whole mess (this is rare, but can happen
+	 * when trying to stop smart card insertion/removal threads)... */
+	oldModuleSpec = secmod_mkAppendTokensList(oldModule->arena, 
+		oldModule->libraryParams, newModuleSpec, newID, 
+		children, ids);
+	if (oldModuleSpec) {
+	    oldModule->libraryParams = oldModuleSpec;
+	}
+	
+	rv = SECSuccess;
+    }
+    secmod_FreeChildren(children, ids);
+    PORT_Free(newModuleSpec);
+    return rv;
+}
+
+/*
  * collect the steps we need to initialize a module in a single function
  */
 SECStatus
-secmod_ModuleInit(SECMODModule *mod, PRBool* alreadyLoaded)
+secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload, 
+		  PRBool* alreadyLoaded)
 {
     CK_C_INITIALIZE_ARGS moduleArgs;
     CK_VOID_PTR pInitArgs;
     CK_RV crv;
 
+    if (reload) {
+	*reload = NULL;
+    }
+
     if (!mod || !alreadyLoaded) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
@@ -144,10 +212,36 @@ secmod_ModuleInit(SECMODModule *mod, PRB
 	pInitArgs = &moduleArgs;
     }
     crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
-    if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
-        (!enforceAlreadyInitializedError)) {
-        *alreadyLoaded = PR_TRUE;
-        return SECSuccess;
+    if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) {
+	SECMODModule *oldModule = NULL;
+
+	/* Library has already been loaded once, if caller expects it, and it
+	 * has additional configuration, try reloading it as well. */
+	if (reload != NULL && mod->libraryParams) {
+	    oldModule = secmod_findModuleByFuncPtr(mod->functionList);
+	}
+	/* Library has been loaded by NSS. It means it may be capable of
+	 * reloading */
+	if (oldModule) {
+	    SECStatus rv;
+	    rv = secmod_HandleReload(oldModule, mod->libraryParams);
+	    if (rv == SECSuccess) {
+		/* This module should go away soon, since we've
+		 * simply expanded the slots on the old module.
+		 * When it goes away, it should not Finalize since
+		 * that will close our old module as well. Setting
+		 * the function list to NULL will prevent that close */
+		mod->functionList = NULL;
+		*reload = oldModule;
+		return SECSuccess;
+	    }
+	    SECMOD_DestroyModule(oldModule);
+	}
+	/* reload not possible, fall back to old semantics */
+	if (!enforceAlreadyInitializedError) {
+       	    *alreadyLoaded = PR_TRUE;
+            return SECSuccess;
+	}
     }
     if (crv != CKR_OK) {
 	if (pInitArgs == NULL ||
@@ -258,7 +352,7 @@ softoken_LoadDSO( void ) 
  * load a new module into our address space and initialize it.
  */
 SECStatus
-SECMOD_LoadPKCS11Module(SECMODModule *mod) {
+secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) {
     PRLibrary *library = NULL;
     CK_C_GetFunctionList entry = NULL;
     char * full_name;
@@ -271,7 +365,7 @@ SECMOD_LoadPKCS11Module(SECMODModule *mo
     if (mod->loaded) return SECSuccess;
 
     /* intenal modules get loaded from their internal list */
-    if (mod->internal) {
+    if (mod->internal && (mod->dllName == NULL)) {
     /*
      * Loads softoken as a dynamic library,
      * even though the rest of NSS assumes this as the "internal" module.
@@ -308,26 +402,14 @@ SECMOD_LoadPKCS11Module(SECMODModule *mo
 	    return SECFailure;
 	}
 
-#ifdef notdef
-	/* look up the library name */
-	full_name = PR_GetLibraryName(PR_GetLibraryPath(),mod->dllName);
-	if (full_name == NULL) {
-	    return SECFailure;
-	}
-#else
 	full_name = PORT_Strdup(mod->dllName);
-#endif
 
 	/* load the library. If this succeeds, then we have to remember to
 	 * unload the library if anything goes wrong from here on out...
 	 */
 	library = PR_LoadLibrary(full_name);
 	mod->library = (void *)library;
-#ifdef notdef
-	PR_FreeLibraryName(full_name);
-#else
 	PORT_Free(full_name);
-#endif
 
 	if (library == NULL) {
 	    return SECFailure;
@@ -375,11 +457,18 @@ SECMOD_LoadPKCS11Module(SECMODModule *mo
     mod->isThreadSafe = PR_TRUE;
 
     /* Now we initialize the module */
-    rv = secmod_ModuleInit(mod, &alreadyLoaded);
+    rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded);
     if (rv != SECSuccess) {
 	goto fail;
     }
 
+    /* module has been reloaded, this module itself is done, 
+     * return to the caller */
+    if (mod->functionList == NULL) {
+	mod->loaded = PR_TRUE; /* technically the module is loaded.. */
+	return SECSuccess;
+    }
+
     /* check the version number */
     if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2;
     if (info.cryptokiVersion.major != 2) goto fail2;
@@ -460,7 +549,9 @@ SECMOD_UnloadModule(SECMODModule *mod) {
 	return SECFailure;
     }
     if (finalizeModules) {
-        if (!mod->moduleDBOnly) PK11_GETTAB(mod)->C_Finalize(NULL);
+        if (mod->functionList &&!mod->moduleDBOnly) {
+	    PK11_GETTAB(mod)->C_Finalize(NULL);
+	}
     }
     mod->moduleID = 0;
     mod->loaded = PR_FALSE;
Index: mozilla/security/nss/lib/pk11wrap/pk11pars.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11pars.c,v
retrieving revision 1.22
diff -u -p -r1.22 pk11pars.c
--- ./mozilla/security/nss/lib/pk11wrap/pk11pars.c	1 Sep 2009 21:56:26 -0000	1.22
+++ ./mozilla/security/nss/lib/pk11wrap/pk11pars.c	1 Sep 2009 22:47:51 -0000
@@ -224,6 +224,389 @@ SECMOD_GetDefaultModDBFlag(SECMODModule 
    return (flags & SECMOD_FLAG_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;
 }
 
+/*
+ * Find any token= values in the module spec. 
+ * Always return a new spec which does not have any token= arguments.
+ * If token= arguments are found, Split the the various tokens defined into
+ * an array of child specs to return.
+ *
+ * Caller is responsible for freeing the child spec and the new token
+ * spec.
+ */
+
+#define SECMOD_SPEC_COPY(new, start, end)    \
+  if (end > start) {                         \
+	int _cnt = end - start;	             \
+	PORT_Memcpy(new, start, _cnt);       \
+	new += _cnt;                         \
+  }
+
+char *
+secmod_ParseModuleSpecForTokens(char *moduleSpec, char ***children, 
+				CK_SLOT_ID **ids)
+{
+    char       *newSpec     = PORT_Alloc(PORT_Strlen(moduleSpec)+2);
+    char       *newSpecPtr  = newSpec;
+    char       *modulePrev  = moduleSpec;
+    char       *target      = NULL;
+    char       **childArray = NULL;
+    char       *tokenIndex;
+    CK_SLOT_ID *idArray     = NULL;
+    int        tokenCount = 0;
+    int        i;
+
+    if (newSpec == NULL) {
+	return NULL;
+    }
+
+    *children = NULL;
+    if (ids) {
+	*ids = NULL;
+    }
+    moduleSpec = secmod_argStrip(moduleSpec);
+    SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
+
+    /*
+     * walk down the list. if we find a tokens= argument, save it,
+     * otherise copy the argument.
+     */
+    while (*moduleSpec) {
+	int next;
+	modulePrev = moduleSpec;
+	SECMOD_HANDLE_STRING_ARG(moduleSpec, target, "tokens=",
+			modulePrev = moduleSpec; /* skip copying */ )
+	SECMOD_HANDLE_FINAL_ARG(moduleSpec)
+	SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
+    }
+    *newSpecPtr = 0;
+
+    /* no target found, return the newSpec */
+    if (target == NULL) {
+	return newSpec;
+    }
+
+    /* now build the child array from target */
+    /*first count them */
+    for (tokenIndex = secmod_argStrip(target); *tokenIndex;
+	tokenIndex = secmod_argStrip(secmod_argSkipParameter(tokenIndex))) {
+	tokenCount++;
+    }
+
+    childArray = PORT_NewArray(char *, tokenCount+1);
+    if (childArray == NULL) {
+	/* just return the spec as is then */
+	PORT_Free(target);
+	return newSpec;
+    }
+    if (ids) {
+	idArray = PORT_NewArray(CK_SLOT_ID, tokenCount+1);
+	if (idArray == NULL) {
+	    PORT_Free(childArray);
+	    PORT_Free(target);
+	    return newSpec;
+	}
+    }
+
+    /* now fill them in */
+    for (tokenIndex = secmod_argStrip(target), i=0 ; 
+			*tokenIndex && (i < tokenCount); 
+			tokenIndex=secmod_argStrip(tokenIndex)) {
+	int next;
+	char *name = secmod_argGetName(tokenIndex, &next);
+	tokenIndex += next;
+
+ 	if (idArray) {
+	   idArray[i] = secmod_argDecodeNumber(name);
+	}
+
+	PORT_Free(name); /* drop the explicit number */
+
+	/* if anything is left, copy the args to the child array */
+	if (!secmod_argIsBlank(*tokenIndex)) {
+	    childArray[i++] = secmod_argFetchValue(tokenIndex, &next);
+	    tokenIndex += next;
+	}
+    }
+
+    PORT_Free(target);
+    childArray[i] = 0;
+    if (idArray) {
+	idArray[i] = 0;
+    }
+
+    /* return it */
+    *children = childArray;
+    if (ids) {
+	*ids = idArray;
+    }
+    return newSpec;
+}
+
+void
+secmod_FreeChildren(char **children, CK_SLOT_ID *ids)
+{
+    char **thisChild = children;
+
+    if (!children) {
+	return;
+    }
+
+    for (thisChild = children; thisChild && *thisChild; thisChild++ ) {
+	PORT_Free(*thisChild);
+    }
+    PORT_Free(children);
+    if (ids) {
+	PORT_Free(ids);
+    }
+    return;
+}
+
+
+static int
+secmod_escapeSize(const char *string, char quote)
+{
+    int escapes = 0, size = 0;
+    const char *src;
+    for (src=string; *src ; src++) {
+        if ((*src == quote) || (*src == '\\')) escapes++;
+        size++;
+    }
+
+    return escapes+size+1;
+}
+
+
+/*
+ * add escapes to protect quote characters...
+ */
+static char *
+secmod_addEscape(const char *string, char quote)
+{
+    char *newString = 0;
+    int size = 0;
+    const char *src;
+    char *dest;
+
+
+    size = secmod_escapeSize(string,quote);
+    newString = PORT_ZAlloc(size);
+    if (newString == NULL) {
+        return NULL;
+    }
+
+    for (src=string, dest=newString; *src; src++,dest++) {
+        if ((*src == '\\') || (*src == quote)) {
+            *dest++ = '\\';
+        }
+        *dest = *src;
+    }
+
+    return newString;
+}
+
+static int
+secmod_doubleEscapeSize(const char *string, char quote1, char quote2)
+{
+    int escapes = 0, size = 0;
+    const char *src;
+    for (src=string; *src ; src++) {
+        if (*src == '\\')   escapes+=3; /* \\\\ */
+        if (*src == quote1) escapes+=2; /* \\quote1 */
+        if (*src == quote2) escapes++;   /* \quote2 */
+        size++;
+    }
+
+    return escapes+size+1;
+}
+
+char *
+secmod_doubleEscape(const char *string, char quote1, char quote2)
+{
+    char *round1 = NULL;
+    char *retValue = NULL;
+    if (string == NULL) {
+        goto done;
+    }
+    round1 = secmod_addEscape(string,quote1);
+    if (round1) {
+        retValue = secmod_addEscape(round1,quote2);
+        PORT_Free(round1);
+    }
+
+done:
+    if (retValue == NULL) {
+        retValue = PORT_Strdup("");
+    }
+    return retValue;
+}
+
+
+/*
+ * caclulate the length of each child record:
+ * " 0x{id}=<{escaped_child}>"
+ */
+static int
+secmod_getChildLength(char *child, CK_SLOT_ID id)
+{
+    int length = secmod_doubleEscapeSize(child, '>', ']');
+    if (id == 0) {
+	length++;
+    }
+    while (id) {
+	length++;
+	id = id >> 4;
+    }
+    length += 6; /* {sp}0x[id]=<{child}> */
+    return length;
+}
+
+/*
+ * Build a child record:
+ * " 0x{id}=<{escaped_child}>"
+ */
+SECStatus
+secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id)
+{
+    int len;
+    char *escSpec;
+
+    len = PR_snprintf(*next, *length, " 0x%x=<",id);
+    if (len < 0) {
+	return SECFailure;
+    }
+    *next += len;
+    *length -= len;
+    escSpec = secmod_doubleEscape(child, '>', ']');
+    if (escSpec == NULL) {
+	return SECFailure;
+    }
+    if (*child && (*escSpec == 0)) {
+	PORT_Free(escSpec);
+	return SECFailure;
+    }
+    len = strlen(escSpec);
+    if (len+1 > *length) {
+	PORT_Free(escSpec);
+	return SECFailure;
+    }
+    PORT_Memcpy(*next,escSpec, len);
+    *next += len;
+    *length -= len;
+    PORT_Free(escSpec);
+    **next = '>';
+    (*next)++;
+    (*length)--;
+    return SECSuccess;
+}
+
+#define TOKEN_STRING " tokens=["
+
+char *
+secmod_mkAppendTokensList(PRArenaPool *arena, char *oldParam, char *newToken, 
+			CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids)
+{
+    char *rawParam = NULL;	/* oldParam with tokens stripped off */
+    char *newParam = NULL;	/* space for the return parameter */
+    char *nextParam = NULL;	/* current end of the new parameter */
+    char **oldChildren = NULL;
+    CK_SLOT_ID *oldIds = NULL;
+    void *mark = NULL;         /* mark the arena pool in case we need 
+				* to release it */
+    int length, i, tmpLen;
+    SECStatus rv;
+
+    /* first strip out and save the old tokenlist */
+    rawParam = secmod_ParseModuleSpecForTokens(oldParam,&oldChildren,&oldIds);
+    if (!rawParam) {
+	goto loser;
+    }
+
+    /* now calculate the total length of the new buffer */
+    /* First the 'fixed stuff', length of rawparam (does not include a NULL),
+     * length of the token string (does include the NULL), closing bracket */
+    length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1;
+    /* now add then length of all the old children */
+    for (i=0; oldChildren && oldChildren[i]; i++) {
+	length += secmod_getChildLength(oldChildren[i], oldIds[i]);
+    }
+
+    /* add the new token */
+    length += secmod_getChildLength(newToken, newID);
+
+    /* and it's new children */
+    for (i=0; children && children[i]; i++) {
+	if (ids[i] == -1) {
+	    continue;
+	}
+	length += secmod_getChildLength(children[i], ids[i]);
+    }
+
+    /* now allocate and build the string */
+    mark = PORT_ArenaMark(arena);
+    if (!mark) {
+	goto loser;
+    }
+    newParam =  PORT_ArenaAlloc(arena,length);
+    if (!newParam) {
+	goto loser;
+    }
+
+    PORT_Strcpy(newParam, oldParam);
+    tmpLen = strlen(oldParam);
+    nextParam = newParam + tmpLen;
+    length -= tmpLen;
+    PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING)-1);
+    nextParam += sizeof(TOKEN_STRING)-1;
+    length -= sizeof(TOKEN_STRING)-1;
+
+    for (i=0; oldChildren && oldChildren[i]; i++) {
+	rv = secmod_mkTokenChild(&nextParam,&length,oldChildren[i],oldIds[i]);
+	if (rv != SECSuccess) {
+	    goto loser;
+	}
+    }
+
+    rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID);
+    if (rv != SECSuccess) {
+	goto loser;
+    }
+
+    for (i=0; children && children[i]; i++) {
+	if (ids[i] == -1) {
+	    continue;
+	}
+	rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]);
+	if (rv != SECSuccess) {
+	    goto loser;
+	}
+    }
+
+    if (length < 2) {
+	goto loser;
+    }
+
+    *nextParam++ = ']';
+    *nextParam++ = 0;
+
+    /* we are going to return newParam now, don't release the mark */
+    PORT_ArenaUnmark(arena, mark);
+    mark = NULL;
+
+loser:
+    if (mark) {
+	PORT_ArenaRelease(arena, mark);
+	newParam = NULL; /* if the mark is still active, 
+			  * don't return the param */
+    }
+    if (rawParam) {
+	PORT_Free(rawParam);
+    }
+    if (oldChildren) {
+	secmod_FreeChildren(oldChildren, oldIds);
+    }
+    return newParam;
+}
+    
 static char *
 secmod_mkModuleSpec(SECMODModule * module)
 {
@@ -365,6 +748,7 @@ SECMOD_LoadModule(char *modulespec,SECMO
     char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL;
     SECStatus status;
     SECMODModule *module = NULL;
+    SECMODModule *oldModule = NULL;
     SECStatus rv;
 
     /* initialize the underlying module structures */
@@ -389,11 +773,19 @@ SECMOD_LoadModule(char *modulespec,SECMO
     }
 
     /* load it */
-    rv = SECMOD_LoadPKCS11Module(module);
+    rv = secmod_LoadPKCS11Module(module, &oldModule);
     if (rv != SECSuccess) {
 	goto loser;
     }
 
+    /* if we just reload an old module, no need to add it to any lists.
+     * we simple release all our references */
+    if (oldModule) {
+	SECMOD_DestroyModule(module);
+	SECMOD_DestroyModule(oldModule);
+	return SECSuccess;
+    }
+
     if (recurse && module->isModuleDB) {
 	char ** moduleSpecList;
 	PORT_SetError(0);
Index: mozilla/security/nss/lib/pk11wrap/pk11util.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/pk11util.c,v
retrieving revision 1.56
diff -u -p -r1.56 pk11util.c
--- ./mozilla/security/nss/lib/pk11wrap/pk11util.c	1 Sep 2009 21:56:26 -0000	1.56
+++ ./mozilla/security/nss/lib/pk11wrap/pk11util.c	1 Sep 2009 22:47:51 -0000
@@ -285,6 +285,30 @@ SECMOD_FindModuleByID(SECMODModuleID id)
 }
 
 /*
+ * find the function pointer.
+ */
+SECMODModule *
+secmod_findModuleByFuncPtr(void *funcPtr) 
+{
+    SECMODModuleList *mlp;
+    SECMODModule *module = NULL;
+
+    SECMOD_GetReadLock(moduleLock);
+    for(mlp = modules; mlp != NULL; mlp = mlp->next) {
+	if (funcPtr == mlp->module->functionList) {
+	    module = mlp->module;
+	    SECMOD_ReferenceModule(module);
+	    break;
+	}
+    }
+    SECMOD_ReleaseReadLock(moduleLock);
+    if (module == NULL) {
+	PORT_SetError(SEC_ERROR_NO_MODULE);
+    }
+    return module;
+}
+
+/*
  * Find the Slot based on ID and the module.
  */
 PK11SlotInfo *
@@ -508,7 +532,7 @@ SECMOD_AddModule(SECMODModule *newModule
         /* module already exists. */
     }
 
-    rv = SECMOD_LoadPKCS11Module(newModule);
+    rv = secmod_LoadPKCS11Module(newModule, NULL);
     if (rv != SECSuccess) {
 	return rv;
     }
@@ -1202,7 +1226,7 @@ SECMOD_CancelWait(SECMODModule *mod)
 	 * we intend to use it again */
 	if (CKR_OK == crv) {
             PRBool alreadyLoaded;
-	    secmod_ModuleInit(mod, &alreadyLoaded);
+	    secmod_ModuleInit(mod, NULL, &alreadyLoaded);
 	} else {
 	    /* Finalized failed for some reason,  notify the application
 	     * so maybe it has a prayer of recovering... */
@@ -1279,58 +1303,6 @@ secmod_UserDBOp(PK11SlotInfo *slot, CK_O
 }
 
 /*
- * add escapes to protect quote characters...
- */
-static char *
-nss_addEscape(const char *string, char quote)
-{
-    char *newString = 0;
-    int escapes = 0, size = 0;
-    const char *src;
-    char *dest;
-
-    for (src=string; *src ; src++) {
-        if ((*src == quote) || (*src == '\\')) escapes++;
-        size++;
-    }
-
-    newString = PORT_ZAlloc(escapes+size+1);
-    if (newString == NULL) {
-        return NULL;
-    }
-
-    for (src=string, dest=newString; *src; src++,dest++) {
-        if ((*src == '\\') || (*src == quote)) {
-            *dest++ = '\\';
-        }
-        *dest = *src;
-    }
-
-    return newString;
-}
-
-static char *
-nss_doubleEscape(const char *string)
-{
-    char *round1 = NULL;
-    char *retValue = NULL;
-    if (string == NULL) {
-        goto done;
-    }
-    round1 = nss_addEscape(string,'>');
-    if (round1) {
-        retValue = nss_addEscape(round1,']');
-        PORT_Free(round1);
-    }
-
-done:
-    if (retValue == NULL) {
-        retValue = PORT_Strdup("");
-    }
-    return retValue;
-}
-
-/*
  * return true if the selected slot ID is not present or doesn't exist
  */
 static PRBool
@@ -1412,7 +1384,7 @@ SECMOD_OpenNewSlot(SECMODModule *mod, co
     }
 
     /* we've found the slot, now build the moduleSpec */
-    escSpec = nss_doubleEscape(moduleSpec);
+    escSpec = secmod_doubleEscape(moduleSpec, '>', ']');
     if (escSpec == NULL) {
 	PK11_FreeSlot(slot);
 	return NULL;
Index: mozilla/security/nss/lib/pk11wrap/secmodi.h
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pk11wrap/secmodi.h,v
retrieving revision 1.31
diff -u -p -r1.31 secmodi.h
--- ./mozilla/security/nss/lib/pk11wrap/secmodi.h	2 Dec 2008 23:24:50 -0000	1.31
+++ ./mozilla/security/nss/lib/pk11wrap/secmodi.h	1 Sep 2009 22:47:51 -0000
@@ -58,7 +58,8 @@ void nss_DumpModuleLog(void);
 extern int secmod_PrivateModuleCount;
 
 extern void SECMOD_Init(void);
-SECStatus secmod_ModuleInit(SECMODModule *mod, PRBool* alreadyLoaded);
+SECStatus secmod_ModuleInit(SECMODModule *mod, SECMODModule **oldModule,
+			    PRBool* alreadyLoaded);
 
 /* list managment */
 extern SECStatus SECMOD_AddModuleToList(SECMODModule *newModule);
@@ -73,6 +74,7 @@ extern void SECMOD_ReleaseWriteLock(SECM
 
 /* Operate on modules by name */
 extern SECMODModule *SECMOD_FindModuleByID(SECMODModuleID);
+extern SECMODModule *secmod_findModuleByFuncPtr(void *funcPtr);
 
 /* database/memory management */
 extern SECMODModuleList *SECMOD_NewModuleListElement(void);
@@ -84,10 +86,25 @@ extern unsigned long SECMOD_InternaltoPu
 extern unsigned long SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags);
 
 /* Library functions */
-SECStatus SECMOD_LoadPKCS11Module(SECMODModule *);
+SECStatus secmod_LoadPKCS11Module(SECMODModule *, SECMODModule **oldModule);
 SECStatus SECMOD_UnloadModule(SECMODModule *);
 void SECMOD_SetInternalModule(SECMODModule *);
 
+/* parsing parameters */
+/* returned char * must be freed by caller with PORT_Free */
+/* children and ids are null terminated arrays which must be freed with
+ * secmod_FreeChildren */
+char *secmod_ParseModuleSpecForTokens(char *moduleSpec,
+				      char ***children, 
+				      CK_SLOT_ID **ids);
+void secmod_FreeChildren(char **children, CK_SLOT_ID *ids);
+char *secmod_mkAppendTokensList(PRArenaPool *arena, char *origModuleSpec, 
+				char *newModuleSpec, CK_SLOT_ID newID,
+				char **children, CK_SLOT_ID *ids);
+char *secmod_doubleEscape(const char *string, char quote1, char quote2);
+
+
+
 void SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot);
 CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
                                                          CK_VOID_PTR pdata);
Index: mozilla/security/nss/lib/pki/pki3hack.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/pki/pki3hack.c,v
retrieving revision 1.97
diff -u -p -r1.97 pki3hack.c
--- ./mozilla/security/nss/lib/pki/pki3hack.c	30 Jul 2009 22:43:32 -0000	1.97
+++ ./mozilla/security/nss/lib/pki/pki3hack.c	1 Sep 2009 22:47:51 -0000
@@ -101,6 +101,11 @@ STAN_InitTokenForSlotInfo(NSSTrustDomain
     NSSToken *token;
     if (!td) {
 	td = g_default_trust_domain;
+	if (!td) {
+	    /* we're called while still initting. slot will get added
+	     * appropriately through normal init processes */
+	    return PR_SUCCESS;
+	}
     }
     token = nssToken_CreateFromPK11SlotInfo(td, slot);
     PK11Slot_SetNSSToken(slot, token);
@@ -118,6 +123,11 @@ STAN_ResetTokenInterator(NSSTrustDomain 
 {
     if (!td) {
 	td = g_default_trust_domain;
+	if (!td) {
+	    /* we're called while still initting. slot will get added
+	     * appropriately through normal init processes */
+	    return PR_SUCCESS;
+	}
     }
     NSSRWLock_LockWrite(td->tokensLock);
     nssListIterator_Destroy(td->tokens);




More information about the fedora-extras-commits mailing list