From 592250ebfbcc7aa47f22bf1f8613fe20f33fd39a Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Feb 20 2015 10:06:24 +0000 Subject: link against moznss again (#1187742) Revert "link against openssl by default" This reverts commit 72da77adb69905307f8c22d15c5ab299ed32d38f. --- diff --git a/openldap-autoconf-pkgconfig-nss.patch b/openldap-autoconf-pkgconfig-nss.patch new file mode 100644 index 0000000..8b4bb19 --- /dev/null +++ b/openldap-autoconf-pkgconfig-nss.patch @@ -0,0 +1,49 @@ +Use pkg-config for Mozilla NSS library detection + +Author: Jan Vcelak + +--- + configure.in | 22 +++++----------------- + 1 file changed, 5 insertions(+), 17 deletions(-) + +diff --git a/configure.in b/configure.in +index ecffe30..2a9cfb4 100644 +--- a/configure.in ++++ b/configure.in +@@ -1223,28 +1223,16 @@ if test $ol_link_tls = no ; then + fi + fi + +-dnl NOTE: caller must specify -I/path/to/nspr4 and -I/path/to/nss3 +-dnl and -L/path/to/nspr4 libs and -L/path/to/nss3 libs if those libs +-dnl are not in the default system location + if test $ol_link_tls = no ; then + if test $ol_with_tls = moznss || test $ol_with_tls = auto ; then +- have_moznss=no +- AC_CHECK_HEADERS([nssutil.h]) +- if test "$ac_cv_header_nssutil_h" = yes ; then +- AC_CHECK_LIB([nss3], [NSS_Initialize], +- [ have_moznss=yes ], [ have_moznss=no ]) +- fi ++ PKG_CHECK_MODULES(MOZNSS, [nss nspr], [have_moznss=yes], [have_moznss=no]) + +- if test "$have_moznss" = yes ; then ++ if test $have_moznss = yes ; then + ol_with_tls=moznss + ol_link_tls=yes +- AC_DEFINE(HAVE_MOZNSS, 1, +- [define if you have MozNSS]) +- TLS_LIBS="-lssl3 -lsmime3 -lnss3 -lnssutil3 -lplds4 -lplc4 -lnspr4" +- else +- if test $ol_with_tls = moznss ; then +- AC_MSG_ERROR([MozNSS not found - please specify the location to the NSPR and NSS header files in CPPFLAGS and the location to the NSPR and NSS libraries in LDFLAGS (if not in the system location)]) +- fi ++ AC_DEFINE(HAVE_MOZNSS, 1, [define if you have MozNSS]) ++ TLS_LIBS="$MOZNSS_LIBS" ++ CFLAGS="$CFLAGS $MOZNSS_CFLAGS" + fi + fi + fi +-- +1.7.11.7 + diff --git a/openldap-nss-allow-certname-with-token-name.patch b/openldap-nss-allow-certname-with-token-name.patch new file mode 100644 index 0000000..a75e84f --- /dev/null +++ b/openldap-nss-allow-certname-with-token-name.patch @@ -0,0 +1,47 @@ +Accept nss certificate name in the form of tokenname:certnickname + +Author: Rich Megginson +Upstream ITS: #7360 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 5022efb..7377bb1 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -2102,6 +2102,22 @@ tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) + return 0; + } + ++/* returns true if the given string looks like ++ "tokenname" ":" "certnickname" ++ This is true if there is a ':' colon character ++ in the string and the colon is not the first ++ or the last character in the string ++*/ ++static int ++tlsm_is_tokenname_certnick( const char *certfile ) ++{ ++ if ( certfile ) { ++ const char *ptr = PL_strchr( certfile, ':' ); ++ return ptr && (ptr != certfile) && (*(ptr+1)); ++ } ++ return 0; ++} ++ + static int + tlsm_deferred_ctx_init( void *arg ) + { +@@ -2268,7 +2284,10 @@ tlsm_deferred_ctx_init( void *arg ) + } else { + char *tmp_certname; + +- if (ctx->tc_certdb_slot) { ++ if (tlsm_is_tokenname_certnick(lt->lt_certfile)) { ++ /* assume already in form tokenname:certnickname */ ++ tmp_certname = PL_strdup(lt->lt_certfile); ++ } else if (ctx->tc_certdb_slot) { + tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile); + } else { + tmp_certname = PR_smprintf("%s", lt->lt_certfile); +-- +1.7.11.4 + diff --git a/openldap-nss-certs-from-certdb-fallback-pem.patch b/openldap-nss-certs-from-certdb-fallback-pem.patch new file mode 100644 index 0000000..d20e48a --- /dev/null +++ b/openldap-nss-certs-from-certdb-fallback-pem.patch @@ -0,0 +1,86 @@ +MozNSS: load certificates from certdb, fallback to PEM + +If TLS_CACERT pointed to a PEM file and TLS_CACERTDIR was set to NSS +certificate database, the backend assumed that the certificate is always +located in the certificate database. This assumption might be wrong. + +This patch makes the library to try to load the certificate from NSS +database and fallback to PEM file if unsuccessfull. + +Author: Jan Vcelak +Upstream ITS: #7389 +Resolves: #857455 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 6847bea..8339391 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -1412,7 +1412,7 @@ tlsm_ctx_load_private_key( tlsm_ctx *ctx ) + /* prefer unlocked key, then key from opened certdb, then any other */ + if ( unlocked_key ) + ctx->tc_private_key = unlocked_key; +- else if ( ctx->tc_certdb_slot ) ++ else if ( ctx->tc_certdb_slot && !ctx->tc_using_pem ) + ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg ); + else + ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg ); +@@ -1909,8 +1909,6 @@ tlsm_deferred_init( void *arg ) + } + return -1; + } +- +- ctx->tc_using_pem = PR_TRUE; + } + + NSS_SetDomesticPolicy(); +@@ -2363,15 +2361,9 @@ tlsm_deferred_ctx_init( void *arg ) + + /* set up our cert and key, if any */ + if ( lt->lt_certfile ) { +- /* if using the PEM module, load the PEM file specified by lt_certfile */ +- /* otherwise, assume this is the name of a cert already in the db */ +- if ( ctx->tc_using_pem ) { +- /* this sets ctx->tc_certificate to the correct value */ +- int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ); +- if ( rc ) { +- return rc; +- } +- } else { ++ ++ /* first search in certdb (lt_certfile is nickname) */ ++ if ( ctx->tc_certdb ) { + char *tmp_certname; + + if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) { +@@ -2391,8 +2383,31 @@ tlsm_deferred_ctx_init( void *arg ) + Debug( LDAP_DEBUG_ANY, + "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n", + lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ } ++ } ++ ++ /* fallback to PEM module (lt_certfile is filename) */ ++ if ( !ctx->tc_certificate ) { ++ if ( !pem_module && tlsm_init_pem_module() ) { ++ int pem_errcode = PORT_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: fallback to PEM impossible, module cannot be loaded - error %d:%s.\n", ++ pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); + return -1; + } ++ ++ /* this sets ctx->tc_certificate to the correct value */ ++ if ( !tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ) ) { ++ ctx->tc_using_pem = PR_TRUE; ++ } ++ } ++ ++ if ( ctx->tc_certificate ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: certificate '%s' successfully loaded from %s.\n", lt->lt_certfile, ++ ctx->tc_using_pem ? "PEM file" : "moznss database", 0); ++ } else { ++ return -1; + } + } + diff --git a/openldap-nss-default-cipher-suite-always-selected.patch b/openldap-nss-default-cipher-suite-always-selected.patch new file mode 100644 index 0000000..10c3523 --- /dev/null +++ b/openldap-nss-default-cipher-suite-always-selected.patch @@ -0,0 +1,34 @@ +MozNSS: default cipher suite always selected + +Author: Tim Strobell +Upstream ITS: #7285 +Upstream commit: 2c2bb2e7aee1b2167f383a8344985a1cf66aff3f +Resolves: #828790 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 23d843c..b608551 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -2218,12 +2218,13 @@ tlsm_deferred_ctx_init( void *arg ) + return -1; + } + +- if ( lt->lt_ciphersuite && +- tlsm_parse_ciphers( ctx, lt->lt_ciphersuite )) { +- Debug( LDAP_DEBUG_ANY, +- "TLS: could not set cipher list %s.\n", +- lt->lt_ciphersuite, 0, 0 ); +- return -1; ++ if ( lt->lt_ciphersuite ) { ++ if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not set cipher list %s.\n", ++ lt->lt_ciphersuite, 0, 0 ); ++ return -1; ++ } + } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not set cipher list DEFAULT.\n", +-- +1.7.10.4 + diff --git a/openldap-nss-ignore-certdb-type-prefix.patch b/openldap-nss-ignore-certdb-type-prefix.patch new file mode 100644 index 0000000..2fab916 --- /dev/null +++ b/openldap-nss-ignore-certdb-type-prefix.patch @@ -0,0 +1,47 @@ +MozNSS: ignore certdb database type prefix when checking existence of the directory + +If the certdb is specified including the database type prefix (e.g. +sql:, dbm:), the prefix has to be ignored when checking the +certificate directory existence. + +Author: Jan Vcelak +Upstream ITS: #7388 +Resolves: #857373 + +--- + libraries/libldap/tls_m.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 49a3f8f..5ee21a2 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -1633,6 +1633,7 @@ tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) + { + char sep = PR_GetDirectorySeparator(); + char *ptr = NULL; ++ char *chkpath = NULL; + struct PRFileInfo prfi; + PRStatus prc; + +@@ -1643,8 +1644,16 @@ tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) + return; + } + +- prc = PR_GetFileInfo( certdir, &prfi ); ++ /* ignore database type prefix (e.g. sql:, dbm:) if provided */ ++ chkpath = strchr( certdir, ':' ); ++ if ( chkpath != NULL ) { ++ chkpath += 1; ++ } else { ++ chkpath = certdir; ++ } ++ + /* if certdir exists (file or directory) then it cannot specify a prefix */ ++ prc = PR_GetFileInfo( chkpath, &prfi ); + if ( prc == PR_SUCCESS ) { + return; + } +-- +1.7.11.7 + diff --git a/openldap-nss-multiple-tls-contexts.patch b/openldap-nss-multiple-tls-contexts.patch new file mode 100644 index 0000000..bf008f4 --- /dev/null +++ b/openldap-nss-multiple-tls-contexts.patch @@ -0,0 +1,1029 @@ +MozNSS: TLS fixes which should resolve problems with applications using multiple TLS contexts + + - context specific token description for certdb + - store certificate object instead of nickname in in ctx + - lock whole init and clenaup process + - do not authenticate to a slot manually + - do not retry when reading the pin from file + +Author: Jan Vcelak +Upstream ITS: #7312 #7313 #7314 #7315 #7316 +Upstream commit: 87132b8 d07779e 3531c34 a171237 2db5195 +Resolves: #795763 (and possibly other) + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 2e755eb..4b5727b 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -81,16 +81,18 @@ + typedef struct tlsm_ctx { + PRFileDesc *tc_model; + int tc_refcnt; ++ int tc_unique; /* unique number associated with this ctx */ + PRBool tc_verify_cert; + CERTCertDBHandle *tc_certdb; +- char *tc_certname; ++ PK11SlotInfo *tc_certdb_slot; ++ CERTCertificate *tc_certificate; ++ SECKEYPrivateKey *tc_private_key; + char *tc_pin_file; + struct ldaptls *tc_config; + int tc_is_server; + int tc_require_cert; + PRCallOnceType tc_callonce; + PRBool tc_using_pem; +- char *tc_slotname; /* if using pem */ + #ifdef HAVE_NSS_INITCONTEXT + NSSInitContext *tc_initctx; /* the NSS context */ + #endif +@@ -104,10 +106,16 @@ typedef struct tlsm_ctx { + + typedef PRFileDesc tlsm_session; + ++static int tlsm_ctx_count; ++#define TLSM_CERTDB_DESC_FMT "ldap(%d)" ++ + static PRDescIdentity tlsm_layer_id; + + static const PRIOMethods tlsm_PR_methods; + ++#define CERTDB_NONE NULL ++#define PREFIX_NONE NULL ++ + #define PEM_LIBRARY "nsspem" + #define PEM_MODULE "PEM" + /* hash files for use with cacertdir have this file name suffix */ +@@ -117,13 +125,11 @@ static const PRIOMethods tlsm_PR_methods; + static SECMODModule *pem_module; + + #define DEFAULT_TOKEN_NAME "default" +-/* sprintf format used to create token name */ +-#define TLSM_PEM_TOKEN_FMT "PEM Token #%ld" ++#define TLSM_PEM_SLOT_CACERTS "PEM Token #0" ++#define TLSM_PEM_SLOT_CERTS "PEM Token #1" + +-static int tlsm_slot_count; +- +-#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ +- (x)->pValue=(v); (x)->ulValueLen = (l); ++#define PK11_SETATTRS(x,id,v,l) (x).type = (id); \ ++ (x).pValue=(v); (x).ulValueLen = (l); + + /* forward declaration */ + static int tlsm_init( void ); +@@ -134,6 +140,7 @@ static int tlsm_init( void ); + tlsm_thr_init in a non-threaded context - so we have + to wrap the mutex creation in a prcallonce + */ ++static ldap_pvt_thread_mutex_t tlsm_ctx_count_mutex; + static ldap_pvt_thread_mutex_t tlsm_init_mutex; + static ldap_pvt_thread_mutex_t tlsm_pem_mutex; + static PRCallOnceType tlsm_init_mutex_callonce = {0,0}; +@@ -141,6 +148,12 @@ static PRCallOnceType tlsm_init_mutex_callonce = {0,0}; + static PRStatus PR_CALLBACK + tlsm_thr_init_callonce( void ) + { ++ if ( ldap_pvt_thread_mutex_init( &tlsm_ctx_count_mutex ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not create mutex for context counter: %d\n", errno, 0, 0 ); ++ return PR_FAILURE; ++ } ++ + if ( ldap_pvt_thread_mutex_init( &tlsm_init_mutex ) ) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not create mutex for moznss initialization: %d\n", errno, 0, 0 ); +@@ -890,6 +903,8 @@ tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) + */ + if ( ctx->tc_pin_file ) { + pwdstr = tlsm_get_pin_from_file( token_name, ctx ); ++ if (retry && pwdstr != NULL) ++ return NULL; + } + #endif /* RETRIEVE_PASSWORD_FROM_FILE */ + #ifdef READ_PASSWORD_FROM_STDIN +@@ -932,6 +947,15 @@ tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg) + return tlsm_get_pin( slot, retry, ctx ); + } + ++static char * ++tlsm_ctx_subject_name(tlsm_ctx *ctx) ++{ ++ if (!ctx || !ctx->tc_certificate) ++ return "(unknown)"; ++ ++ return ctx->tc_certificate->subjectName; ++} ++ + static SECStatus + tlsm_get_basic_constraint_extension( CERTCertificate *cert, + CERTBasicConstraints *cbcval ) +@@ -1088,25 +1112,6 @@ tlsm_auth_cert_handler(void *arg, PRFileDesc *fd, + return ret; + } + +-static int +-tlsm_authenticate_to_slot( tlsm_ctx *ctx, PK11SlotInfo *slot ) +-{ +- int rc = -1; +- +- if ( SECSuccess != PK11_Authenticate( slot, PR_FALSE, ctx ) ) { +- char *token_name = PK11_GetTokenName( slot ); +- PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: could not authenticate to the security token %s - error %d:%s.\n", +- token_name ? token_name : DEFAULT_TOKEN_NAME, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); +- } else { +- rc = 0; /* success */ +- } +- +- return rc; +-} +- + static SECStatus + tlsm_nss_shutdown_cb( void *appData, void *nssData ) + { +@@ -1196,22 +1201,18 @@ tlsm_free_pem_objs( tlsm_ctx *ctx ) + } + + static int +-tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca, PRBool istrusted ) ++tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca ) + { +- CK_SLOT_ID slotID; +- PK11SlotInfo *slot = NULL; +- PK11GenericObject *rv; +- CK_ATTRIBUTE *attrs; +- CK_ATTRIBUTE theTemplate[20]; ++ PK11SlotInfo *slot; ++ PK11GenericObject *cert; ++ CK_ATTRIBUTE attrs[4]; + CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; + CK_OBJECT_CLASS objClass = CKO_CERTIFICATE; +- char tmpslotname[64]; +- char *slotname = NULL; +- const char *ptr = NULL; +- char sep = PR_GetDirectorySeparator(); ++ char *slotname; + PRFileInfo fi; + PRStatus status; ++ SECItem certDER = { 0, NULL, 0 }; + + memset( &fi, 0, sizeof(fi) ); + status = PR_GetFileInfo( filename, &fi ); +@@ -1232,87 +1233,96 @@ tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca, PRBoo + return -1; + } + +- attrs = theTemplate; ++ slotname = isca ? TLSM_PEM_SLOT_CACERTS : TLSM_PEM_SLOT_CERTS; ++ slot = PK11_FindSlotByName( slotname ); + +- if ( isca ) { +- slotID = 0; /* CA and trust objects use slot 0 */ +- PR_snprintf( tmpslotname, sizeof(tmpslotname), TLSM_PEM_TOKEN_FMT, slotID ); +- slotname = tmpslotname; +- istrusted = PR_TRUE; +- } else { +- if ( ctx->tc_slotname == NULL ) { /* need new slot */ +- if ( istrusted ) { +- slotID = 0; +- } else { +- slotID = ++tlsm_slot_count; +- } +- ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID ); +- } +- slotname = ctx->tc_slotname; +- +- if ( ( ptr = PL_strrchr( filename, sep ) ) ) { +- PL_strfree( ctx->tc_certname ); +- ++ptr; +- if ( istrusted ) { +- /* pemnss conflates trusted certs with CA certs - since there can +- be more than one CA cert in a file (e.g. ca-bundle.crt) pemnss +- numbers each trusted cert - in the case of a server cert, there will be +- only one, so it will be number 0 */ +- ctx->tc_certname = PR_smprintf( "%s:%s - 0", slotname, ptr ); +- } else { +- ctx->tc_certname = PR_smprintf( "%s:%s", slotname, ptr ); +- } +- } ++ if ( !slot ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not find the slot for the certificate '%s' - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ return -1; + } + +- slot = PK11_FindSlotByName( slotname ); ++ PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) ); ++ PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); ++ PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); ++ PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); + +- if ( !slot ) { ++ cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ ); ++ ++ if ( !cert ) { + PRErrorCode errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, +- "TLS: could not find the slot for certificate %s - error %d:%s.\n", +- ctx->tc_certname, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ "TLS: could not add the certificate '%s' - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ PK11_FreeSlot( slot ); + return -1; + } + +- PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; +- PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; +- PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++; +- if ( istrusted ) { +- PK11_SETATTRS( attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); attrs++; +- } else { +- PK11_SETATTRS( attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); attrs++; ++ /* if not CA, we store the certificate in ctx->tc_certificate */ ++ if ( !isca ) { ++ if ( PK11_ReadRawAttribute( PK11_TypeGeneric, cert, CKA_VALUE, &certDER ) != SECSuccess ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not get DER of the '%s' certificate - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ PK11_DestroyGenericObject( cert ); ++ PK11_FreeSlot( slot ); ++ return -1; ++ } ++ ++ ctx->tc_certificate = PK11_FindCertFromDERCertItem( slot, &certDER, NULL ); ++ SECITEM_FreeItem( &certDER, PR_FALSE ); ++ ++ if ( !ctx->tc_certificate ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not get certificate '%s' using DER - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ PK11_DestroyGenericObject( cert ); ++ PK11_FreeSlot( slot ); ++ return -1; ++ } + } +- /* This loads the certificate in our PEM module into the appropriate +- * slot. +- */ +- rv = PK11_CreateGenericObject( slot, theTemplate, 4, PR_FALSE /* isPerm */ ); ++ ++ tlsm_add_pem_obj( ctx, cert ); + + PK11_FreeSlot( slot ); + +- if ( !rv ) { ++ return 0; ++} ++ ++static int ++tlsm_ctx_load_private_key(tlsm_ctx *ctx) ++{ ++ if (!ctx->tc_certificate) ++ return -1; ++ ++ if (ctx->tc_private_key) ++ return 0; ++ ++ void *pin_arg = SSL_RevealPinArg(ctx->tc_model); ++ ++ ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg); ++ if (!ctx->tc_private_key) { + PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: could not add the certificate %s - error %d:%s.\n", +- ctx->tc_certname, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ Debug(LDAP_DEBUG_ANY, ++ "TLS: cannot find private key for certificate '%s' (error %d: %s)", ++ tlsm_ctx_subject_name(ctx), errcode, ++ PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT)); + return -1; + } + +- tlsm_add_pem_obj( ctx, rv ); +- + return 0; + } + + static int + tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename ) + { +- CK_SLOT_ID slotID; + PK11SlotInfo * slot = NULL; +- PK11GenericObject *rv; +- CK_ATTRIBUTE *attrs; +- CK_ATTRIBUTE theTemplate[20]; ++ PK11GenericObject *key; ++ CK_ATTRIBUTE attrs[3]; + CK_BBOOL cktrue = CK_TRUE; + CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; + int retcode = 0; +@@ -1338,48 +1348,40 @@ tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename ) + return -1; + } + +- attrs = theTemplate; +- +- if ( ctx->tc_slotname == NULL ) { /* need new slot */ +- slotID = ++tlsm_slot_count; +- ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID ); +- } +- slot = PK11_FindSlotByName( ctx->tc_slotname ); ++ slot = PK11_FindSlotByName( TLSM_PEM_SLOT_CERTS ); + + if ( !slot ) { + PRErrorCode errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, +- "TLS: could not find the slot %s for the private key - error %d:%s.\n", +- ctx->tc_slotname, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ "TLS: could not find the slot for the private key '%s' - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); + return -1; + } + +- PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; +- PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; +- PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++; +- rv = PK11_CreateGenericObject( slot, theTemplate, 3, PR_FALSE /* isPerm */ ); ++ PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) ); ++ PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); ++ PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); ++ ++ key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ ); + +- if ( !rv ) { ++ if ( !key ) { + PRErrorCode errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, +- "TLS: could not add the certificate %s - error %d:%s.\n", +- ctx->tc_certname, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ "TLS: could not add the private key '%s' - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); + retcode = -1; + } else { ++ tlsm_add_pem_obj( ctx, key ); ++ retcode = 0; ++ + /* When adding an encrypted key the PKCS#11 will be set as removed */ + /* This will force the token to be seen as re-inserted */ + SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 ); + PK11_IsPresent( slot ); +- retcode = 0; + } + + PK11_FreeSlot( slot ); + +- if ( !retcode ) { +- tlsm_add_pem_obj( ctx, rv ); +- } + return retcode; + } + +@@ -1396,7 +1398,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir + } + + if ( cacertfile ) { +- int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca, PR_TRUE ); ++ int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca ); + if ( rc ) { + errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, +@@ -1470,7 +1472,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir + continue; + } + fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name ); +- if ( !tlsm_add_cert_from_file( ctx, fullpath, isca, PR_TRUE ) ) { ++ if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) { + Debug( LDAP_DEBUG_TRACE, + "TLS: loaded CA certificate file %s from CA certificate directory %s.\n", + fullpath, cacertdir, 0 ); +@@ -1534,6 +1536,45 @@ tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) + } + + /* ++ * Currently mutiple MozNSS contexts share one certificate storage. When the ++ * certdb is being opened, only new certificates are added to the storage. ++ * When different databases are used, conflicting nicknames make the ++ * certificate lookup by the nickname impossible. In addition a token ++ * description might be prepended in certain conditions. ++ * ++ * In order to make the certificate lookup by nickname possible, we explicitly ++ * open each database using SECMOD_OpenUserDB and assign it the token ++ * description. The token description is generated using ctx->tc_unique value, ++ * which is unique for each context. ++ */ ++static PK11SlotInfo * ++tlsm_init_open_certdb(tlsm_ctx *ctx, const char *dbdir, const char *prefix) ++{ ++ PK11SlotInfo *slot = NULL; ++ char *token_desc = NULL; ++ char *config = NULL; ++ ++ token_desc = PR_smprintf(TLSM_CERTDB_DESC_FMT, ctx->tc_unique); ++ config = PR_smprintf("configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly", ++ dbdir, token_desc, prefix, prefix); ++ Debug(LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0); ++ ++ slot = SECMOD_OpenUserDB(config); ++ if (!slot) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug(LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode, ++ PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT)); ++ } ++ ++ if (token_desc) ++ PR_smprintf_free(token_desc); ++ if (config) ++ PR_smprintf_free(config); ++ ++ return slot; ++} ++ ++/* + * This is the part of the init we defer until we get the + * actual security configuration information. This is + * only called once, protected by a PRCallOnce +@@ -1553,6 +1594,7 @@ tlsm_deferred_init( void *arg ) + #ifdef HAVE_NSS_INITCONTEXT + NSSInitParameters initParams; + NSSInitContext *initctx = NULL; ++ PK11SlotInfo *certdb_slot = NULL; + #endif + SECStatus rc; + int done = 0; +@@ -1613,28 +1655,37 @@ tlsm_deferred_init( void *arg ) + } + + tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix ); +- LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + ++ /* initialize only moddb; certdb will be initialized explicitly */ + #ifdef HAVE_NSS_INITCONTEXT + #ifdef INITCONTEXT_HACK + if ( !NSS_IsInitialized() && ctx->tc_is_server ) { + rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY ); + } else { + initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB, +- &initParams, NSS_INIT_READONLY ); +- rc = (initctx == NULL) ? SECFailure : SECSuccess; ++ &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB ); + } + #else + initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB, +- &initParams, NSS_INIT_READONLY ); +- rc = (initctx == NULL) ? SECFailure : SECSuccess; ++ &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB ); + #endif ++ rc = SECFailure; ++ ++ if (initctx != NULL) { ++ certdb_slot = tlsm_init_open_certdb(ctx, realcertdir, prefix); ++ if (certdb_slot) { ++ rc = SECSuccess; ++ ctx->tc_initctx = initctx; ++ ctx->tc_certdb_slot = certdb_slot; ++ } else { ++ NSS_ShutdownContext(initctx); ++ initctx = NULL; ++ } ++ } + #else + rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY ); + #endif + +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); +- + if ( rc != SECSuccess ) { + errcode = PORT_GetError(); + if ( securitydirs[ii] != lt->lt_cacertdir) { +@@ -1658,26 +1709,29 @@ tlsm_deferred_init( void *arg ) + } + + if ( errcode ) { /* no moznss db found, or not using moznss db */ +- LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + #ifdef HAVE_NSS_INITCONTEXT + int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB; + #ifdef INITCONTEXT_HACK + if ( !NSS_IsInitialized() && ctx->tc_is_server ) { + rc = NSS_NoDB_Init( NULL ); + } else { +- initctx = NSS_InitContext( "", "", "", SECMOD_DB, ++ initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB, + &initParams, flags ); + rc = (initctx == NULL) ? SECFailure : SECSuccess; + } + #else +- initctx = NSS_InitContext( "", "", "", SECMOD_DB, ++ initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB, + &initParams, flags ); +- rc = (initctx == NULL) ? SECFailure : SECSuccess; ++ if (initctx) { ++ ctx->tc_initctx = initctx; ++ rc = SECSuccess; ++ } else { ++ rc = SECFailure; ++ } + #endif + #else + rc = NSS_NoDB_Init( NULL ); + #endif +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + if ( rc != SECSuccess ) { + errcode = PORT_GetError(); + Debug( LDAP_DEBUG_ANY, +@@ -1685,18 +1739,11 @@ tlsm_deferred_init( void *arg ) + errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); + return -1; + } +- +-#ifdef HAVE_NSS_INITCONTEXT +- ctx->tc_initctx = initctx; +-#endif +- + } + + if ( errcode || lt->lt_cacertfile ) { + /* initialize the PEM module */ +- LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + if ( tlsm_init_pem_module() ) { +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + int pem_errcode = PORT_GetError(); + Debug( LDAP_DEBUG_ANY, + "TLS: could not initialize moznss PEM module - error %d:%s.\n", +@@ -1708,7 +1755,6 @@ tlsm_deferred_init( void *arg ) + } else if ( !errcode ) { + tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL ); + } +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + } + + if ( errcode ) { +@@ -1734,12 +1780,6 @@ tlsm_deferred_init( void *arg ) + ctx->tc_using_pem = PR_TRUE; + } + +-#ifdef HAVE_NSS_INITCONTEXT +- if ( !ctx->tc_initctx ) { +- ctx->tc_initctx = initctx; +- } +-#endif +- + NSS_SetDomesticPolicy(); + + PK11_SetPasswordFunc( tlsm_pin_prompt ); +@@ -1754,10 +1794,8 @@ tlsm_deferred_init( void *arg ) + } + + if ( ctx->tc_is_server ) { +- LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + /* 0 means use the defaults here */ + SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL ); +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + } + + #ifndef HAVE_NSS_INITCONTEXT +@@ -1767,137 +1805,34 @@ tlsm_deferred_init( void *arg ) + return 0; + } + +-static int +-tlsm_authenticate( tlsm_ctx *ctx, const char *certname, const char *pininfo ) +-{ +- const char *colon = NULL; +- char *token_name = NULL; +- PK11SlotInfo *slot = NULL; +- int rc = -1; +- +- if ( !certname || !*certname ) { +- return 0; +- } +- +- if ( ( colon = PL_strchr( certname, ':' ) ) ) { +- token_name = PL_strndup( certname, colon-certname ); +- } +- +- if ( token_name ) { +- slot = PK11_FindSlotByName( token_name ); +- } else { +- slot = PK11_GetInternalKeySlot(); +- } +- +- if ( !slot ) { +- PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: could not find the slot for security token %s - error %d:%s.\n", +- token_name ? token_name : DEFAULT_TOKEN_NAME, errcode, +- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); +- goto done; +- } +- +- rc = tlsm_authenticate_to_slot( ctx, slot ); +- +-done: +- PL_strfree( token_name ); +- if ( slot ) { +- PK11_FreeSlot( slot ); +- } +- +- return rc; +-} +- + /* + * Find and verify the certificate. +- * Either fd is given, in which case the cert will be taken from it via SSL_PeerCertificate +- * or certname is given, and it will be searched for by name ++ * The key is loaded and stored in ctx->tc_private_key + */ + static int +-tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certname, int isServer, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey) ++tlsm_find_and_verify_cert_key(tlsm_ctx *ctx) + { +- CERTCertificate *cert = NULL; +- int rc = -1; +- void *pin_arg = NULL; +- SECKEYPrivateKey *key = NULL; ++ SECCertificateUsage certUsage; ++ PRBool checkSig; ++ SECStatus status; ++ int errorToIgnore; ++ void *pin_arg; + +- pin_arg = SSL_RevealPinArg( fd ); +- if ( certname ) { +- cert = PK11_FindCertFromNickname( certname, pin_arg ); +- if ( !cert ) { +- PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: the certificate %s could not be found in the database - error %d:%s\n", +- certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); +- return -1; +- } +- } else { +- /* we are verifying the peer cert +- we also need to swap the isServer meaning */ +- cert = SSL_PeerCertificate( fd ); +- if ( !cert ) { +- PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: could not get the certificate from the peer connection - error %d:%s\n", +- errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), NULL ); +- return -1; +- } +- isServer = !isServer; /* verify the peer's cert instead */ +- } +- +- if ( ctx->tc_slotname ) { +- PK11SlotInfo *slot = PK11_FindSlotByName( ctx->tc_slotname ); +- key = PK11_FindPrivateKeyFromCert( slot, cert, NULL ); +- PK11_FreeSlot( slot ); +- } else { +- key = PK11_FindKeyByAnyCert( cert, pin_arg ); +- } +- +- if (key) { +- SECCertificateUsage certUsage; +- PRBool checkSig = PR_TRUE; +- SECStatus status; +- /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */ +- int errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER; ++ if (tlsm_ctx_load_private_key(ctx)) ++ return -1; + +- if ( pRetKey ) { +- *pRetKey = key; /* caller will deal with this */ +- } else { +- SECKEY_DestroyPrivateKey( key ); +- } +- if ( isServer ) { +- certUsage = certificateUsageSSLServer; +- } else { +- certUsage = certificateUsageSSLClient; +- } +- if ( ctx->tc_verify_cert ) { +- checkSig = PR_TRUE; +- } else { +- checkSig = PR_FALSE; +- } +- if ( ctx->tc_warn_only ) { +- errorToIgnore = -1; +- } +- status = tlsm_verify_cert( ctx->tc_certdb, cert, pin_arg, +- checkSig, certUsage, errorToIgnore ); +- if ( status == SECSuccess ) { +- rc = 0; +- } +- } else { +- PRErrorCode errcode = PR_GetError(); +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: could not find the private key for certificate %s - error %d:%s\n", +- certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); +- } ++ pin_arg = SSL_RevealPinArg(ctx->tc_model); ++ certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient; ++ checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE; ++ if ( ctx->tc_warn_only ) ++ errorToIgnore = -1; ++ else ++ errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER; /* may not have a CA cert */ + +- if ( pRetCert ) { +- *pRetCert = cert; /* caller will deal with this */ +- } else { +- CERT_DestroyCertificate( cert ); +- } ++ status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg, ++ checkSig, certUsage, errorToIgnore ); + +- return rc; ++ return status == SECSuccess ? 0 : -1; + } + + static int +@@ -1906,39 +1841,18 @@ tlsm_get_client_auth_data( void *arg, PRFileDesc *fd, + SECKEYPrivateKey **pRetKey ) + { + tlsm_ctx *ctx = (tlsm_ctx *)arg; +- int rc; +- PRBool saveval; + +- /* don't need caNames - this function will call CERT_VerifyCertificateNow +- which will verify the cert against the known CAs */ +- saveval = ctx->tc_warn_only; +- ctx->tc_warn_only = PR_TRUE; +- rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey ); +- ctx->tc_warn_only = saveval; +- if ( rc ) { +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: unable to perform client certificate authentication for " +- "certificate named %s\n", ctx->tc_certname, 0, 0 ); +- if ( pRetKey && *pRetKey ) { +- SECKEY_DestroyPrivateKey( *pRetKey ); +- *pRetKey = NULL; +- } +- if ( pRetCert && *pRetCert ) { +- CERT_DestroyCertificate( *pRetCert ); +- *pRetCert = NULL; +- } +- return SECFailure; +- } ++ if (pRetCert) ++ *pRetCert = CERT_DupCertificate(ctx->tc_certificate); ++ ++ if (pRetKey) ++ *pRetKey = SECKEY_CopyPrivateKey(ctx->tc_private_key); + + return SECSuccess; + } + + /* + * ctx must have a tc_model that is valid +- * certname is in the form [:] +- * where is the name of the PKCS11 token +- * and is the nickname of the cert/key in +- * the database + */ + static int + tlsm_clientauth_init( tlsm_ctx *ctx ) +@@ -1949,12 +1863,12 @@ tlsm_clientauth_init( tlsm_ctx *ctx ) + + saveval = ctx->tc_warn_only; + ctx->tc_warn_only = PR_TRUE; +- rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL ); ++ rc = tlsm_find_and_verify_cert_key(ctx); + ctx->tc_warn_only = saveval; + if ( rc ) { + Debug( LDAP_DEBUG_ANY, + "TLS: error: unable to set up client certificate authentication for " +- "certificate named %s\n", ctx->tc_certname, 0, 0 ); ++ "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 ); + return -1; + } + +@@ -1972,6 +1886,7 @@ static void + tlsm_destroy( void ) + { + #ifdef LDAP_R_COMPILE ++ ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex ); + ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex ); + ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex ); + #endif +@@ -2048,16 +1963,20 @@ tlsm_ctx_new ( struct ldapoptions *lo ) + #ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &ctx->tc_refmutex ); + #endif ++ LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex ); ++ ctx->tc_unique = tlsm_ctx_count++; ++ LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex ); + ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */ + ctx->tc_certdb = NULL; +- ctx->tc_certname = NULL; ++ ctx->tc_certdb_slot = NULL; ++ ctx->tc_certificate = NULL; ++ ctx->tc_private_key = NULL; + ctx->tc_pin_file = NULL; + ctx->tc_model = NULL; + memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce)); + ctx->tc_require_cert = lo->ldo_tls_require_cert; + ctx->tc_verify_cert = PR_FALSE; + ctx->tc_using_pem = PR_FALSE; +- ctx->tc_slotname = NULL; + #ifdef HAVE_NSS_INITCONTEXT + ctx->tc_initctx = NULL; + #endif /* HAVE_NSS_INITCONTEXT */ +@@ -2090,28 +2009,38 @@ tlsm_ctx_free ( tls_ctx *ctx ) + LDAP_MUTEX_UNLOCK( &c->tc_refmutex ); + if ( refcount ) + return; ++ ++ LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + if ( c->tc_model ) + PR_Close( c->tc_model ); ++ if (c->tc_certificate) ++ CERT_DestroyCertificate(c->tc_certificate); ++ if (c->tc_private_key) ++ SECKEY_DestroyPrivateKey(c->tc_private_key); + c->tc_certdb = NULL; /* if not the default, may have to clean up */ +- PL_strfree( c->tc_certname ); +- c->tc_certname = NULL; ++ if ( c->tc_certdb_slot ) { ++ if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not close certdb slot - error %d:%s.\n", ++ errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); ++ } ++ } + PL_strfree( c->tc_pin_file ); + c->tc_pin_file = NULL; +- PL_strfree( c->tc_slotname ); + tlsm_free_pem_objs( c ); + #ifdef HAVE_NSS_INITCONTEXT + if ( c->tc_initctx ) { +- LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + if ( NSS_ShutdownContext( c->tc_initctx ) ) { + PRErrorCode errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, + "TLS: could not shutdown NSS - error %d:%s.\n", + errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); + } +- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + } + c->tc_initctx = NULL; + #endif /* HAVE_NSS_INITCONTEXT */ ++ LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + #ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_destroy( &c->tc_refmutex ); + #endif +@@ -2173,6 +2102,12 @@ tlsm_deferred_ctx_init( void *arg ) + return -1; + } + ++ if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: could not set pin prompt argument\n", 0, 0, 0); ++ return -1; ++ } ++ + if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not set secure mode on.\n", +@@ -2287,14 +2222,30 @@ tlsm_deferred_ctx_init( void *arg ) + /* if using the PEM module, load the PEM file specified by lt_certfile */ + /* otherwise, assume this is the name of a cert already in the db */ + if ( ctx->tc_using_pem ) { +- /* this sets ctx->tc_certname to the correct value */ +- int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE, PR_TRUE ); ++ /* this sets ctx->tc_certificate to the correct value */ ++ int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ); + if ( rc ) { + return rc; + } + } else { +- PL_strfree( ctx->tc_certname ); +- ctx->tc_certname = PL_strdup( lt->lt_certfile ); ++ char *tmp_certname; ++ ++ if (ctx->tc_certdb_slot) { ++ tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile); ++ } else { ++ tmp_certname = PR_smprintf("%s", lt->lt_certfile); ++ } ++ ++ ctx->tc_certificate = PK11_FindCertFromNickname(tmp_certname, SSL_RevealPinArg(ctx->tc_model)); ++ PR_smprintf_free(tmp_certname); ++ ++ if (!ctx->tc_certificate) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n", ++ lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ return -1; ++ } + } + } + +@@ -2302,7 +2253,6 @@ tlsm_deferred_ctx_init( void *arg ) + /* if using the PEM module, load the PEM file specified by lt_keyfile */ + /* otherwise, assume this is the pininfo for the key */ + if ( ctx->tc_using_pem ) { +- /* this sets ctx->tc_certname to the correct value */ + int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile ); + if ( rc ) { + return rc; +@@ -2334,66 +2284,42 @@ tlsm_deferred_ctx_init( void *arg ) + /* + since a cert has been specified, assume the client wants to do cert auth + */ +- if ( ctx->tc_certname ) { +- if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) { +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: unable to authenticate to the security device for certificate %s\n", +- ctx->tc_certname, 0, 0 ); +- return -1; +- } ++ if ( ctx->tc_certificate ) { + if ( tlsm_clientauth_init( ctx ) ) { + Debug( LDAP_DEBUG_ANY, +- "TLS: error: unable to set up client certificate authentication using %s\n", +- ctx->tc_certname, 0, 0 ); ++ "TLS: error: unable to set up client certificate authentication using '%s'\n", ++ tlsm_ctx_subject_name(ctx), 0, 0 ); + return -1; + } + } + } else { /* set up secure server */ + SSLKEAType certKEA; +- CERTCertificate *serverCert = NULL; +- SECKEYPrivateKey *serverKey = NULL; + SECStatus status; + + /* must have a certificate for the server to use */ +- if ( !ctx->tc_certname ) { ++ if ( !ctx->tc_certificate ) { + Debug( LDAP_DEBUG_ANY, + "TLS: error: no server certificate: must specify a certificate for the server to use\n", + 0, 0, 0 ); + return -1; + } + +- /* authenticate to the server's token - this will do nothing +- if the key/cert db is not password protected */ +- if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) { +- Debug( LDAP_DEBUG_ANY, +- "TLS: error: unable to authenticate to the security device for certificate %s\n", +- ctx->tc_certname, 0, 0 ); +- return -1; +- } +- +- /* get the server's key and cert */ +- if ( tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, ctx->tc_is_server, +- &serverCert, &serverKey ) ) { ++ if (tlsm_find_and_verify_cert_key(ctx)) { + Debug( LDAP_DEBUG_ANY, + "TLS: error: unable to find and verify server's cert and key for certificate %s\n", +- ctx->tc_certname, 0, 0 ); +- CERT_DestroyCertificate( serverCert ); +- SECKEY_DestroyPrivateKey( serverKey ); ++ tlsm_ctx_subject_name(ctx), 0, 0 ); + return -1; + } + +- certKEA = NSS_FindCertKEAType( serverCert ); + /* configure the socket to be a secure server socket */ +- status = SSL_ConfigSecureServer( ctx->tc_model, serverCert, serverKey, certKEA ); +- /* SSL_ConfigSecureServer copies these */ +- CERT_DestroyCertificate( serverCert ); +- SECKEY_DestroyPrivateKey( serverKey ); ++ certKEA = NSS_FindCertKEAType( ctx->tc_certificate ); ++ status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA ); + + if ( SECSuccess != status ) { + PRErrorCode err = PR_GetError(); + Debug( LDAP_DEBUG_ANY, +- "TLS: error: unable to configure secure server using certificate %s - error %d:%s\n", +- ctx->tc_certname, err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) ); ++ "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n", ++ tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) ); + return -1; + } + } +@@ -2515,7 +2441,9 @@ tlsm_session_new ( tls_ctx * ctx, int is_server ) + int rc; + + c->tc_is_server = is_server; ++ LDAP_MUTEX_LOCK( &tlsm_init_mutex ); + status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c ); ++ LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); + if ( PR_SUCCESS != status ) { + PRErrorCode err = PR_GetError(); + Debug( LDAP_DEBUG_ANY, diff --git a/openldap-nss-pk11-freeslot.patch b/openldap-nss-pk11-freeslot.patch new file mode 100644 index 0000000..ca657c8 --- /dev/null +++ b/openldap-nss-pk11-freeslot.patch @@ -0,0 +1,23 @@ +Resolves: #929357 + +Upstream commit: 6330d1b87a45b447f33fe8ffd6fbbce9e60bb0ec +Author: Rich Megginson +Date: Thu, 28 Mar 2013 19:05:02 -0600 +Modified by: Jan Synacek + +This patch has been re-diffed so it clearly applies to OpenLDAP 2.4.39. + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 072d41d..c59d303 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -2151,6 +2151,8 @@ + "TLS: could not close certdb slot - error %d:%s.\n", + errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); + } ++ PK11_FreeSlot( c->tc_certdb_slot ); ++ c->tc_certdb_slot = NULL; + } + if ( c->tc_pin_file ) { + PL_strfree( c->tc_pin_file ); + diff --git a/openldap-nss-regex-search-hashed-cacert-dir.patch b/openldap-nss-regex-search-hashed-cacert-dir.patch new file mode 100644 index 0000000..03493db --- /dev/null +++ b/openldap-nss-regex-search-hashed-cacert-dir.patch @@ -0,0 +1,91 @@ +MozNSS: better file name matching for hashed CA certificate directory + +CA certificate files in OpenSSL compatible CACERTDIR were loaded if the file extension was '.0'. However the file name +should be 8 letters long certificate hash of the certificate subject name, followed by a numeric suffix which is used +to differentiate between two certificates with the same subject name. + +Wit this patch, certificate file names are matched correctly (using regular expressions). + +Author: Jan Vcelak +Upstream ITS: #7374 +Resolves: #852786 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 5e49fc5..61d71d4 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include "ldap-int.h" + #include "ldap-tls.h" +@@ -118,9 +119,7 @@ static const PRIOMethods tlsm_PR_methods; + + #define PEM_LIBRARY "nsspem" + #define PEM_MODULE "PEM" +-/* hash files for use with cacertdir have this file name suffix */ +-#define PEM_CA_HASH_FILE_SUFFIX ".0" +-#define PEM_CA_HASH_FILE_SUFFIX_LEN 2 ++#define PEM_CA_HASH_FILE_REGEX "^[0-9a-f]{8}\\.[0-9]+$" + + static SECMODModule *pem_module; + +@@ -1541,6 +1540,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir + PRDir *dir; + PRDirEntry *entry; + PRStatus fistatus = PR_FAILURE; ++ regex_t hashfile_re; + + memset( &fi, 0, sizeof(fi) ); + fistatus = PR_GetFileInfo( cacertdir, &fi ); +@@ -1570,20 +1570,30 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir + goto done; + } + ++ if ( regcomp( &hashfile_re, PEM_CA_HASH_FILE_REGEX, REG_NOSUB|REG_EXTENDED ) != 0 ) { ++ Debug( LDAP_DEBUG_ANY, "TLS: cannot compile regex for CA hash files matching\n", 0, 0, 0 ); ++ goto done; ++ } ++ + do { + entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN ); + if ( ( NULL != entry ) && ( NULL != entry->name ) ) { + char *fullpath = NULL; +- char *ptr; ++ int match; + +- ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX ); +- if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) { ++ match = regexec( &hashfile_re, entry->name, 0, NULL, 0 ); ++ if ( match == REG_NOMATCH ) { + Debug( LDAP_DEBUG_TRACE, +- "TLS: file %s does not end in [%s] - does not appear to be a CA certificate " +- "directory file with a properly hashed file name - skipping.\n", +- entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 ); ++ "TLS: skipping '%s' - filename does not have expected format " ++ "(certificate hash with numeric suffix)\n", entry->name, 0, 0 ); ++ continue; ++ } else if ( match != 0 ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLS: cannot execute regex for CA hash file matching (%d).\n", ++ match, 0, 0 ); + continue; + } ++ + fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name ); + if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) { + Debug( LDAP_DEBUG_TRACE, +@@ -1599,6 +1609,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir + PR_smprintf_free( fullpath ); + } + } while ( NULL != entry ); ++ regfree ( &hashfile_re ); + PR_CloseDir( dir ); + } + done: +-- +1.7.11.4 + diff --git a/openldap-nss-update-list-of-ciphers.patch b/openldap-nss-update-list-of-ciphers.patch new file mode 100644 index 0000000..d5986c0 --- /dev/null +++ b/openldap-nss-update-list-of-ciphers.patch @@ -0,0 +1,193 @@ +MozNSS: update list of supported cipher suites + +The updated list includes all ciphers implemented in Mozilla NSS 3.13.15 + +Author: Jan Vcelak +Upstream ITS: #7374 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 1422ce2..5e49fc5 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -211,27 +211,34 @@ typedef struct { + int num; /* The cipher id */ + int attr; /* cipher attributes: algorithms, etc */ + int version; /* protocol version valid for this cipher */ +- int bits; /* bits of strength */ +- int alg_bits; /* bits of the algorithm */ + int strength; /* LOW, MEDIUM, HIGH */ + int enabled; /* Enabled by default? */ + } cipher_properties; + + /* cipher attributes */ +-#define SSL_kRSA 0x00000001L +-#define SSL_aRSA 0x00000002L +-#define SSL_aDSS 0x00000004L +-#define SSL_DSS SSL_aDSS +-#define SSL_eNULL 0x00000008L +-#define SSL_DES 0x00000010L +-#define SSL_3DES 0x00000020L +-#define SSL_RC4 0x00000040L +-#define SSL_RC2 0x00000080L +-#define SSL_AES 0x00000100L +-#define SSL_MD5 0x00000200L +-#define SSL_SHA1 0x00000400L +-#define SSL_SHA SSL_SHA1 +-#define SSL_RSA (SSL_kRSA|SSL_aRSA) ++#define SSL_kRSA 0x00000001L ++#define SSL_aRSA 0x00000002L ++#define SSL_RSA (SSL_kRSA|SSL_aRSA) ++#define SSL_aDSA 0x00000004L ++#define SSL_DSA SSL_aDSA ++#define SSL_eNULL 0x00000008L ++#define SSL_DES 0x00000010L ++#define SSL_3DES 0x00000020L ++#define SSL_RC4 0x00000040L ++#define SSL_RC2 0x00000080L ++#define SSL_AES128 0x00000100L ++#define SSL_AES256 0x00000200L ++#define SSL_AES (SSL_AES128|SSL_AES256) ++#define SSL_MD5 0x00000400L ++#define SSL_SHA1 0x00000800L ++#define SSL_kEDH 0x00001000L ++#define SSL_CAMELLIA128 0x00002000L ++#define SSL_CAMELLIA256 0x00004000L ++#define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256) ++#define SSL_SEED 0x00008000L ++#define SSL_kECDH 0x00010000L ++#define SSL_kECDHE 0x00020000L ++#define SSL_aECDSA 0x00040000L + + /* cipher strength */ + #define SSL_NULL 0x00000001L +@@ -248,29 +255,70 @@ typedef struct { + + /* Cipher translation */ + static cipher_properties ciphers_def[] = { +- /* SSL 2 ciphers */ +- {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, 168, 168, SSL_HIGH, SSL_ALLOWED}, +- {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, +- {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, +- {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, 56, 56, SSL_LOW, SSL_ALLOWED}, +- {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, +- {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, +- +- /* SSL3 ciphers */ +- {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, +- {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, +- {"DES-CBC3-SHA", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, 168, 168, SSL_HIGH, SSL_ALLOWED}, +- {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, 56, 56, SSL_LOW, SSL_ALLOWED}, +- {"EXP-RC4-MD5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, +- {"EXP-RC2-CBC-MD5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, 0, 0, SSL_EXPORT40, SSL_ALLOWED}, +- {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED}, +- {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED}, ++ ++ /* ++ * Use the same DEFAULT cipher list as OpenSSL, which is defined as: ALL:!aNULL:!eNULL:!SSLv2 ++ */ ++ ++ /* SSLv2 ciphers */ ++ {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, SSL_LOW, SSL_NOT_ALLOWED}, ++ {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, SSL_HIGH, SSL_NOT_ALLOWED}, ++ {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, SSL_MEDIUM, SSL_NOT_ALLOWED}, ++ {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, SSL_MEDIUM, SSL_NOT_ALLOWED}, ++ {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, SSL_EXPORT40, SSL_NOT_ALLOWED}, ++ {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, SSL_EXPORT40, SSL_NOT_ALLOWED}, ++ ++ /* SSLv3 ciphers */ ++ {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW, SSL_ALLOWED}, ++ {"DES-CBC3-SHA", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH, SSL_ALLOWED}, ++ {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, SSL_MEDIUM, SSL_ALLOWED}, ++ {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, SSL_MEDIUM, SSL_ALLOWED}, ++ {"EXP-RC2-CBC-MD5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, SSL_EXPORT40, SSL_ALLOWED}, ++ {"EXP-RC4-MD5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, SSL_EXPORT40, SSL_ALLOWED}, ++ {"EDH-RSA-DES-CBC-SHA", SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW, SSL_ALLOWED}, ++ {"EDH-RSA-DES-CBC3-SHA", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH, SSL_ALLOWED}, ++ {"EDH-DSS-DES-CBC-SHA", SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW, SSL_ALLOWED}, ++ {"EDH-DSS-DES-CBC3-SHA", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH, SSL_ALLOWED}, + + /* TLSv1 ciphers */ +- {"EXP1024-DES-CBC-SHA", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED}, +- {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED}, +- {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 128, 128, SSL_HIGH, SSL_ALLOWED}, +- {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 256, 256, SSL_HIGH, SSL_ALLOWED}, ++ {"EXP1024-DES-CBC-SHA", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, TLS1, SSL_EXPORT56, SSL_ALLOWED}, ++ {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_EXPORT56, SSL_ALLOWED}, ++ {"SEED-SHA", TLS_RSA_WITH_SEED_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_SEED|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"CAMELLIA256-SHA", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_CAMELLIA|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"CAMELLIA128-SHA", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_CAMELLIA|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-RSA-CAMELLIA128-SHA", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-RSA-CAMELLIA256-SHA", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-DSS-RC4-SHA", TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_kEDH|SSL_aDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"DHE-DSS-AES128-SHA", TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-DSS-AES256-SHA", TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-DSS-CAMELLIA128-SHA", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_CAMELLIA128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"DHE-DSS-CAMELLIA256-SHA", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_CAMELLIA256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-RSA-NULL-SHA", TLS_ECDH_RSA_WITH_NULL_SHA, SSL_kECDH|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"ECDH-RSA-RC4-SHA", TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_kECDH|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"ECDH-RSA-DES-CBC3-SHA", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-RSA-AES128-SHA", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-RSA-AES256-SHA", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-ECDSA-NULL-SHA", TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_kECDH|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"ECDH-ECDSA-RC4-SHA", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_kECDH|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"ECDH-ECDSA-DES-CBC3-SHA", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-ECDSA-AES128-SHA", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDH-ECDSA-AES256-SHA", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-RSA-NULL-SHA", TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_kECDHE|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_kECDHE|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"ECDHE-RSA-DES-CBC3-SHA", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-ECDSA-NULL-SHA", TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_kECDHE|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL, SSL_NOT_ALLOWED}, ++ {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_kECDHE|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM, SSL_ALLOWED}, ++ {"ECDHE-ECDSA-DES-CBC3-SHA", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, ++ {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH, SSL_ALLOWED}, + }; + + #define ciphernum (sizeof(ciphers_def)/sizeof(cipher_properties)) +@@ -577,6 +625,10 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) + mask |= SSL_RSA; + } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) { + mask |= SSL_eNULL; ++ } else if (!strcmp(cipher, "AES128")) { ++ mask |= SSL_AES128; ++ } else if (!strcmp(cipher, "AES256")) { ++ mask |= SSL_AES256; + } else if (!strcmp(cipher, "AES")) { + mask |= SSL_AES; + } else if (!strcmp(cipher, "3DES")) { +@@ -591,6 +643,24 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) + mask |= SSL_MD5; + } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) { + mask |= SSL_SHA1; ++ } else if (!strcmp(cipher, "EDH")) { ++ mask |= SSL_kEDH; ++ } else if (!strcmp(cipher, "DSS")) { ++ mask |= SSL_aDSA; ++ } else if (!strcmp(cipher, "CAMELLIA128")) { ++ mask |= SSL_CAMELLIA128; ++ } else if (!strcmp(cipher, "CAMELLIA256")) { ++ mask |= SSL_CAMELLIA256; ++ } else if (!strcmp(cipher, "CAMELLIA")) { ++ mask |= SSL_CAMELLIA; ++ } else if (!strcmp(cipher, "SEED")) { ++ mask |= SSL_SEED; ++ } else if (!strcmp(cipher, "ECDH")) { ++ mask |= SSL_kECDH; ++ } else if (!strcmp(cipher, "ECDHE")) { ++ mask |= SSL_kECDHE; ++ } else if (!strcmp(cipher, "ECDSA")) { ++ mask |= SSL_aECDSA; + } else if (!strcmp(cipher, "SSLv2")) { + protocol |= SSL2; + } else if (!strcmp(cipher, "SSLv3")) { +-- +1.7.11.4 + diff --git a/openldap-support-tlsv1-and-later.patch b/openldap-support-tlsv1-and-later.patch index a6c50fd..b8cc0f8 100644 --- a/openldap-support-tlsv1-and-later.patch +++ b/openldap-support-tlsv1-and-later.patch @@ -5,19 +5,18 @@ Backported-by: Jan Synacek Upstream ITS: #7979 Upstream commit: 7a7d9419432954cac18a582bed85a7c489d90f00 ---- openldap-2.4.40/include/ldap.h 2014-09-19 03:48:49.000000000 +0200 -+++ openldap-2.4.40/include/ldap.h 2015-01-27 14:52:42.741364186 +0100 -@@ -176,6 +176,7 @@ LDAP_BEGIN_DECL - #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ((3 << 8) + 1) - #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2) - #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3) -+#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 ((3 << 8) + 4) +--- openldap-2.4.40/libraries/libldap/tls_m.c 2014-11-14 09:02:39.489493061 +0100 ++++ openldap-2.4.40/libraries/libldap/tls_m.c 2014-11-14 09:23:07.239463097 +0100 +@@ -790,7 +790,7 @@ tlsm_bad_cert_handler(void *arg, PRFileD + case SSL_ERROR_BAD_CERT_DOMAIN: + break; + default: +- success = SECFailure; ++ success = SECFailure; + break; + } - /* OpenLDAP SASL options */ - #define LDAP_OPT_X_SASL_MECH 0x6100 ---- openldap-2.4.40/libraries/libldap/tls_m.c 2014-09-19 03:48:49.000000000 +0200 -+++ openldap-2.4.40/libraries/libldap/tls_m.c 2015-01-27 14:57:25.702243542 +0100 -@@ -1639,6 +1639,8 @@ tlsm_deferred_init( void *arg ) +@@ -1729,6 +1729,8 @@ tlsm_deferred_init( void *arg ) NSSInitContext *initctx = NULL; PK11SlotInfo *certdb_slot = NULL; #endif @@ -26,8 +25,8 @@ Upstream commit: 7a7d9419432954cac18a582bed85a7c489d90f00 SECStatus rc; int done = 0; -@@ -1823,7 +1825,17 @@ tlsm_deferred_init( void *arg ) - ctx->tc_using_pem = PR_TRUE; +@@ -1911,6 +1913,16 @@ tlsm_deferred_init( void *arg ) + } } + /* @@ -40,7 +39,16 @@ Upstream commit: 7a7d9419432954cac18a582bed85a7c489d90f00 + variant = ssl_variant_stream; + SSL_VersionRangeSetDefault(variant, &range); + - NSS_SetDomesticPolicy(); + NSS_SetDomesticPolicy(); PK11_SetPasswordFunc( tlsm_pin_prompt ); +--- openldap-2.4.40/include/ldap.h 2014-09-19 03:48:49.000000000 +0200 ++++ openldap-2.4.40/include/ldap.h 2014-11-14 09:25:54.560801030 +0100 +@@ -176,6 +176,7 @@ LDAP_BEGIN_DECL + #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ((3 << 8) + 1) + #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2) + #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3) ++#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 ((3 << 8) + 4) + /* OpenLDAP SASL options */ + #define LDAP_OPT_X_SASL_MECH 0x6100 diff --git a/openldap.spec b/openldap.spec index 88107a7..ec144d0 100644 --- a/openldap.spec +++ b/openldap.spec @@ -5,7 +5,7 @@ Name: openldap Version: 2.4.40 -Release: 9%{?dist} +Release: 10%{?dist} Summary: LDAP support libraries Group: System Environment/Daemons License: OpenLDAP @@ -26,6 +26,13 @@ Patch2: openldap-reentrant-gethostby.patch Patch3: openldap-smbk5pwd-overlay.patch Patch4: openldap-man-sasl-nocanon.patch Patch5: openldap-ai-addrconfig.patch +# nss patches, unlikely to ever get upstreamed +Patch11: openldap-nss-update-list-of-ciphers.patch +Patch12: openldap-tls-no-reuse-of-tls_session.patch +Patch13: openldap-nss-regex-search-hashed-cacert-dir.patch +Patch14: openldap-nss-ignore-certdb-type-prefix.patch +Patch15: openldap-nss-certs-from-certdb-fallback-pem.patch +Patch16: openldap-nss-pk11-freeslot.patch # fix back_perl problems with lt_dlopen() # might cause crashes because of symbol collisions @@ -43,13 +50,16 @@ Patch22: openldap-require-non-empty-attributelist.patch Patch90: check-password-makefile.patch Patch91: check-password.patch +# Fedora specific patches +Patch100: openldap-autoconf-pkgconfig-nss.patch # GCC 5 cpp patch, pending upstream inclusion (ITS #8056) -Patch100: openldap-gcc-5.patch +Patch101: openldap-gcc-5.patch -BuildRequires: cyrus-sasl-devel, krb5-devel, tcp_wrappers-devel, unixODBC-devel +BuildRequires: cyrus-sasl-devel, nss-devel, krb5-devel, tcp_wrappers-devel, unixODBC-devel BuildRequires: glibc-devel, libtool, libtool-ltdl-devel, groff, perl, perl-devel, perl(ExtUtils::Embed) # smbk5pwd overlay: BuildRequires: openssl-devel +Requires: nss-tools %description OpenLDAP is an open source suite of LDAP (Lightweight Directory Access @@ -115,8 +125,14 @@ programs needed for accessing and modifying OpenLDAP directories. pushd openldap-%{version} +# use pkg-config for Mozilla NSS library %patch100 -p1 +%patch101 -p1 +# alternative include paths for Mozilla NSS +ln -s %{_includedir}/nss3 include/nss +ln -s %{_includedir}/nspr4 include/nspr + AUTOMAKE=%{_bindir}/true autoreconf -fi %patch0 -p1 @@ -125,6 +141,12 @@ AUTOMAKE=%{_bindir}/true autoreconf -fi %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 %patch19 -p1 %patch20 -p1 %patch21 -p1 @@ -194,6 +216,7 @@ pushd openldap-%{version} --without-fetch \ --with-threads \ --with-pic \ + --with-tls=moznss \ --with-gnu-ld \ \ --libexecdir=%{_libdir} @@ -514,6 +537,9 @@ exit 0 %{_mandir}/man3/* %changelog +* Fri Feb 20 2015 Jan Synáček - 2.4.40-10 +- link against moznss again (#1187742) + * Wed Feb 11 2015 Jan Synáček - 2.4.40-9 - fix: Unknown Berkeley DB major version in db.h (#1191098) diff --git a/slapd.ldif b/slapd.ldif index a6c6bfc..4105131 100644 --- a/slapd.ldif +++ b/slapd.ldif @@ -9,9 +9,9 @@ cn: config # # TLS settings # -#olcTLSCACertificatePath: /etc/openldap/certs/cacert.pem -#olcTLSCertificateFile: /etc/openldap/certs/servercert.pem -#olcTLSCertificateKeyFile: /etc/openldap/certs/serverkey.pem +olcTLSCACertificatePath: /etc/openldap/certs +olcTLSCertificateFile: "OpenLDAP Server" +olcTLSCertificateKeyFile: /etc/openldap/certs/password # # Do not enable referrals until AFTER you have a working directory