From 944d7ff57fbda967db73114c2c8d49eff3f83160 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 6 Apr 2012 16:05:25 +0200 Subject: [PATCH 1/2] nss: unconditionally require PK11_CreateGenericObject() This bumps the minimal supported version of NSS to 3.12.x. [upstream commit 42aa7961] Signed-off-by: Kamil Dudka --- configure | 64 +++++++--------------------------------------- configure.ac | 10 +------ docs/INTERNALS | 2 +- lib/config-symbian.h | 3 -- lib/config-vxworks.h | 3 -- lib/curl_config.h.cmake | 3 -- lib/curl_config.h.in | 3 -- lib/nss.c | 30 +-------------------- lib/urldata.h | 2 - 9 files changed, 15 insertions(+), 105 deletions(-) diff --git a/configure b/configure index 8b0b30a..d20dab3 100755 --- a/configure +++ b/configure @@ -672,7 +672,6 @@ CURL_CA_BUNDLE SSL_ENABLED USE_AXTLS USE_NSS -HAVE_PK11_CREATEGENERICOBJECT USE_CYASSL USE_POLARSSL HAVE_GNUTLS_SRP @@ -22530,49 +22529,6 @@ $as_echo "found" >&6; } nssprefix=$OPT_NSS fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PK11_CreateGenericObject in -lnss3" >&5 -$as_echo_n "checking for PK11_CreateGenericObject in -lnss3... " >&6; } -if test "${ac_cv_lib_nss3_PK11_CreateGenericObject+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnss3 $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -#ifdef __cplusplus -extern "C" -#endif -char PK11_CreateGenericObject (); -int main (void) -{ -return PK11_CreateGenericObject (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_nss3_PK11_CreateGenericObject=yes -else - ac_cv_lib_nss3_PK11_CreateGenericObject=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_PK11_CreateGenericObject" >&5 -$as_echo "$ac_cv_lib_nss3_PK11_CreateGenericObject" >&6; } -if test "x$ac_cv_lib_nss3_PK11_CreateGenericObject" = x""yes; then : - - -$as_echo "#define HAVE_PK11_CREATEGENERICOBJECT 1" >>confdefs.h - - HAVE_PK11_CREATEGENERICOBJECT=1 - - -fi - if test -n "$addlib"; then CLEANLIBS="$LIBS" @@ -22583,9 +22539,9 @@ fi CPPFLAGS="$CPPFLAGS $addcflags" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NSS_Initialize in -lnss3" >&5 -$as_echo_n "checking for NSS_Initialize in -lnss3... " >&6; } -if test "${ac_cv_lib_nss3_NSS_Initialize+set}" = set; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PK11_CreateGenericObject in -lnss3" >&5 +$as_echo_n "checking for PK11_CreateGenericObject in -lnss3... " >&6; } +if test "${ac_cv_lib_nss3_PK11_CreateGenericObject+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22597,26 +22553,26 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char NSS_Initialize (); +char PK11_CreateGenericObject (); int main (void) { -return NSS_Initialize (); +return PK11_CreateGenericObject (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_nss3_NSS_Initialize=yes + ac_cv_lib_nss3_PK11_CreateGenericObject=yes else - ac_cv_lib_nss3_NSS_Initialize=no + ac_cv_lib_nss3_PK11_CreateGenericObject=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_NSS_Initialize" >&5 -$as_echo "$ac_cv_lib_nss3_NSS_Initialize" >&6; } -if test "x$ac_cv_lib_nss3_NSS_Initialize" = x""yes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_PK11_CreateGenericObject" >&5 +$as_echo "$ac_cv_lib_nss3_PK11_CreateGenericObject" >&6; } +if test "x$ac_cv_lib_nss3_PK11_CreateGenericObject" = x""yes; then : $as_echo "#define USE_NSS 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 631563d..1b48f7b 100644 --- a/configure.ac +++ b/configure.ac @@ -2079,13 +2079,6 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then nssprefix=$OPT_NSS fi - dnl Check for functionPK11_CreateGenericObject - dnl this is needed for using the PEM PKCS#11 module - AC_CHECK_LIB(nss3, PK11_CreateGenericObject, - [ - AC_DEFINE(HAVE_PK11_CREATEGENERICOBJECT, 1, [if you have the function PK11_CreateGenericObject]) - AC_SUBST(HAVE_PK11_CREATEGENERICOBJECT, [1]) - ]) if test -n "$addlib"; then CLEANLIBS="$LIBS" @@ -2096,7 +2089,8 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then CPPFLAGS="$CPPFLAGS $addcflags" fi - AC_CHECK_LIB(nss3, NSS_Initialize, + dnl The function PK11_CreateGenericObject is needed to load libnsspem.so + AC_CHECK_LIB(nss3, PK11_CreateGenericObject, [ AC_DEFINE(USE_NSS, 1, [if NSS is enabled]) AC_SUBST(USE_NSS, [1]) diff --git a/docs/INTERNALS b/docs/INTERNALS index 39c4df7..8024ea8 100644 --- a/docs/INTERNALS +++ b/docs/INTERNALS @@ -43,7 +43,7 @@ Portability openldap 2.0 MIT krb5 lib 1.2.4 qsossl V5R2M0 - NSS 3.11.x + NSS 3.12.x axTLS 1.2.7 Heimdal ? diff --git a/lib/config-symbian.h b/lib/config-symbian.h index 24ed733..417025a 100644 --- a/lib/config-symbian.h +++ b/lib/config-symbian.h @@ -400,9 +400,6 @@ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 -/* if you have the function PK11_CreateGenericObject */ -/* #undef HAVE_PK11_CREATEGENERICOBJECT */ - /* Define to 1 if you have the `poll' function. */ /*#define HAVE_POLL 1*/ diff --git a/lib/config-vxworks.h b/lib/config-vxworks.h index 8e2d05a..9149507 100644 --- a/lib/config-vxworks.h +++ b/lib/config-vxworks.h @@ -469,9 +469,6 @@ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 -/* if you have the function PK11_CreateGenericObject */ -/* #undef HAVE_PK11_CREATEGENERICOBJECT */ - /* Define to 1 if you have a working poll function. */ /* #undef HAVE_POLL */ diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index a321302..88b4de2 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -444,9 +444,6 @@ /* Define to 1 if you have the `pipe' function. */ #cmakedefine HAVE_PIPE ${HAVE_PIPE} -/* if you have the function PK11_CreateGenericObject */ -#cmakedefine HAVE_PK11_CREATEGENERICOBJECT ${HAVE_PK11_CREATEGENERICOBJECT} - /* Define to 1 if you have a working poll function. */ #cmakedefine HAVE_POLL ${HAVE_POLL} diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in index 5823939..e79c364 100644 --- a/lib/curl_config.h.in +++ b/lib/curl_config.h.in @@ -506,9 +506,6 @@ /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE -/* if you have the function PK11_CreateGenericObject */ -#undef HAVE_PK11_CREATEGENERICOBJECT - /* Define to 1 if you have a working poll function. */ #undef HAVE_POLL diff --git a/lib/nss.c b/lib/nss.c index 8f6da50..6108917 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -170,9 +170,7 @@ static const int enable_ciphers_by_default[] = { SSL_NULL_WITH_NULL_NULL }; -#ifdef HAVE_PK11_CREATEGENERICOBJECT static const char* pem_library = "libnsspem.so"; -#endif SECMODModule* mod = NULL; static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, @@ -305,7 +303,6 @@ static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind) return NULL; } -#ifdef HAVE_PK11_CREATEGENERICOBJECT /* Call PK11_CreateGenericObject() with the given obj_class and filename. If * the call succeeds, append the object handle to the list of objects so that * the object can be destroyed in Curl_nss_close(). */ @@ -369,7 +366,6 @@ static void nss_destroy_object(void *user, void *ptr) (void) user; PK11_DestroyGenericObject(obj); } -#endif static CURLcode nss_load_cert(struct ssl_connect_data *ssl, const char *filename, PRBool cacert) @@ -378,7 +374,6 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl, ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; -#ifdef HAVE_PK11_CREATEGENERICOBJECT /* libnsspem.so leaks memory if the requested file does not exist. For more * details, go to . */ if(is_file(filename)) @@ -405,7 +400,6 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl, free(nickname); } } -#endif return err; } @@ -499,10 +493,10 @@ fail: static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { -#ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo *slot; SECStatus status; struct ssl_connect_data *ssl = conn->ssl; + (void)sockindex; /* unused */ CURLcode rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); if(CURLE_OK != rv) { @@ -524,15 +518,6 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; -#else - /* If we don't have PK11_CreateGenericObject then we can't load a file-based - * key. - */ - (void)conn; /* unused */ - (void)key_file; /* unused */ - return CURLE_SSL_CERTPROBLEM; -#endif - (void)sockindex; /* unused */ } static int display_error(struct connectdata *conn, PRInt32 err, @@ -775,7 +760,6 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct SessionHandle *data = connssl->data; const char *nickname = connssl->client_nickname; -#ifdef HAVE_PK11_CREATEGENERICOBJECT if(connssl->obj_clicert) { /* use the cert/key provided by PEM reader */ static const char pem_slotname[] = "PEM Token #1"; @@ -815,7 +799,6 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, display_cert_info(data, *pRetCert); return SECSuccess; } -#endif /* use the default NSS hook */ if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, @@ -1053,12 +1036,11 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) * next time to the same server */ SSL_InvalidateSession(connssl->handle); } -#ifdef HAVE_PK11_CREATEGENERICOBJECT /* destroy all NSS objects in order to avoid failure of NSS shutdown */ Curl_llist_destroy(connssl->obj_list, NULL); connssl->obj_list = NULL; connssl->obj_clicert = NULL; -#endif + PR_Close(connssl->handle); connssl->handle = NULL; } @@ -1173,12 +1155,10 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) connssl->data = data; -#ifdef HAVE_PK11_CREATEGENERICOBJECT /* list of all NSS objects we need to destroy in Curl_nss_close() */ connssl->obj_list = Curl_llist_alloc(nss_destroy_object); if(!connssl->obj_list) return CURLE_OUT_OF_MEMORY; -#endif /* FIXME. NSS doesn't support multiple databases open at the same time. */ PR_Lock(nss_initlock); @@ -1190,7 +1170,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) curlerr = CURLE_SSL_CONNECT_ERROR; -#ifdef HAVE_PK11_CREATEGENERICOBJECT if(!mod) { char *configstring = aprintf("library=%s name=PEM", pem_library); if(!configstring) { @@ -1209,7 +1188,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) "OpenSSL PEM certificates will not work.\n", pem_library); } } -#endif PK11_SetPasswordFunc(nss_get_password); PR_Unlock(nss_initlock); @@ -1340,9 +1318,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) char *nickname = dup_nickname(data, STRING_CERT); if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ -#ifdef HAVE_PK11_CREATEGENERICOBJECT connssl->obj_clicert = NULL; -#endif } else { CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], @@ -1442,11 +1418,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) if(model) PR_Close(model); -#ifdef HAVE_PK11_CREATEGENERICOBJECT /* cleanup on connection failure */ Curl_llist_destroy(connssl->obj_list, NULL); connssl->obj_list = NULL; -#endif if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) { /* schedule reconnect through Curl_retry_request() */ diff --git a/lib/urldata.h b/lib/urldata.h index 7830686..8b6023c 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -271,10 +271,8 @@ struct ssl_connect_data { PRFileDesc *handle; char *client_nickname; struct SessionHandle *data; -#ifdef HAVE_PK11_CREATEGENERICOBJECT struct curl_llist *obj_list; PK11GenericObject *obj_clicert; -#endif #endif /* USE_NSS */ #ifdef USE_QSOSSL SSLHandle *handle; -- 1.7.1 From 1467ca453bc0feed5109227c09e8e47c2de079d1 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 10 Apr 2012 15:42:34 +0200 Subject: [PATCH 2/2] 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 [upstream commit 20cb12db] Signed-off-by: Kamil Dudka --- configure | 13 +++++++++++++ configure.ac | 8 ++++++++ lib/Makefile.in | 2 +- lib/curl_config.h.in | 3 +++ lib/nss.c | 37 ++++++++++++++++++++++++++++++++++++- 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/configure b/configure index d20dab3..495f65a 100755 --- a/configure +++ b/configure @@ -671,6 +671,7 @@ USE_LIBSSH2 CURL_CA_BUNDLE SSL_ENABLED USE_AXTLS +HAVE_NSS_INITCONTEXT USE_NSS USE_CYASSL USE_POLARSSL @@ -22595,6 +22596,18 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: detected NSS version $version" >&5 $as_echo "$as_me: detected NSS version $version" >&6;} + ac_fn_c_check_func "$LINENO" "NSS_InitContext" "ac_cv_func_NSS_InitContext" +if test "x$ac_cv_func_NSS_InitContext" = x""yes; then : + + +$as_echo "#define HAVE_NSS_INITCONTEXT 1" >>confdefs.h + + HAVE_NSS_INITCONTEXT=1 + + +fi + + if test "x$cross_compiling" != "xyes"; then LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$nssprefix/lib$libsuff" export LD_LIBRARY_PATH diff --git a/configure.ac b/configure.ac index 1b48f7b..54b0af3 100644 --- a/configure.ac +++ b/configure.ac @@ -2106,6 +2106,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/Makefile.in b/lib/Makefile.in index bdfd796..c4468ab 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -233,7 +233,7 @@ HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ HAVE_LIBZ = @HAVE_LIBZ@ HAVE_LIBZ_FALSE = @HAVE_LIBZ_FALSE@ HAVE_LIBZ_TRUE = @HAVE_LIBZ_TRUE@ -HAVE_PK11_CREATEGENERICOBJECT = @HAVE_PK11_CREATEGENERICOBJECT@ +HAVE_NSS_INITCONTEXT = @HAVE_NSS_INITCONTEXT@ HAVE_SSLEAY_SRP = @HAVE_SSLEAY_SRP@ IDN_ENABLED = @IDN_ENABLED@ INSTALL_DATA = @INSTALL_DATA@ diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in index e79c364..a613f7d 100644 --- a/lib/curl_config.h.in +++ b/lib/curl_config.h.in @@ -469,6 +469,9 @@ /* Define to 1 if NI_WITHSCOPEID exists and works. */ #undef HAVE_NI_WITHSCOPEID +/* if you have the NSS_InitContext function */ +#undef HAVE_NSS_INITCONTEXT + /* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */ #undef HAVE_OLD_GSSMIT diff --git a/lib/nss.c b/lib/nss.c index 6108917..16127ee 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) { +#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); -- 1.7.1