From 20cb12db8df6f956b885a5215bcffd425f2d34dd Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 10 Apr 2012 15:42:34 +0200 Subject: [PATCH] nss: use NSS_InitContext() to initialize NSS if available NSS_InitContext() was introduced in NSS 3.12.5 and helps to prevent collisions on NSS initialization/shutdown with other libraries. Bug: https://bugzilla.redhat.com/738456 --- RELEASE-NOTES | 2 ++ configure.ac | 8 ++++++++ lib/nss.c | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 58a4cbd65..15b1d0a2a 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -14,6 +14,7 @@ This release includes the following changes: This release includes the following bugfixes: + o nss: libcurl now uses NSS_InitContext() to prevent collisions if available [1] o This release includes the following known bugs: @@ -29,4 +30,5 @@ advice from friends like these: References to bug reports and discussions on issues: + [1] = https://bugzilla.redhat.com/738456 diff --git a/configure.ac b/configure.ac index 541c74f3d..89f26f47a 100644 --- a/configure.ac +++ b/configure.ac @@ -2118,6 +2118,14 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then if test "x$USE_NSS" = "xyes"; then AC_MSG_NOTICE([detected NSS version $version]) + dnl NSS_InitContext() was introduced in NSS 3.12.5 and helps to prevent + dnl collisions on NSS initialization/shutdown with other libraries + AC_CHECK_FUNC(NSS_InitContext, + [ + AC_DEFINE(HAVE_NSS_INITCONTEXT, 1, [if you have the NSS_InitContext function]) + AC_SUBST(HAVE_NSS_INITCONTEXT, [1]) + ]) + dnl when shared libs were found in a path that the run-time dnl linker doesn't search through, we need to add it to dnl LD_LIBRARY_PATH to prevent further configure tests to fail diff --git a/lib/nss.c b/lib/nss.c index 61089173c..16127ee7f 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -78,6 +78,9 @@ PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); PRLock * nss_initlock = NULL; PRLock * nss_crllock = NULL; +#ifdef HAVE_NSS_INITCONTEXT +NSSInitContext * nss_context = NULL; +#endif volatile int initialized = 0; @@ -861,29 +864,56 @@ isTLSIntoleranceError(PRInt32 err) static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) { - if(NSS_IsInitialized()) +#ifdef HAVE_NSS_INITCONTEXT + if(nss_context != NULL) return CURLE_OK; + NSSInitParameters initparams; + memset((void *) &initparams, '\0', sizeof(initparams)); + initparams.length = sizeof(initparams); +#else /* HAVE_NSS_INITCONTEXT */ + SECStatus rv; + + if(NSS_IsInitialized()) + return CURLE_OK; +#endif + if(cert_dir) { - SECStatus rv; const bool use_sql = NSS_VersionCheck("3.12.0"); char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir); if(!certpath) return CURLE_OUT_OF_MEMORY; infof(data, "Initializing NSS with certpath: %s\n", certpath); +#ifdef HAVE_NSS_INITCONTEXT + nss_context = NSS_InitContext(certpath, "", "", "", &initparams, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + free(certpath); + + if(nss_context != NULL) + return CURLE_OK; +#else /* HAVE_NSS_INITCONTEXT */ rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); free(certpath); if(rv == SECSuccess) return CURLE_OK; +#endif infof(data, "Unable to initialize NSS database\n"); } infof(data, "Initializing NSS with certpath: none\n"); +#ifdef HAVE_NSS_INITCONTEXT + nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY + | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN + | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); + if(nss_context != NULL) + return CURLE_OK; +#else /* HAVE_NSS_INITCONTEXT */ if(NSS_NoDB_Init(NULL) == SECSuccess) return CURLE_OK; +#endif infof(data, "Unable to initialize NSS\n"); return CURLE_SSL_CACERT_BADFILE; @@ -979,7 +1009,12 @@ void Curl_nss_cleanup(void) SECMOD_DestroyModule(mod); mod = NULL; } +#ifdef HAVE_NSS_INITCONTEXT + NSS_ShutdownContext(nss_context); + nss_context = NULL; +#else /* HAVE_NSS_INITCONTEXT */ NSS_Shutdown(); +#endif } PR_Unlock(nss_initlock);