diff --git a/openldap-autoconf-pkgconfig-nss.patch b/openldap-autoconf-pkgconfig-nss.patch deleted file mode 100644 index 8b4bb19..0000000 --- a/openldap-autoconf-pkgconfig-nss.patch +++ /dev/null @@ -1,49 +0,0 @@ -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-doc1.patch b/openldap-doc1.patch deleted file mode 100644 index 13c4c41..0000000 --- a/openldap-doc1.patch +++ /dev/null @@ -1,36 +0,0 @@ -Upstream ITS: #7568 - -From 6be982c000133ccf9da949d39eed23a93bc7bfc5 Mon Sep 17 00:00:00 2001 -From: Jan Synacek -Date: Tue, 9 Apr 2013 12:41:38 +0200 -Subject: [PATCH 1/2] Fix typos in ldap.conf.5 - ---- - doc/man/man5/ldap.conf.5 | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5 -index cfde143..8f7fecd 100644 ---- a/doc/man/man5/ldap.conf.5 -+++ b/doc/man/man5/ldap.conf.5 -@@ -297,7 +297,7 @@ Specifies if GSSAPI encryption (GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG) - should be used. The default is off. - .TP - .B GSSAPI_ALLOW_REMOTE_PRINCIPAL --Specifies if GSSAPI based authentification should try to form the -+Specifies if GSSAPI based authentication should try to form the - target principal name out of the ldapServiceName or dnsHostName - attribute of the targets RootDSE entry. The default is off. - .SH TLS OPTIONS -@@ -354,7 +354,7 @@ it is of critical importance that the key file is protected carefully. - When using Mozilla NSS, TLS_KEY specifies the name of a file that contains - the password for the key for the certificate specified with TLS_CERT. The - modutil command can be used to turn off password protection for the cert/key --database. For example, if TLS_CACERTDIR specifes /home/scarter/.moznss as -+database. For example, if TLS_CACERTDIR specifies /home/scarter/.moznss as - the location of the cert/key database, use modutil to change the password - to the empty string: - .nf --- -1.8.1.4 - diff --git a/openldap-doc2.patch b/openldap-doc2.patch deleted file mode 100644 index 47b1c13..0000000 --- a/openldap-doc2.patch +++ /dev/null @@ -1,27 +0,0 @@ -Upstream ITS: #7568 - -From 05c726c62785b2c307f9c5343a253d43ec7322c6 Mon Sep 17 00:00:00 2001 -From: Jan Synacek -Date: Tue, 9 Apr 2013 12:42:31 +0200 -Subject: [PATCH 2/2] Add -Q to slaptest's help - ---- - servers/slapd/slapcommon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c -index 714e2bc..153310f 100644 ---- a/servers/slapd/slapcommon.c -+++ b/servers/slapd/slapcommon.c -@@ -92,7 +92,7 @@ usage( int tool, const char *progname ) - break; - - case SLAPTEST: -- options = " [-n databasenumber] [-u]\n"; -+ options = " [-n databasenumber] [-u] [-Q]\n"; - break; - - case SLAPSCHEMA: --- -1.8.1.4 - diff --git a/openldap-loglevel2bvarray.patch b/openldap-loglevel2bvarray.patch deleted file mode 100644 index 1a0e766..0000000 --- a/openldap-loglevel2bvarray.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 4313b91b0bc2fe6585656cd69a03f9755b5af3c4 Mon Sep 17 00:00:00 2001 -From: Jan Synacek -Date: Wed, 29 May 2013 10:21:40 +0200 -Subject: [PATCH] Fix loglevel2bvarray - ---- - servers/slapd/bconfig.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c -index 4e1f1b5..def6daf 100644 ---- a/servers/slapd/bconfig.c -+++ b/servers/slapd/bconfig.c -@@ -3622,6 +3622,10 @@ loglevel2bvarray( int l, BerVarray *bva ) - loglevel_init(); - } - -+ if ( l == 0 ) { -+ return value_add_one( bva, ber_bvstr( "0" ) ); -+ } -+ - return mask_to_verbs( loglevel_ops, l, bva ); - } - --- -1.8.1.4 - diff --git a/openldap-nss-allow-certname-with-token-name.patch b/openldap-nss-allow-certname-with-token-name.patch deleted file mode 100644 index a75e84f..0000000 --- a/openldap-nss-allow-certname-with-token-name.patch +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index d20e48a..0000000 --- a/openldap-nss-certs-from-certdb-fallback-pem.patch +++ /dev/null @@ -1,86 +0,0 @@ -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-cipher-attributes.patch b/openldap-nss-cipher-attributes.patch deleted file mode 100644 index ad15aea..0000000 --- a/openldap-nss-cipher-attributes.patch +++ /dev/null @@ -1,95 +0,0 @@ -Update MozNSS cipher attributes definitions - -Author: Matus Honek -PreviousAuthor: Jan Vcelak - -diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c ---- a/libraries/libldap/tls_m.c -+++ b/libraries/libldap/tls_m.c -@@ -210,27 +210,44 @@ 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_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_MD5 0x00000400L -+#define SSL_SHA1 0x00000800L -+#define SSL_kEDH 0x00001000L -+#define SSL_CAMELLIA128 0x00002000L -+#define SSL_CAMELLIA256 0x00004000L -+#define SSL_SEED 0x00008000L -+#define SSL_kECDH 0x00010000L -+#define SSL_kECDHE 0x00020000L -+#define SSL_aECDSA 0x00040000L -+#define SSL_SHA256 0x00080000L -+#define SSL_SHA384 0x00100000L -+#define SSL_kEECDH 0x00200000L -+#define SSL_AESGCM 0x00400000L -+#define SSL_AEAD 0x00800000L -+#define SSL_aPSK 0x01000000L -+#define SSL_CHACHA20POLY1305 0x02000000L -+ -+/* cipher attributes non-unique - do not use for definitions */ -+#define SSL_RSA 0x00000001L -+#define SSL_AES 0x00000002L -+#define SSL_CAMELLIA 0x00000004L -+#define SSL_ECDH 0x00000008L - - /* cipher strength */ - #define SSL_NULL 0x00000001L -@@ -240,10 +257,15 @@ typedef struct { - #define SSL_MEDIUM 0x00000010L - #define SSL_HIGH 0x00000020L - -+/* cipher strengths non-unique - do not use for definitions */ -+#define SSL_EXPORT 0x00000001L -+ - #define SSL2 0x00000001L - #define SSL3 0x00000002L - /* OpenSSL treats SSL3 and TLSv1 the same */ - #define TLS1 SSL3 -+#define TLS1_2 0x00000004L -+#define TLS1_3 0x00000008L - - /* Cipher translation */ - static cipher_properties ciphers_def[] = { ---- 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-nss-ciphers-definitions.patch b/openldap-nss-ciphers-definitions.patch deleted file mode 100644 index 6de142c..0000000 --- a/openldap-nss-ciphers-definitions.patch +++ /dev/null @@ -1,139 +0,0 @@ -Update MozNSS definitions of ciphers - -Author: Matus Honek -PreviousAuthor: Jan Vcelak - -diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c ---- a/libraries/libldap/tls_m.c -+++ b/libraries/libldap/tls_m.c -@@ -268,29 +268,109 @@ 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}, -+ -+ /* SSLv2 ciphers */ -+ {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, SSL_LOW}, -+ {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, SSL_HIGH}, -+ {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, SSL_MEDIUM}, -+ {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, SSL_MEDIUM}, -+ {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, SSL_EXPORT40}, -+ {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, SSL_EXPORT40}, -+ -+ /* SSLv3 ciphers */ -+ {"NULL-MD5", TLS_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, SSL_NULL}, /* SSL_RSA_WITH_NULL_MD5 */ -+ {"NULL-SHA", TLS_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, SSL_NULL}, /* SSL_RSA_WITH_NULL_SHA */ -+ {"DES-CBC-SHA", TLS_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW}, /* SSL_RSA_WITH_DES_CBC_SHA */ -+ {"DES-CBC3-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH}, /* SSL_RSA_WITH_3DES_EDE_CBC_SHA */ -+ {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, SSL_MEDIUM}, /* SSL_RSA_WITH_RC4_128_MD5 */ -+ {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, SSL_MEDIUM}, /* SSL_RSA_WITH_RC4_128_SHA */ -+ {"EXP-RC2-CBC-MD5", TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, SSL_EXPORT40}, /* SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */ -+ {"EXP-RC4-MD5", TLS_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, SSL_EXPORT40}, /* SSL_RSA_EXPORT_WITH_RC4_40_MD5 */ -+ {"EDH-RSA-DES-CBC-SHA", TLS_DHE_RSA_WITH_DES_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW}, /* SSL_DHE_RSA_WITH_DES_CBC_SHA */ -+ {"EDH-RSA-DES-CBC3-SHA", TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH}, /* SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ -+ {"EDH-DSS-DES-CBC-SHA", TLS_DHE_DSS_WITH_DES_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_DES|SSL_SHA1, SSL3, SSL_LOW}, /* SSL_DHE_DSS_WITH_DES_CBC_SHA */ -+ {"EDH-DSS-DES-CBC3-SHA", TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_3DES|SSL_SHA1, SSL3, SSL_HIGH}, /* SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA */ - - /* 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}, -+ {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_EXPORT56}, -+ {"SEED-SHA", TLS_RSA_WITH_SEED_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_SEED|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"CAMELLIA256-SHA", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"CAMELLIA128-SHA", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-RSA-CAMELLIA128-SHA", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-RSA-CAMELLIA256-SHA", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_kEDH|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-DSS-RC4-SHA", TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_kEDH|SSL_aDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"DHE-DSS-AES128-SHA", TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-DSS-AES256-SHA", TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-DSS-CAMELLIA128-SHA", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_CAMELLIA128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"DHE-DSS-CAMELLIA256-SHA", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_kEDH|SSL_aDSA|SSL_CAMELLIA256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-RSA-NULL-SHA", TLS_ECDH_RSA_WITH_NULL_SHA, SSL_kECDH|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL}, -+ {"ECDH-RSA-RC4-SHA", TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_kECDH|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"ECDH-RSA-DES-CBC3-SHA", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-RSA-AES128-SHA", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-RSA-AES256-SHA", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_kECDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-ECDSA-NULL-SHA", TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_kECDH|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL}, -+ {"ECDH-ECDSA-RC4-SHA", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_kECDH|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"ECDH-ECDSA-DES-CBC3-SHA", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-ECDSA-AES128-SHA", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDH-ECDSA-AES256-SHA", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDH|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-RSA-NULL-SHA", TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_kECDHE|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL}, -+ {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_kECDHE|SSL_aRSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"ECDHE-RSA-DES-CBC3-SHA", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_kECDHE|SSL_aRSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-ECDSA-NULL-SHA", TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_kECDHE|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLS1, SSL_NULL}, -+ {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_kECDHE|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLS1, SSL_MEDIUM}, -+ {"ECDHE-ECDSA-DES-CBC3-SHA", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLS1, SSL_HIGH}, -+ {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDHE|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLS1, SSL_HIGH}, -+ -+ // Ciphers commented out are not in NSS yet. -+ -+ {"NULL-SHA256", TLS_RSA_WITH_NULL_SHA256, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA256, TLS1_2, SSL_NULL}, -+ {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"AES128-GCM-SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"AES256-GCM-SHA384", 0x009d /* TLS_RSA_WITH_AES_256_GCM_SHA384 */, SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ -+ {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_kEDH|SSL_aRSA|SSL_AES256|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_kEDH|SSL_aRSA|SSL_AES128|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"DHE-RSA-AES128-GCM-SHA256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kEDH|SSL_aRSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"DHE-RSA-AES256-GCM-SHA384", 0x009f /* TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */, SSL_kEDH|SSL_aRSA|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ -+ {"DHE-DSS-AES128-SHA256", TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, SSL_kEDH|SSL_aDSA|SSL_AES128|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"DHE-DSS-AES256-SHA256", TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, SSL_kEDH|SSL_aDSA|SSL_AES256|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"DHE-DSS-AES128-GCM-SHA256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_kEDH|SSL_aDSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"DHE-DSS-AES128-GCM-SHA256", 0x00a3 /* TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 */, SSL_kEDH|SSL_aDSA|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ //{"DHE-DSS-AES128-GCM-SHA384", TLS_DHE_DSS_WITH_AES_128_GCM_SHA384, SSL_kEDH|SSL_aDSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ -+ {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_kECDHE|SSL_aECDSA|SSL_AES128|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_kECDHE|SSL_aRSA|SSL_AES128|SSL_SHA256, TLS1_2, SSL_HIGH}, -+ {"ECDHE-ECDSA-AES128-GCM-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE|SSL_aECDSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-RSA-AES128-GCM-SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE|SSL_aRSA|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-ECDSA-AES256-GCM-SHA384", 0xc02c /* TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 */, SSL_kECDHE|SSL_aECDSA|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-RSA-AES256-GCM-SHA384", 0xc030 /* TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 */, SSL_kECDHE|SSL_aRSA|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-ECDSA-AES256-SHA384", 0xc024 /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 */, SSL_kECDHE|SSL_aECDSA|SSL_AES256|SSL_SHA384, TLS1_2, SSL_HIGH}, -+ {"ECDHE-RSA-AES256-SHA384", 0xc028 /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 */, SSL_kECDHE|SSL_aRSA|SSL_AES256|SSL_SHA384, TLS1_2, SSL_HIGH}, -+ -+ {"ECDHE-PSK-AES128-GCM-SHA256", 0xd001 /* TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 */, SSL_kECDHE|SSL_aPSK|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-PSK-CHACHA20-POLY1305", 0xccac /* TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */, SSL_kECDHE|SSL_aPSK|SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"ECDHE-PSK-AES256-GCM-SHA384", 0xd002 /* TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 */, SSL_kECDHE|SSL_aPSK|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"", 0x00aa /* TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 */, SSL_kEDH|SSL_aPSK|SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"", 0xccad /* TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */, SSL_kEDH|SSL_aPSK|SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ {"", 0x00ab /* TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 */, SSL_kEDH|SSL_aPSK|SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ //{"ECDHE-ECDSA-CHACHA20-POLY1305", 0xcca9 /* TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */, SSL_kECDHE|SSL_aECDSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ //{"ECDHE-RSA-CHACHA20-POLY1305", 0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */, SSL_kECDHE|SSL_aRSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ //{"DHE-RSA-CHACHA20-POLY1305", 0xccaa /* TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */, SSL_kEDH|SSL_aRSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_2, SSL_HIGH}, -+ -+ // TLSv1.3 -+ {"TLS13-AES-128-GCM-SHA256", 0x1301 /* TLS_AES_128_GCM_SHA256 */, SSL_AES128|SSL_AESGCM|SSL_AEAD, TLS1_3, SSL_HIGH}, -+ {"TLS13-AES-256-GCM-SHA384", 0x1302 /* TLS_AES_256_GCM_SHA384 */, SSL_AES256|SSL_AESGCM|SSL_AEAD, TLS1_3, SSL_HIGH}, -+ {"TLS13-CHACHA20-POLY1305-SHA256", 0x1303 /* TLS_CHACHA20_POLY1305_SHA256 */, SSL_CHACHA20POLY1305|SSL_AEAD, TLS1_3, SSL_HIGH}, - }; - - #define ciphernum (sizeof(ciphers_def)/sizeof(cipher_properties)) diff --git a/openldap-nss-ciphers-parsing.patch b/openldap-nss-ciphers-parsing.patch deleted file mode 100644 index dd0407b..0000000 --- a/openldap-nss-ciphers-parsing.patch +++ /dev/null @@ -1,196 +0,0 @@ -Update MozNSS OpenSSL-like parsing code - -Author: Matus Honek -PreviousAuthor: Jan Vcelak - -diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c ---- a/libraries/libldap/tls_m.c -+++ b/libraries/libldap/tls_m.c -@@ -617,10 +617,12 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - while ((*cipher) && (isspace(*cipher))) - ++cipher; - -- action = 1; - switch(*cipher) { -- case '+': /* Add something */ -- action = 1; -+ case '+': /* Do nothig. NSS does not support ordering. */ -+ Debug( LDAP_DEBUG_ARGS, -+ "TLS: warning: parsing cipher string: ordering is not supported by NSS.\n", -+ 0, 0, 0 ); -+ action = 2; - cipher++; - break; - case '-': /* Subtract something */ -@@ -631,8 +633,8 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - action = -1; - cipher++; - break; -- default: -- /* do nothing */ -+ default: /* Add something */ -+ action = 1; - break; - } - -@@ -666,7 +668,10 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - } - } else { - int mask = 0; -+ int multi_mask = 0; -+ int negative_mask = 0; - int strength = 0; -+ int multi_strength = 0; - int protocol = 0; - char *c; - -@@ -677,12 +682,21 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - *c++ = '\0'; - } - -- if (!strcmp(cipher, "RSA")) { -- mask |= SSL_RSA; -+ if ((!strcmp(cipher, "RSA")) || (!strcmp(cipher, "kRSA"))) { -+ mask |= SSL_kRSA; -+ } else if (!strcmp(cipher, "aRSA")) { -+ mask |= SSL_aRSA; -+ negative_mask |= SSL_kECDH; - } 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, "AESGCM")) { -+ mask |= SSL_AESGCM; - } else if (!strcmp(cipher, "AES")) { -- mask |= SSL_AES; -+ multi_mask |= SSL_AES; - } else if (!strcmp(cipher, "3DES")) { - mask |= SSL_3DES; - } else if (!strcmp(cipher, "DES")) { -@@ -693,26 +707,69 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - mask |= SSL_RC2; - } else if (!strcmp(cipher, "MD5")) { - mask |= SSL_MD5; -+ } else if (!strcmp(cipher, "SHA256")) { -+ mask |= SSL_SHA256; -+ } else if (!strcmp(cipher, "SHA384")) { -+ mask |= SSL_SHA384; - } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) { - mask |= SSL_SHA1; -+ } else if ((!strcmp(cipher, "EDH")) || (!strcmp(cipher, "DH"))) { -+ mask |= SSL_kEDH; -+ } else if ((!strcmp(cipher, "DSS")) || (!strcmp(cipher, "aDSS"))) { -+ mask |= SSL_aDSA; -+ } else if (!strcmp(cipher, "CAMELLIA128")) { -+ mask |= SSL_CAMELLIA128; -+ } else if (!strcmp(cipher, "CAMELLIA256")) { -+ mask |= SSL_CAMELLIA256; -+ } else if (!strcmp(cipher, "CAMELLIA")) { -+ multi_mask |= SSL_CAMELLIA; -+ } else if (!strcmp(cipher, "SEED")) { -+ mask |= SSL_SEED; -+ } else if (!strcmp(cipher, "kECDHe")) { -+ mask |= SSL_kECDH|SSL_aECDSA; -+ } else if (!strcmp(cipher, "kECDHr")) { -+ mask |= SSL_kECDH|SSL_aRSA; -+ } else if (!strcmp(cipher, "kECDH")) { -+ mask |= SSL_kECDH; -+ } else if (!strcmp(cipher, "aECDH")) { -+ mask |= SSL_kECDH; -+ } else if (!strcmp(cipher, "EECDH")) { -+ mask |= SSL_kECDHE; -+ } else if (!strcmp(cipher, "kEECDH")) { -+ mask |= SSL_kECDHE; -+ } else if (!strcmp(cipher, "ECDHE")) { -+ mask |= SSL_kECDHE; -+ } else if (!strcmp(cipher, "ECDH")) { -+ multi_mask |= SSL_ECDH; -+ } else if ((!strcmp(cipher, "ECDSA")) || (!strcmp(cipher, "aECDSA"))) { -+ mask |= SSL_aECDSA; -+ negative_mask |= SSL_kECDH; -+ } else if (!strcmp(cipher, "PSK")) { -+ mask |= SSL_aPSK; -+ } else if (!strcmp(cipher, "CHACHA20POLY1305")) { -+ mask |= SSL_CHACHA20POLY1305; - } else if (!strcmp(cipher, "SSLv2")) { - protocol |= SSL2; - } else if (!strcmp(cipher, "SSLv3")) { - protocol |= SSL3; - } else if (!strcmp(cipher, "TLSv1")) { - protocol |= TLS1; -+ } else if (!strcmp(cipher, "TLSv1.2")) { -+ protocol |= TLS1_2; -+ } else if (!strcmp(cipher, "TLSv1.3")) { -+ protocol |= TLS1_3; - } else if (!strcmp(cipher, "HIGH")) { - strength |= SSL_HIGH; - } else if (!strcmp(cipher, "MEDIUM")) { - strength |= SSL_MEDIUM; - } else if (!strcmp(cipher, "LOW")) { - strength |= SSL_LOW; -- } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) { -- strength |= SSL_EXPORT40|SSL_EXPORT56; - } else if (!strcmp(cipher, "EXPORT40")) { - strength |= SSL_EXPORT40; - } else if (!strcmp(cipher, "EXPORT56")) { - strength |= SSL_EXPORT56; -+ } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) { -+ multi_strength |= SSL_EXPORT; - } - - if (c) -@@ -720,23 +775,39 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - - } /* while */ - -+ /* NSS does not support ordering */ -+ if (action == 2) -+ continue; -+ - /* If we have a mask, apply it. If not then perhaps they provided - * a specific cipher to enable. -+ * if more than one mask is provided then AND logic applies (to match openssl) - */ -- if (mask || strength || protocol) { -+ if (mask || negative_mask || multi_mask || strength || multi_strength || protocol) { - for (i=0; i -Resolves: #1387868 -Backports: #1245279 #1300701 - -diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c ---- a/libraries/libldap/tls_m.c -+++ b/libraries/libldap/tls_m.c -@@ -645,7 +645,16 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) - } - } else if (!strcmp(cipher, "DEFAULT")) { - for (i=0; i -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 deleted file mode 100644 index 2fab916..0000000 --- a/openldap-nss-ignore-certdb-type-prefix.patch +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index bf008f4..0000000 --- a/openldap-nss-multiple-tls-contexts.patch +++ /dev/null @@ -1,1029 +0,0 @@ -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 deleted file mode 100644 index ca657c8..0000000 --- a/openldap-nss-pk11-freeslot.patch +++ /dev/null @@ -1,23 +0,0 @@ -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-protocol-version-new-api.patch b/openldap-nss-protocol-version-new-api.patch deleted file mode 100644 index 8a5efa7..0000000 --- a/openldap-nss-protocol-version-new-api.patch +++ /dev/null @@ -1,71 +0,0 @@ -Implement new API for setting TLS protocol version. - -The code being deleted has been misplaced and it's effect has been -mangled by a code later on. This patch puts the code at the correct -place and introduces some more logging and error checking. - -Author: Matus Honek -RHBZ: #1375432 - -diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c ---- a/libraries/libldap/tls_m.c -+++ b/libraries/libldap/tls_m.c -@@ -2421,6 +2411,58 @@ tlsm_deferred_ctx_init( void *arg ) - 0, 0, 0 ); - return -1; - } -+ if ( lt->lt_protocol_min >= LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) { -+ SSLVersionRange supported_range, default_range, selected_range; -+ if ( SECSuccess != SSL_VersionRangeGetSupported(ssl_variant_stream, &supported_range) ) { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: error: could not get SSL supported version range (SSL_VersionRangeGetSupported).\n", -+ 0, 0, 0 ); -+ return -1; -+ } else { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: info: SSL supported protocol version range is (%#04x, %#04x) (SSL_VersionRangeGetSupported).\n", -+ supported_range.min, supported_range.max, 0); -+ } -+ if ( SECSuccess != SSL_VersionRangeGetDefault(ssl_variant_stream, &default_range) ) { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: error: could not get SSL default protocol version range (SSL_VersionRangeGetDefault).\n", -+ 0, 0, 0 ); -+ return -1; -+ } else { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: info: SSL default protocol version range is (%#04x, %#04x) (SSL_VersionRangeGetDefault).\n", -+ default_range.min, default_range.max, 0); -+ } -+ selected_range.min = lt->lt_protocol_min; -+ selected_range.max = default_range.max; -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: info: TLS configured protocol minimal version is %#04x, the maximal version (the NSS default) is %#04x.\n", -+ selected_range.min, selected_range.max, 0); -+ if ( (selected_range.min > supported_range.max) || -+ (selected_range.max < supported_range.min) ) { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: error: selected protocol version range out of NSS-supported version range.\n", -+ 0, 0, 0); -+ return -1; -+ } else { -+ if ( SECSuccess != SSL_VersionRangeSet(ctx->tc_model, &selected_range) ) { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: error: could not set protocol version range (SSL_VersionRangeSet).\n", -+ 0, 0, 0); -+ return -1; -+ } -+ if ( SECSuccess != SSL_VersionRangeGet(ctx->tc_model, &selected_range) ) { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: error: could not get protocol version range (SSL_VersionRangeGet).\n", -+ 0, 0, 0); -+ return -1; -+ } else { -+ Debug( LDAP_DEBUG_ANY, -+ "TLS: info: SSL set protocol version range is (%#04x, %#04x) (SSL_VersionRangeGet).\n", -+ selected_range.min, selected_range.max, 0); -+ } -+ } -+ } - - if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) { - Debug( LDAP_DEBUG_ANY, diff --git a/openldap-nss-regex-search-hashed-cacert-dir.patch b/openldap-nss-regex-search-hashed-cacert-dir.patch deleted file mode 100644 index 03493db..0000000 --- a/openldap-nss-regex-search-hashed-cacert-dir.patch +++ /dev/null @@ -1,91 +0,0 @@ -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-tls-no-reuse-of-tls_session.patch b/openldap-tls-no-reuse-of-tls_session.patch deleted file mode 100644 index 5c397d1..0000000 --- a/openldap-tls-no-reuse-of-tls_session.patch +++ /dev/null @@ -1,92 +0,0 @@ -TLS: do not reuse tls_session if hostname check fails - -If multiple servers are specified, the connection to the first one succeeds, and the hostname verification fails, -*tls_session is not dropped, but reused when connecting to the second server. - -This is a problem with Mozilla NSS backend because another handshake cannot be performed on the same file descriptor. -From this reason, hostname checking was moved into ldap_int_tls_connect() before connection error handling. - -Author: Jan Vcelak -Upstream ITS: #7373 -Resolves: #852476 - -diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c -index 10b993b..a3cd590 100644 ---- a/libraries/libldap/tls2.c -+++ b/libraries/libldap/tls2.c -@@ -320,7 +320,7 @@ update_flags( Sockbuf *sb, tls_session * ssl, int rc ) - */ - - static int --ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) -+ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host ) - { - Sockbuf *sb = conn->lconn_sb; - int err; -@@ -365,6 +365,10 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) - errno = WSAGetLastError(); - #endif - -+ if ( err == 0 ) { -+ err = ldap_pvt_tls_check_hostname( ld, ssl, host ); -+ } -+ - if ( err < 0 ) - { - char buf[256], *msg; -@@ -495,7 +499,15 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in ) - { - tls_session *session = s; - -- return tls_imp->ti_session_chkhost( ld, session, name_in ); -+ if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && -+ ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { -+ ld->ld_errno = tls_imp->ti_session_chkhost( ld, session, name_in ); -+ if (ld->ld_errno != LDAP_SUCCESS) { -+ return ld->ld_errno; -+ } -+ } -+ -+ return LDAP_SUCCESS; - } - - int -@@ -857,7 +869,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) - #endif /* LDAP_USE_NON_BLOCKING_TLS */ - - ld->ld_errno = LDAP_SUCCESS; -- ret = ldap_int_tls_connect( ld, conn ); -+ ret = ldap_int_tls_connect( ld, conn, host ); - - #ifdef LDAP_USE_NON_BLOCKING_TLS - while ( ret > 0 ) { /* this should only happen for non-blocking io */ -@@ -878,7 +890,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) - } else { - /* ldap_int_poll called ldap_pvt_ndelay_off */ - ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb ); -- ret = ldap_int_tls_connect( ld, conn ); -+ ret = ldap_int_tls_connect( ld, conn, host ); - if ( ret > 0 ) { /* need to call tls_connect once more */ - struct timeval curr_time_tv, delta_tv; - -@@ -935,20 +947,6 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) - return (ld->ld_errno); - } - -- ssl = ldap_pvt_tls_sb_ctx( sb ); -- assert( ssl != NULL ); -- -- /* -- * compare host with name(s) in certificate -- */ -- if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && -- ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { -- ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host ); -- if (ld->ld_errno != LDAP_SUCCESS) { -- return ld->ld_errno; -- } -- } -- - return LDAP_SUCCESS; - } - diff --git a/openldap-tlsmc.patch b/openldap-tlsmc.patch new file mode 100644 index 0000000..2bc514f --- /dev/null +++ b/openldap-tlsmc.patch @@ -0,0 +1,1776 @@ +diff --git a/configure.in b/configure.in +index b251b6b06..8a836eabb 100644 +--- a/configure.in ++++ b/configure.in +@@ -237,6 +237,7 @@ dnl OL_ARG_ENABLE(referrals,[ --enable-referrals enable LDAPv2+ Referrals (ex + ol_enable_referrals=${ol_enable_referrals-no} + OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl + OL_ARG_ENABLE(local,[ --enable-local enable AF_LOCAL (AF_UNIX) socket support], auto)dnl ++OL_ARG_ENABLE(moznss_compatibility,[ --enable-moznss-compatibility enable MozNSS compatibility], no)dnl + + dnl ---------------------------------------------------------------- + dnl General "with" options +@@ -1256,6 +1257,26 @@ if test $ol_link_tls = no ; then + fi + fi + ++if test $ol_enable_moznss_compatibility = yes ; then ++ if test $have_openssl = yes ; then ++ if test $ol_with_tls = openssl ; then ++ PKG_CHECK_MODULES(MOZNSS, [nss nspr], [have_moznss_libs=yes], [have_moznss_libs=no]) ++ if test $have_moznss_libs = yes ; then ++ AC_DEFINE(HAVE_MOZNSS_COMPATIBILITY, 1, ++ [define if you want to support MozNSS databases when compiled with OpenSSL]) ++ TLS_LIBS="$TLS_LIBS $MOZNSS_LIBS" ++ CFLAGS="$CFLAGS $MOZNSS_CFLAGS" ++ else ++ AC_MSG_ERROR([For MOZNSS_COMPATIBILITY you have to have MozNSS present.]) ++ fi ++ else ++ AC_MSG_ERROR([For MOZNSS_COMPATIBILITY you have to compile with OpenSSL for crypto. (see --with-tls flag)]) ++ fi ++ else ++ AC_MSG_ERROR([For MOZNSS_COMPATIBILITY you have to have OpenSSL devel available. (unable to build with OpenSSL)]) ++ fi ++fi ++ + WITH_TLS=no + if test $ol_link_tls = yes ; then + AC_DEFINE(HAVE_TLS, 1, [define if you have TLS]) +diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3 +index 389e1c4fd..60c7d05a5 100644 +--- a/doc/man/man3/ldap_get_option.3 ++++ b/doc/man/man3/ldap_get_option.3 +@@ -772,6 +772,19 @@ must be + When using the OpenSSL library this is an SSL*. When using other + crypto libraries this is a pointer to an OpenLDAP private structure. + Applications generally should not use this option. ++.TP ++.B LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY ++Sets/gets the status of the MozNSS database compatibility layer for TLS options. This options is available only if OpenLDAP is compiled with OpenSSL. This has effect only before the TLS context is established. ++This option defaults to be on. ++.BR invalue ++should either be ++.BR LDAP_OPT_OFF ++or ++.BR LDAP_OPT_ON ; ++.BR outvalue ++must be ++.BR "int *" . ++When set, just before TLS context initialization the library will first check if TLS settings are MozNSS-specific and if so it will export certificates from a preconfigured database and set other TLS settings so that OpenSSL can continue without issues. + .SH ERRORS + On success, the functions return + .BR LDAP_OPT_SUCCESS , +diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5 +index b6735bab5..612b63a2b 100644 +--- a/doc/man/man5/ldap.conf.5 ++++ b/doc/man/man5/ldap.conf.5 +@@ -483,6 +483,11 @@ Check the CRL for a whole certificate chain + Specifies the file containing a Certificate Revocation List to be used + to verify if the server certificates have not been revoked. This + parameter is only supported with GnuTLS and Mozilla NSS. ++.RE ++.TP ++.B TLS_MOZNSS_COMPATIBILITY ++Specifies whether the MozNSS database compatibility layer for TLS options should be enabled. This options is available only if OpenLDAP is compiled with OpenSSL. ++This option defaults to be on. + .SH "ENVIRONMENT VARIABLES" + .TP + LDAPNOINIT +diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5 +index 6afbd7d6b..2893cd4a5 100644 +--- a/doc/man/man5/slapd-config.5 ++++ b/doc/man/man5/slapd-config.5 +@@ -1004,6 +1004,11 @@ Check the CRL for a whole certificate chain + Specifies a file containing a Certificate Revocation List to be used + for verifying that certificates have not been revoked. This parameter + is only valid when using GnuTLS or Mozilla NSS. ++.RE ++.TP ++.B olcTLSMozNSSCompatibility ++Specifies whether the MozNSS database compatibility layer for TLS options should be enabled. This options is available only if OpenLDAP is compiled with OpenSSL. ++This option defaults to be on. + .SH DYNAMIC MODULE OPTIONS + If + .B slapd +diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 +index 86abeca80..742568393 100644 +--- a/doc/man/man5/slapd.conf.5 ++++ b/doc/man/man5/slapd.conf.5 +@@ -1235,6 +1235,11 @@ Check the CRL for a whole certificate chain + Specifies a file containing a Certificate Revocation List to be used + for verifying that certificates have not been revoked. This directive is + only valid when using GnuTLS and Mozilla NSS. ++.RE ++.TP ++.B TLSMozNSSCompatibility ++Specifies whether the MozNSS database compatibility layer for TLS options should be enabled. This options is available only if OpenLDAP is compiled with OpenSSL. ++This option defaults to be on. + .SH GENERAL BACKEND OPTIONS + Options in this section only apply to the configuration file section + for the specified backend. They are supported by every +diff --git a/include/ldap.h b/include/ldap.h +index db6869da8..aae8bebd8 100644 +--- a/include/ldap.h ++++ b/include/ldap.h +@@ -158,6 +158,10 @@ LDAP_BEGIN_DECL + #define LDAP_OPT_X_TLS_NEWCTX 0x600f + #define LDAP_OPT_X_TLS_CRLFILE 0x6010 /* GNUtls only */ + #define LDAP_OPT_X_TLS_PACKAGE 0x6011 ++#define LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY 0x6050 ++ ++#define LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_DISABLED 0 ++#define LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_ENABLED 1 + + #define LDAP_OPT_X_TLS_NEVER 0 + #define LDAP_OPT_X_TLS_HARD 1 +diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in +index 636b15506..a1445312f 100644 +--- a/libraries/libldap/Makefile.in ++++ b/libraries/libldap/Makefile.in +@@ -26,7 +26,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ + request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ + init.c options.c print.c string.c util-int.c schema.c \ + charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ +- tls2.c tls_o.c tls_g.c tls_m.c \ ++ tls2.c tls_o.c tls_g.c tls_m.c tls_mc.c tls_mc_ossl.c \ + turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ + assertion.c deref.c ldif.c fetch.c + +@@ -39,7 +39,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ + request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ + init.lo options.lo print.lo string.lo util-int.lo schema.lo \ + charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ +- tls2.lo tls_o.lo tls_g.lo tls_m.lo \ ++ tls2.lo tls_o.lo tls_g.lo tls_m.lo tls_mc.lo tls_mc_ossl.lo \ + turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ + assertion.lo deref.lo ldif.lo fetch.lo + +diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c +index 39ad7ce7c..689144ca3 100644 +--- a/libraries/libldap/init.c ++++ b/libraries/libldap/init.c +@@ -137,7 +137,9 @@ static const struct ol_attribute { + #ifdef HAVE_GNUTLS + {0, ATTR_TLS, "TLS_CRLFILE", NULL, LDAP_OPT_X_TLS_CRLFILE}, + #endif +- ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ {0, ATTR_TLS, "TLS_MOZNSS_COMPATIBILITY", NULL, LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY}, ++#endif + #endif + + {0, ATTR_NONE, NULL, NULL, 0} +@@ -582,6 +584,9 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl + gopts->ldo_tls_connect_cb = NULL; + gopts->ldo_tls_connect_arg = NULL; + gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND; ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ gopts->ldo_tls_moznss_compatibility = LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_ENABLED; ++#endif + #endif + gopts->ldo_keepalive_probes = 0; + gopts->ldo_keepalive_interval = 0; +diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h +index bcc58f367..d42b82627 100644 +--- a/libraries/libldap/ldap-int.h ++++ b/libraries/libldap/ldap-int.h +@@ -260,7 +260,8 @@ struct ldapoptions { + int ldo_tls_require_cert; + int ldo_tls_impl; + int ldo_tls_crlcheck; +-#define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0},0,0,0,0 ++ int ldo_tls_moznss_compatibility; ++#define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0},0,0,0,0,0 + #else + #define LDAP_LDO_TLS_NULLARG + #endif +diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c +index 8f842278a..878e1a0a8 100644 +--- a/libraries/libldap/tls2.c ++++ b/libraries/libldap/tls2.c +@@ -37,6 +37,8 @@ + + #include "ldap-tls.h" + ++#include "tls_mc.h" ++ + static tls_impl *tls_imp = &ldap_int_tls_impl; + #define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ + (void *)tls_imp->ti_sbio ) +@@ -96,6 +98,7 @@ tls_ctx_ref( tls_ctx *ctx ) + * an extra mutex for the default ctx. + */ + static ldap_pvt_thread_mutex_t tls_def_ctx_mutex; ++ldap_pvt_thread_mutex_t tlsmc_mutex; + #endif + + void +@@ -161,6 +164,7 @@ tls_init(tls_impl *impl ) + if ( !tls_initialized++ ) { + #ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex ); ++ ldap_pvt_thread_mutex_init( &tlsmc_mutex ); + #endif + } + +@@ -196,6 +200,27 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) + + tls_init( ti ); + ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ if ( LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_ENABLED == lo->ldo_tls_moznss_compatibility ) { ++ Debug( LDAP_DEBUG_ANY, ++ "TLSMC: MozNSS compatibility interception begins.\n", ++ 0, 0, 0 ); ++ if ( 0 == tlsmc_intercept_initialization( lo, is_server ) ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "TLSMC: ERROR: MozNSS compatibility layer failed.\n", ++ 0, 0, 0 ); ++ } ++ lts = lo->ldo_tls_info; ++ Debug( LDAP_DEBUG_ANY, ++ "TLSMC: MozNSS compatibility interception ends.\n", ++ 0, 0, 0 ); ++ } else { ++ Debug( LDAP_DEBUG_TRACE, ++ "TLS: MozNSS compatibility layer disabled.\n", ++ 0, 0, 0 ); ++ } ++#endif ++ + if ( is_server && !lts.lt_certfile && !lts.lt_keyfile && + !lts.lt_cacertfile && !lts.lt_cacertdir ) { + /* minimum configuration not provided */ +@@ -573,6 +598,21 @@ ldap_int_tls_config( LDAP *ld, int option, const char *arg ) + } + return -1; + #endif ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ case LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY: ++ i = -1; ++ if ( (strcasecmp( arg, "yes" ) == 0) || ++ (strcasecmp( arg, "true" ) == 0) || ++ (strcasecmp( arg, "on" ) == 0) ) { ++ i = LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_ENABLED; ++ } ++ if ( (strcasecmp( arg, "no" ) == 0) || ++ (strcasecmp( arg, "false" ) == 0) || ++ (strcasecmp( arg, "off" ) == 0) ) { ++ i = LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_DISABLED; ++ } ++ return ldap_pvt_tls_set_option( ld, option, &i ); ++#endif + } + return -1; + } +@@ -675,6 +715,9 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) + case LDAP_OPT_X_TLS_CONNECT_ARG: + *(void **)arg = lo->ldo_tls_connect_arg; + break; ++ case LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY: ++ *(int *)arg = lo->ldo_tls_moznss_compatibility; ++ break; + default: + return -1; + } +@@ -802,6 +845,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) + ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); + lo->ldo_tls_ctx = NULL; + return ldap_int_tls_init_ctx( lo, *(int *)arg ); ++ case LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY: ++ if ( !arg ) return -1; ++ lo->ldo_tls_moznss_compatibility = *(int *)arg; ++ break; + default: + return -1; + } +diff --git a/libraries/libldap/tls_mc.c b/libraries/libldap/tls_mc.c +new file mode 100644 +index 000000000..8383cb4ec +--- /dev/null ++++ b/libraries/libldap/tls_mc.c +@@ -0,0 +1,1323 @@ ++#include "portable.h" ++ ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ldap-int.h" ++#include "ldap-tls.h" ++#include "ldap_pvt_thread.h" ++ ++#include "tls_mc.h" ++#include "tls_mc_ossl.h" ++ ++#define TLSMC_CHECKSUM_LEN 32 ++ ++#define TLSMC_CACERTS_DIR_NAME "cacerts" ++#define TLSMC_CERT_FILE_NAME "cert.pem" ++#define TLSMC_KEY_FILE_NAME "key.pem" ++#define TLSMC_README_FILE_NAME "README" ++ ++#define TLSM_CERTDB_DESC "ldap" ++#define DEFAULT_TOKEN_NAME "default" ++ ++#define TLSMC_IS_INPLACE 1 ++#define TLSMC_IS_TEMPORARY 2 ++ ++#define DONOTEDIT \ ++ "This file is auto-generated by MOZNSS Compatibility Layer of OpenLDAP software.\n" \ ++ "This layer is not a part of upstream distributed OpenLDAP software.\n" \ ++ "Please, file any related bugs with your GNU/Linux distribution.\n" \ ++ "Do not edit directly. Rather, change your configuration to use OpenSSL-style TLS options, so that this does not need to be generated anymore.\n" \ ++ "Please, refer to man (5) of slapd.conf, slapd-config, and ldap.conf for more information." ++#define PEM_CERT_HEADER "-----BEGIN CERTIFICATE-----" ++#define PEM_CERT_FOOTER "-----END CERTIFICATE-----" ++#define PEM_KEY_HEADER "-----BEGIN PRIVATE KEY-----" ++#define PEM_KEY_FOOTER "-----END PRIVATE KEY-----" ++#define README_HEADER "Contents of this file are hashed and used as a part of a name of the parent directory.\n" ++ ++#ifdef LDAP_R_COMPILE ++ldap_pvt_thread_mutex_t tlsmc_mutex; ++#endif ++/*******************************************************************/ ++ ++ ++char * ++tlsmc_path2name( char *path ) ++{ ++ if ( NULL == path ) return NULL; ++ char *last_slash = strrchr( path, '/' ); ++ if ( NULL == last_slash ) ++ return path; ++ else ++ return last_slash + 1; ++} ++ ++ ++int ++tlsmc_write_file( char *filename, char *buf, mode_t final_mode ) ++{ ++ int rv = 0; ++ int fd = -1; ++ if ( 0 > ( fd = open( filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR ) ) ) { ++ perror("IO ERROR: could not open file"); ++ goto bail; ++ } ++ if ( -1 >= write( fd, buf, strlen(buf) ) ) { ++ perror("IO ERROR: could not write file"); ++ goto bail; ++ } ++ if ( -1 >= fchmod( fd, final_mode ) ) { ++ perror("IO ERROR: could not set file mode"); ++ goto bail; ++ } ++ if ( 0 > close( fd ) ) { ++ perror("IO ERROR: could not close file"); ++ goto bail; ++ } ++ rv = 1; ++bail: ++ if ( fd > -1 ) close( fd ); ++ return rv; ++} ++ ++ ++void ++tlsmc_debug_nspr_msg() ++{ ++ int _errno = errno; ++ PRInt32 oserror = PR_GetOSError(); ++ char *errno_str = strerror(_errno); ++ char *errstr = PR_Malloc( PR_GetErrorTextLength() + 1 ); ++ PR_GetErrorText( errstr ); ++ Debug( LDAP_DEBUG_ANY, ++ "... NSPR error %d:`%s'\n", ++ PR_GetError(), errstr, 0 ); ++ Debug( LDAP_DEBUG_ANY, ++ "... NSPR OS-error %d, errno %d:%s\n", ++ oserror, _errno, errno_str ); ++ PR_Free( errstr ); ++} ++ ++/* BORROWED FROM tls_m.c */ ++static void ++tlsmc_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) ++{ ++ char sep = PR_GetDirectorySeparator(); ++ char *ptr = NULL; ++ struct PRFileInfo prfi; ++ PRStatus prc; ++ ++ *realcertdir = (char *)certdir; /* default is the one passed in */ ++ if ( !certdir ) return; ++ ++ prc = PR_GetFileInfo( certdir, &prfi ); ++ /* if certdir exists (file or directory) then it cannot specify a prefix */ ++ if ( prc == PR_SUCCESS ) { ++ /* and drop potential last '/' */ ++ ptr = strrchr( *realcertdir, sep ); ++ if ( ptr && (! *(ptr+1) ) ) { ++ *ptr = '\0'; ++ } ++ return; ++ } ++ ++ /* if certdir was given, and there is a '/' in certdir, see if there ++ is anything after the last '/' - if so, assume it is the prefix */ ++ if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) { ++ *realcertdir = PL_strndup( certdir, ptr-certdir ); ++ *prefix = PL_strdup( ptr+1 ); ++ } ++ ++ return; ++} ++ ++ ++static char * ++tlsmc_get_pin_from_file(const char *token_name, char *filename) ++{ ++ char *pwdstr = NULL; ++ char *contents = NULL; ++ char *lasts = NULL; ++ char *line = NULL; ++ char *candidate = NULL; ++ PRFileInfo file_info; ++ PRFileDesc *pwd_fileptr = NULL; ++ pwd_fileptr = PR_Open( filename, PR_RDONLY, 00400 ); ++ ++ /* open the password file */ ++ if ( !pwd_fileptr ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_get_pin_from_file: could not open security pin file %s - error %d:%s.\n", ++ filename, errcode, ++ PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ goto done; ++ } ++ ++ /* get the file size */ ++ if ( PR_SUCCESS != PR_GetFileInfo( filename, &file_info ) ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_get_pin_from_file: could not get file info from pin file %s - error %d:%s.\n", ++ filename, errcode, ++ PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ goto done; ++ } ++ ++ /* create a buffer to hold the file contents */ ++ if ( !( contents = PR_CALLOC( file_info.size + 1 ) ) ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_get_pin_from_file: could not alloc a buffer for contents of pin file %s - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ goto done; ++ } ++ ++ /* read file into the buffer */ ++ if( PR_Read( pwd_fileptr, contents, file_info.size ) <= 0 ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_get_pin_from_file: could not read the file contents from pin file %s - error %d:%s.\n", ++ filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ goto done; ++ } ++ ++ /* format is [tokenname:]password EOL [tokenname:]password EOL ... */ ++ /* if you want to use a password containing a colon character, use ++ the special tokenname "default" */ ++ for ( line = PL_strtok_r( contents, "\r\n", &lasts ); line; ++ line = PL_strtok_r( NULL, "\r\n", &lasts ) ) { ++ char *colon; ++ ++ if ( !*line ) { ++ continue; /* skip blank lines */ ++ } ++ colon = PL_strchr( line, ':' ); ++ if ( colon ) { ++ if ( *(colon + 1) && token_name && ++ !PL_strncmp( token_name, line, colon-line ) ) { ++ candidate = colon + 1; /* found a definite match */ ++ break; ++ } else if ( !PL_strncmp( DEFAULT_TOKEN_NAME, line, colon-line ) ) { ++ candidate = colon + 1; /* found possible match */ ++ } ++ } else { /* no token name */ ++ candidate = line; ++ } ++ } ++done: ++ if ( pwd_fileptr ) { ++ PR_Close( pwd_fileptr ); ++ } ++ if ( candidate ) { ++ pwdstr = PL_strdup( candidate ); ++ } ++ PL_strfree( contents ); ++ ++ return pwdstr; ++} ++ ++ ++/* ++ * Turn the echoing off on a tty. ++ */ ++static void ++echoOff(int fd) ++{ ++ if ( isatty( fd ) ) { ++ struct termios tio; ++ tcgetattr( fd, &tio ); ++ tio.c_lflag &= ~ECHO; ++ tcsetattr( fd, TCSAFLUSH, &tio ); ++ } ++} ++ ++/* ++ * Turn the echoing on on a tty. ++ */ ++static void ++echoOn(int fd) ++{ ++ if ( isatty( fd ) ) { ++ struct termios tio; ++ tcgetattr( fd, &tio ); ++ tio.c_lflag |= ECHO; ++ tcsetattr( fd, TCSAFLUSH, &tio ); ++ tcsetattr( fd, TCSAFLUSH, &tio ); ++ } ++} ++ ++ ++/* Borrowed from tlsm_get_pin() */ ++char * ++tlsmc_get_pin( PK11SlotInfo *slot, PRBool retry, void * filename) ++{ ++ char *token_name = NULL; ++ char *pwdstr = NULL; ++ ++ token_name = PK11_GetTokenName( slot ); ++ /* Try to get the passwords from the password file if it exists. ++ * THIS IS UNSAFE and is provided for convenience only. Without this ++ * capability the server would have to be started in foreground mode ++ * if using an encrypted key. ++ */ ++ if ( filename ) { ++ pwdstr = tlsmc_get_pin_from_file( token_name, (char *)filename ); ++ if ( retry && pwdstr != NULL ) ++ return NULL; ++ } ++ if ( !pwdstr ) { ++ int infd = PR_FileDesc2NativeHandle( PR_STDIN ); ++ int isTTY = isatty( infd ); ++ unsigned char phrase[200]; ++ /* Prompt for password */ ++ if ( isTTY ) { ++ fprintf( stdout, ++ "Please enter pin, password, or pass phrase for security token '%s': ", ++ token_name ? token_name : DEFAULT_TOKEN_NAME ); ++ echoOff( infd ); ++ } ++ fgets( (char*)phrase, sizeof(phrase), stdin ); ++ if ( isTTY ) { ++ fprintf( stdout, "\n" ); ++ echoOn( infd ); ++ } ++ /* stomp on newline */ ++ phrase[strlen((char*)phrase)-1] = 0; ++ ++ pwdstr = PL_strdup( (char*)phrase ); ++ } ++ ++ return pwdstr; ++} ++ ++ ++int ++tlsmc_hash( unsigned char **dest, char *src ) ++{ ++ int rv = 0; ++ unsigned char fp[SHA256_LENGTH]; ++ SECItem fpItem; ++ ++ if ( SECSuccess != ( rv = PK11_HashBuf( SEC_OID_SHA256, fp, src, strlen(src) ) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_hash: could not hash a buffer", ++ NULL, NULL, NULL ); ++ goto bail; ++ } ++ fpItem.data = fp; ++ fpItem.len = SHA256_LENGTH; ++ if ( NULL == ( *dest = CERT_Hexify( &fpItem, 0 ) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_hash: could not hexify the hash", ++ NULL, NULL, NULL ); ++ goto bail; ++ } ++ ++ rv = 1; ++bail: ++ return rv; ++} ++ ++ ++/* BORROWED FROM tls_m.c */ ++static PK11SlotInfo * ++tlsmc_init_open_certdb( const char *nssdb_dir, const char *prefix ) ++{ ++ PK11SlotInfo *slot = NULL; ++ char *config = NULL; ++ ++ config = PR_smprintf( "configDir='%s' tokenDescription='%s' " ++ "certPrefix='%s' keyPrefix='%s' flags=readOnly", ++ nssdb_dir, TLSM_CERTDB_DESC, ++ prefix, prefix ); ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_init_open_certdb: INFO: certdb config: `%s`.\n", ++ config, 0, 0 ); ++ ++ slot = SECMOD_OpenUserDB( config ); ++ if ( !slot ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_init_open_certdb: ERROR: cannot open certdb `%s`, error `%d:%s`.\n", ++ nssdb_dir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); ++ } ++ ++ if ( config ) PR_smprintf_free( config ); ++ ++ return slot; ++} ++ ++ ++/* Borrowed from tlsm_deferred_init */ ++int ++tlsmc_open_nssdb( char *ld_cacertdir, NSSInitContext **out_initctx, char **out_nssdb_dir, char **out_nssdb_prefix ) ++{ ++#define SECURITYDIRS_COUNT 3 ++ int rc = 0; ++ PRErrorCode errcode = 1; ++ ++ /* restart secmod modules */ ++#ifdef HAVE_SECMOD_RESTARTMODULES ++ /* NSS enforces the pkcs11 requirement that modules should be unloaded after ++ a fork() - since there is no portable way to determine if NSS has been ++ already initialized in a parent process, we just call SECMOD_RestartModules ++ with force == FALSE - if the module has been unloaded due to a fork, it will ++ be reloaded, otherwise, it is a no-op */ ++ if ( 0 == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) { ++ errcode = PORT_GetError(); ++ if ( errcode != SEC_ERROR_NOT_INITIALIZED ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_open_nssdb: WARN: could not restart the security modules: %d:%s.\n", ++ errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); ++ } else { ++ errcode = 1; ++ } ++ } ++#endif ++ ++ ++ /* context and certdb */ ++ char *dir_moznss = PR_GetEnv( "MOZNSS_DIR" ); ++ char *dir_default_moznss = PR_GetEnv( "DEFAULT_MOZNSS_DIR" ); ++ const char *securitydirs[SECURITYDIRS_COUNT] = { dir_moznss, ld_cacertdir, dir_default_moznss }; ++ int done = 0; ++ int ii = 0; ++ for ( ii = 0; !done && ( ii < SECURITYDIRS_COUNT ); ++ii ) { ++ // get certdb prefix ++ const char *securitydir = securitydirs[ii]; ++ char *realcertdir = NULL; ++ const char *defprefix = ""; ++ char *prefix = (char *)defprefix; ++ if ( securitydir == NULL ) continue; ++ tlsmc_get_certdb_prefix( securitydir, &realcertdir, &prefix ); //FIXME ++ *out_nssdb_dir = strdup( realcertdir ); ++ *out_nssdb_prefix = strdup( prefix ); ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_open_nssdb: INFO: trying to initialize moznss using security dir `%s` prefix `%s`.\n", ++ realcertdir, prefix, NULL); ++ ++ // init context ++ NSSInitContext *initctx = NULL; ++ NSSInitParameters initparams; ++ memset( &initparams, 0, sizeof( initparams ) ); ++ initparams.length = sizeof( initparams ); ++ ++ initctx = NSS_InitContext( realcertdir, ++ prefix, ++ prefix, ++ SECMOD_DB, ++ &initparams, ++ NSS_INIT_READONLY // | NSS_INIT_NOCERTDB ++ ); ++ rc = initctx ? 1 : 0; ++ ++ *out_initctx = initctx; ++ ++ if ( rc != 1 ) { ++ errcode = PORT_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_open_nssdb: WARN: could not initialize MozNSS context - error %d.\n", ++ errcode, 0, 0 ); ++ } else { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_open_nssdb: INFO: initialized MozNSS context.\n", ++ 0, 0, 0 ); ++ errcode = 0; ++ done = 1; ++ } ++ } ++ ++ PR_Free( dir_moznss ); ++ PR_Free( dir_default_moznss ); ++ ++ PK11_SetPasswordFunc( tlsmc_get_pin ); ++ ++ if ( done && (errcode == 0) && out_initctx ) { ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++ ++static int ++tlsmc_is_sql_nssdb( const char *ld_cacertdir ) ++{ ++ if ( 0 == strncmp( "sql:", ld_cacertdir, 4 ) ) { ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++ ++int ++tlsmc_filestamp( char **filestamp, char *path ) ++{ ++ int rv = 0; ++ struct stat attr; ++ char stime[20]; ++ ++ if ( 0 != stat( path, &attr ) ) { ++ perror("IO ERROR: could not stat file"); ++ goto bail; ++ } ++ if ( 0 == strftime(stime, sizeof(stime), "%FT%T", localtime(&attr.st_mtime)) ) { ++ perror("IO ERROR: could not format mtime"); ++ goto bail; ++ } ++ ++ *filestamp = PR_smprintf("mtime %s.%d, size %lld", ++ stime, attr.st_mtim.tv_nsec, (long long) attr.st_size); ++ ++ rv = 1; ++bail: ++ return rv; ++} ++ ++ ++char * ++tlsmc_compute_checksum( char *nssdb_dir, char *nssdb_prefix, ++ char *ld_cacertdir, char *ld_cert, char *ld_key, ++ char **out_data) ++{ ++ int rv = 0; ++ char *data = NULL; ++ ++ /* gather data */ ++ data = PR_sprintf_append( data, ++ DONOTEDIT "\n" ++ README_HEADER "\n" ++ "PARAMETERS:\n" ++ "nssdb_dir: %s\n" ++ "nssdb_prefix: %s\n" ++ "ld_cacertdir: %s\n" ++ "ld_cert: %s\n" ++ "ld_key: %s\n" ++ "euid: %d\n\n" ++ "FILES:\n", ++ nssdb_dir, nssdb_prefix, ld_cacertdir, ld_cert, ld_key, geteuid() ); ++ ++ char *bdb_files[] = { "cert8.db", "key3.db", "secmod.db", NULL }; ++ char *sql_files[] = { "cert9.db", "key4.db", "secmod.db", NULL }; ++ char **files = ( 1 == tlsmc_is_sql_nssdb( ld_cacertdir ) ) ? sql_files : bdb_files; // FIXME we should do all files as default prefix may (and will) change and thus change the semantics of the ld_cacertdir ++ char *file = *files; ++ while ( NULL != ( file = *(files++) ) ) { ++ char *filestamp = NULL; ++ char *path = NULL; ++ path = PR_smprintf( "%s/%s%s", nssdb_dir, nssdb_prefix, file ); ++ if ( 0 == tlsmc_filestamp( &filestamp, path ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_compute_checksum: ERROR: could not stat file `%s'.\n", ++ path, 0, 0 ); ++ rv = -1; ++ } else { ++ data = PR_sprintf_append( data, "%s: %s\n", file, filestamp ); ++ } ++ bail_one: ++ if ( filestamp ) PR_smprintf_free( filestamp ); ++ if ( path ) PR_smprintf_free( path ); ++ if ( -1 == rv ) goto bail; ++ } ++ ++ /* compute data checksum */ ++ unsigned char *checksum = NULL; ++ if ( 1 != tlsmc_hash( &checksum, data ) ) { ++ checksum = NULL; ++ goto bail; ++ } ++ ++ /* possibly supply data */ ++ if ( out_data ) { ++ *out_data = strdup( data ); ++ } ++ ++ /* return checksum */ ++bail: ++ if ( data ) PR_smprintf_free( data ); ++ return checksum; ++} ++ ++ ++int ++tlsmc_prepare_dir( char *dir ) ++{ ++ int rv = 0; ++ PRFileInfo info; ++ PRStatus prv; ++ char *cacerts_dir = NULL; ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_prepare_dir: INFO: preparing PEM directory `%s'.\n", ++ dir, 0, 0 ); ++ ++ if ( 0 != mkdir( dir, S_IRWXU /* u+rwx */ ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_prepare_dir: WARN: cound not create the PEM directory.\n", ++ 0, 0, 0 ); ++ perror( "tlsmc_prepare_dir: WARN: cound not create the PEM directory" ); ++ rv = 0; ++ goto bail; ++ } ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_prepare_dir: INFO: creating a subdirectory `%s'.\n", ++ TLSMC_CACERTS_DIR_NAME, 0, 0 ); ++ cacerts_dir = PR_smprintf( "%s/%s", dir, TLSMC_CACERTS_DIR_NAME ); ++ if ( 0 != mkdir( cacerts_dir, S_IRWXU /* u+rwx */ ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_prepare_dir: WARN: cound not create the subdirectory.\n", ++ 0, 0, 0 ); ++ perror( "tlsmc_prepare_dir: WARN: cound not create the subdirectory" ); ++ rv = 0; ++ goto bail; ++ } ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_prepare_dir: INFO: successfully created PEM directory structure.\n", ++ TLSMC_CACERTS_DIR_NAME, 0, 0 ); ++ rv = 1; ++ ++bail: ++ if ( cacerts_dir ) PR_smprintf_free( cacerts_dir ); ++ return rv; ++} ++ ++int ++tlsmc_extract_cert_to_file(CERTCertDBHandle *certdb_handle, CERTCertificate *cert, char *file_path) ++{ ++ int rv = 0; ++ SECItem data; ++ char *b64 = NULL; ++ char *output = NULL; ++ ++ if ( ! cert ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_to_file: ERROR: cert empty.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ data.data = cert->derCert.data; ++ data.len = cert->derCert.len; ++ b64 = BTOA_DataToAscii(data.data, data.len); ++ if ( ! b64 ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_to_file: ERROR: could not base64 encode.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ output = PR_smprintf( DONOTEDIT "\n\n" ++ "NSS nickname: %s\n" ++ "Issuer: %s\n" ++ "Subject: %s\n" ++ PEM_CERT_HEADER "\n" ++ "%s\n" ++ PEM_CERT_FOOTER "\n", ++ cert->nickname, ++ cert->issuerName, ++ cert->subjectName, ++ b64 ); ++ ++ if ( 0 == tlsmc_write_file( file_path, output, S_IRUSR ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_to_file: ERROR: could not write certificate.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ rv = 1; ++bail: ++ if ( output ) PR_smprintf_free( output ); ++ if ( b64 ) PORT_Free( b64 ); ++ return rv; ++} ++ ++ ++ ++/* borrowed from 389-ds-base, ssl.c, DecryptKey */ ++int ++tlsmc_decrypt_key(SECKEYEncryptedPrivateKeyInfo *epki, ++ SECOidTag algTag, ++ SECItem *pwitem, ++ void *pin_arg, ++ SECItem *derPKI) ++{ ++ SECItem *cryptoParam = NULL; ++ PK11SymKey *symKey = NULL; ++ PK11Context *ctx = NULL; ++ int rv = 0; ++ ++ if (!pwitem) return rv; ++ ++ do { ++ SECAlgorithmID algid = epki->algorithm; ++ CK_MECHANISM_TYPE cryptoMechType; ++ CK_ATTRIBUTE_TYPE operation = CKA_DECRYPT; ++ PK11SlotInfo *slot = NULL; ++ ++ cryptoMechType = PK11_GetPBECryptoMechanism(&algid, &cryptoParam, pwitem); ++ if (cryptoMechType == CKM_INVALID_MECHANISM) { ++ goto bail; ++ } ++ ++ if ( NULL == ( slot = PK11_GetBestSlot(cryptoMechType, NULL) ) ) { ++ goto bail; ++ } ++ ++ if ( NULL == ( symKey = PK11_PBEKeyGen(slot, &algid, pwitem, PR_FALSE, pin_arg) ) ) { ++ rv = -1; ++ goto bail_one; ++ } ++ ++ if ( NULL == ( ctx = PK11_CreateContextBySymKey( ++ cryptoMechType, operation, symKey, cryptoParam) ) ) { ++ rv = -1; ++ goto bail_one; ++ } ++ ++ if ( SECSuccess != PK11_CipherOp(ctx, ++ derPKI->data, /* out */ ++ (int *)(&derPKI->len), /* out len */ ++ (int)epki->encryptedData.len, /* max out */ ++ epki->encryptedData.data, /* in */ ++ (int)epki->encryptedData.len /* in len */ ) ) { ++ rv = -1; ++ goto bail_one; ++ } ++ ++ if ( derPKI->len != epki->encryptedData.len ) goto bail_one; ++ if ( SECSuccess != PK11_Finalize(ctx) ) goto bail_one; ++ bail_one: ++ if (slot) PK11_FreeSlot(slot); ++ } while (0); ++ ++ rv = ((rv == 0) ? 1 : 0); ++bail: ++ if (symKey) PK11_FreeSymKey(symKey); ++ if (cryptoParam) { ++ SECITEM_ZfreeItem(cryptoParam, PR_TRUE); ++ cryptoParam = NULL; ++ } ++ if (ctx) PK11_DestroyContext(ctx, PR_TRUE); ++ ++ return rv; ++} ++ ++ ++ ++int ++tlsmc_extract_key_of_cert_to_file(CERTCertificate *cert, ++ char *pin_filename, ++ char *filename) ++{ ++ int rv = 0; ++ SECKEYPrivateKey *key = NULL; ++ SECItem pwitem; ++ SECKEYEncryptedPrivateKeyInfo *epki = NULL; ++ PLArenaPool *arenaForPKI = NULL; ++ SECItem clearKeyDER; ++ char *b64 = NULL; ++ char *output = NULL; ++ //SECItem *data = PK11_ExportDERPrivateKeyInfo(key, (void *)pin_filename); // FIXME NULL? // probably won't work ++ ++ // establish password ++ pwitem.data = "secretpw"; // FIXME use pin_filename ++ pwitem.len = strlen(pwitem.data); ++ pwitem.type = siBuffer; ++ ++ // get key ++ if ( NULL == ( key = PK11_FindKeyByAnyCert(cert, (void *)pin_filename) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: PK11_FindKeyByAnyCert failed.\n", ++ 0,0,0); ++ goto bail; ++ } ++ ++ // get key info ++ if ( NULL == ( epki = PK11_ExportEncryptedPrivKeyInfo( ++ NULL, SEC_OID_DES_EDE3_CBC, &pwitem, key, 1000, (void *)pin_filename) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: PK11_ExportEncryptedPrivKeyInfo returned NULL.\n", ++ 0,0,0); ++ goto bail; ++ } ++ ++ // get clear DER ++ if ( NULL == ( arenaForPKI = PORT_NewArena(2048) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: PORT_NewArena failed.\n", ++ 0,0,0); ++ goto bail; ++ } ++ ++ clearKeyDER.data = PORT_ArenaAlloc(arenaForPKI, epki->encryptedData.len); ++ clearKeyDER.len = epki->encryptedData.len; ++ clearKeyDER.type = siBuffer; ++ ++ if ( 0 == tlsmc_decrypt_key(epki, SEC_OID_DES_EDE3_CBC, &pwitem, ++ (void *)pin_filename, &clearKeyDER) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: could not decrypt the key.\n", ++ 0,0,0); ++ goto bail; ++ } ++ ++ // base64 encode ++ if ( NULL == ( b64 = BTOA_ConvertItemToAscii(&clearKeyDER) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: could not base64 encode.\n", ++ 0,0,0); ++ goto bail; ++ } ++ ++ // print out ++ output = PR_smprintf( DONOTEDIT "\n" ++ PEM_KEY_HEADER "\n" ++ "%s\n" ++ PEM_KEY_FOOTER "\n", ++ b64 ); ++ ++ if ( 0 == tlsmc_write_file( filename, output, S_IRUSR ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_key_of_cert_to_file: ERROR: could not write PK.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ rv = 1; ++ ++bail: ++ if (b64) PORT_Free(b64); ++ if (arenaForPKI) PORT_FreeArena(arenaForPKI, PR_FALSE); ++ if (epki) SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); ++ if (key) SECKEY_DestroyPrivateKey(key); ++ return rv; ++} ++ ++//TODO drop? ++int ++tlsmc_extract_cert_key_pair(char *nickname, char *pin_filename, char *dir_name) ++{ ++ int rv = 0; ++ int fd = -1; ++ CERTCertDBHandle *certHandle = NULL; ++ CERTCertificate *cert = NULL; ++ char *cert_file_path = NULL; ++ char *key_file_path = NULL; ++ ++ if ( NULL == ( certHandle = CERT_GetDefaultCertDB() ) ) { ++ // FIXME see same in tlsmc_extract_cacerts() ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_key_pair: ERROR: could not get certificate handle.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ if ( NULL == ( cert = PK11_FindCertFromNickname(nickname, NULL) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_key_pair: ERROR: could not find certificate with nickname `%s'.\n", ++ nickname, 0, 0 ); ++ goto bail; ++ } ++ ++ /* cert */ ++ cert_file_path = PR_smprintf( "%s/cert.pem", dir_name ); ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cert_key_pair: INFO: extracting certificate `%s' to file `%s'.\n", ++ nickname, cert_file_path, 0 ); ++ if ( 0 == tlsmc_extract_cert_to_file(certHandle, cert, cert_file_path) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_key_pair: ERROR: could not extract certificate.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ /* key */ ++ key_file_path = PR_smprintf( "%s/key.pem", dir_name ); ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cert_key_pair: INFO: extracting associated PK to file `%s'.\n", ++ key_file_path, 0, 0 ); ++ if ( 0 == tlsmc_extract_key_of_cert_to_file( cert, pin_filename, key_file_path ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cert_key_pair: ERROR: could not extract PK.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ rv = 1; ++ ++bail: ++ if (key_file_path) PR_smprintf_free(key_file_path); ++ if (cert_file_path) PR_smprintf_free(cert_file_path); ++ if (cert) CERT_DestroyCertificate(cert); ++ return rv; ++} ++ ++ ++/* Adopted from 389DS. */ ++static int ++tlsmc_list_certs(CERTCertDBHandle *handle, ++ CERTCertificate *cert, ++ PK11SlotInfo *slot, ++ PRFileDesc *outfile, ++ void *pwarg) ++{ ++ SECItem data; ++ int rv = 0; ++ CERTCertList *certs; ++ CERTCertListNode *node; ++ CERTCertificate *the_cert = NULL; ++ char *name = NULL; ++ ++ if (!cert) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_list_certs: WARN: no cert given.\n", ++ 0, 0, 0 ); ++ return rv; ++ } ++ name = cert->nickname; ++ ++ if (!name) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_list_certs: WARN: no cert nickname.\n", ++ 0, 0, 0 ); ++ return rv; ++ } ++ the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); ++ if (!the_cert) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_list_certs: WARN: could not find cert: %s.\n", ++ name, 0, 0 ); ++ return 0; ++ } ++ ++ PR_fprintf(outfile, "%s\n", DONOTEDIT); ++ /* Here, we have one cert with the desired nickname or email ++ * address. Now, we will attempt to get a list of ALL certs ++ * with the same subject name as the cert we have. That list ++ * should contain, at a minimum, the one cert we have already found. ++ * If the list of certs is empty (NULL), the libraries have failed. ++ */ ++ certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject, ++ PR_Now(), PR_FALSE); ++ CERT_DestroyCertificate(the_cert); ++ if (!certs) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_list_certs: WARN: problem printing certificates.\n", ++ 0, 0, 0 ); ++ return 0; ++ } ++ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); node = CERT_LIST_NEXT(node)) { ++ the_cert = node->cert; ++ PR_fprintf(outfile, "Issuer: %s\n", the_cert->issuerName); ++ PR_fprintf(outfile, "Subject: %s\n", the_cert->subjectName); ++ /* now get the subjectList that matches this cert */ ++ data.data = the_cert->derCert.data; ++ data.len = the_cert->derCert.len; ++ PR_fprintf(outfile, "\n%s\n%s\n%s\n", ++ PEM_CERT_HEADER, ++ BTOA_DataToAscii(data.data, data.len), ++ PEM_CERT_FOOTER); ++ rv = 1; ++ } ++ if (certs) { ++ CERT_DestroyCertList(certs); ++ } ++ if (rv) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_list_certs: WARN: problem printing certificate nicknames.\n", ++ 0, 0, 0 ); ++ return 0; ++ } ++ ++ return rv; ++} ++ ++static char* ++tlsmc_extract_key() ++{ ++ return NULL; ++} ++ ++/* Adopted from 389DS. */ ++static int ++tlsmc_extract_cert(char *token_colon_name, char *filename) ++{ ++ CERTCertListNode *node; ++ CERTCertList *list = PK11_ListCerts(PK11CertListAll, NULL); ++ for (node = CERT_LIST_HEAD(list); ++ !CERT_LIST_END(node, list); ++ node = CERT_LIST_NEXT(node)) { ++ CERTCertificate *cert = node->cert; ++ CERTCertTrust trust; ++ } ++ return 0; ++} ++ ++int ++tlsmc_extract_cacerts( char *dir_name ) ++{ ++ int rv = 0; ++ CERTCertDBHandle *certHandle = NULL; ++ CERTCertListNode *node = NULL; ++ CERTCertList *list = NULL; ++ char *cacerts_dir = NULL; ++ int cert_cnt = 0; ++ ++ cacerts_dir = PR_smprintf( "%s/" TLSMC_CACERTS_DIR_NAME, dir_name ); ++ ++ certHandle = CERT_GetDefaultCertDB(); // FIXME maybe we should really use certdb_slot? ++ if ( ! certHandle ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cacerts: could not get certificate database handle.\n", ++ 0, 0, 0); ++ goto bail; ++ } ++ ++ list = PK11_ListCerts(PK11CertListAll, NULL); ++ if ( ! list ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cacerts: could not get list of certificates.\n", ++ 0, 0, 0); ++ goto bail; ++ } ++ for ( node = CERT_LIST_HEAD(list); ++ !CERT_LIST_END(node, list); ++ node = CERT_LIST_NEXT(node)) { ++ ++ CERTCertificate *cert = NULL; ++ CERTCertTrust trust; ++ char *cert_file_path = NULL; ++ int is_ca = 0; ++ ++ cert = node->cert; ++ if ( SECFailure == CERT_GetCertTrust( cert, &trust ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cacerts: ERROR: could not get trust flags of certificate nick=`%s'.\n", ++ cert->nickname, 0, 0); ++ goto bail; ++ } ++ if (trust.sslFlags & ++ (CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA)) { ++ is_ca = 1; ++ } ++ ++ Debug(LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cacerts: INFO: found cert nick=`%s'%s.\n", ++ cert->nickname, is_ca ? ", a trusted CA" : ", _not_ a trusted CA, skipping", 0); ++ if ( ! is_ca ) continue; ++ ++ cert_file_path = PR_smprintf( "%s/cert%d.pem", cacerts_dir, cert_cnt ); ++ cert_cnt++; ++ Debug(LDAP_DEBUG_TRACE, ++ "tlsmc_extract_cacerts: INFO: extracting cert nick=`%s' to file `%s'.\n", ++ cert->nickname, cert_file_path, 0); ++ if ( 0 == tlsmc_extract_cert_to_file( certHandle, cert, cert_file_path ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cacerts: ERROR: could not extract the certificate.\n", ++ 0, 0, 0); ++ goto bail_one; ++ } ++ if ( 0 == tlsmc_cert_create_hash_symlink( cert_file_path, cacerts_dir ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_cacerts: ERROR: could not rehash the certificate.\n", ++ 0, 0, 0); ++ goto bail_one; ++ } ++ if ( cert_file_path ) PR_smprintf_free( cert_file_path ); ++ continue; ++ bail_one: ++ if ( cert_file_path ) PR_smprintf_free( cert_file_path ); ++ goto bail; ++ } ++ ++ rv = 1; ++bail: ++ if ( cacerts_dir ) PR_smprintf_free( cacerts_dir ); ++ if ( list ) CERT_DestroyCertList( list ); ++ return rv; ++} ++ ++ ++/* returns 1 if successfull; ++ returns -1 if only cert-key pair is NULL or could not be extracted; ++ returns 0 if any other error ++*/ ++int ++tlsmc_extract_nssdb( char *dir_name, char **ld_cacertdir, char **ld_cert, char **ld_key ) ++{ ++ int rv = 0; ++ ++ if ( ! dir_name ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_nssdb: FATAL: target dir name empty.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ if ( 0 == tlsmc_extract_cacerts( dir_name ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_nssdb: ERROR: could not export CA certificates.\n", ++ 0, 0, 0 ); ++ } ++ ++ if ( ( ! *ld_cert ) || ( ! *ld_key ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_nssdb: ERROR: cert or key empty.\n", ++ 0, 0, 0 ); ++ rv = -1; ++ goto bail; ++ } ++ ++ if ( 0 == tlsmc_extract_cert_key_pair( *ld_cert, *ld_key, dir_name ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_extract_nssdb: ERROR: could not export user cert and/or key.\n", ++ 0, 0, 0 ); ++ rv = -1; ++ goto bail; ++ } ++ ++ rv = 1; ++bail: ++ return rv; ++} ++ ++int ++tlsmc_close_nssdb(NSSInitContext **initctx) ++{ ++ if ( *initctx && NSS_ShutdownContext( *initctx ) ) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_close_nssdb: ERROR: could not shutdown NSS - error %d:%s.\n", ++ errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++int ++tlsmc_convert( char **ld_cacertdir, char **ld_cert, char **ld_key ) ++{ ++ ++ int rv = 0; ++ ++ NSSInitContext *nss_ctx = NULL; ++ char *nssdb_dir_path = NULL; ++ char *nssdb_dir_name = NULL; ++ char *nssdb_prefix = NULL; ++ char *pem_dirs[] = { NULL, NULL, NULL }; ++ char *readme_path = NULL; ++ char *data = NULL; // data before checksum ++ char *checksum = NULL; // checksummed data ++ char **dirs = pem_dirs; ++ char *dir = *dirs; ++ struct stat stat_buf; ++ ++#ifdef LDAP_R_COMPILE ++ ldap_pvt_thread_mutex_lock( &tlsmc_mutex ); ++#endif ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_convert: INFO: trying to open NSS DB with CACertDir = `%s'.\n", ++ *ld_cacertdir, 0, 0 ); ++ if ( 0 == tlsmc_open_nssdb( *ld_cacertdir, &nss_ctx, &nssdb_dir_path, &nssdb_prefix ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: INFO: cannot open the NSS DB, expecting PEM configuration is present.\n", ++ 0, 0, 0 ); ++ rv = 1; ++ goto bail; ++ } ++ ++ if ( NULL == ( checksum = tlsmc_compute_checksum( nssdb_dir_path, nssdb_prefix, ++ *ld_cacertdir, *ld_cert, *ld_key, ++ &data ) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: ERROR: could not compute checksum.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ pem_dirs[0] = PR_smprintf( "%s-%s-tlsmc-%s", nssdb_dir_path, nssdb_prefix, checksum ); ++ pem_dirs[1] = PR_smprintf( "/tmp/%s", tlsmc_path2name( pem_dirs[0] ) ); ++ ++ int i=0; ++ while ( NULL != ( dir = *(dirs++) ) ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_convert: INFO: trying with PEM dir = `%s'.\n", ++ dir, 0, 0 ); ++ if ( 0 == stat( dir, &stat_buf ) ) { ++ if ( S_ISDIR(stat_buf.st_mode) ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_convert: INFO: using the existing PEM dir.\n", ++ 0, 0, 0 ); ++ break; ++ } else { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: WARN: tried to stat the PEM dir but it is not a directory, will try another one.\n", ++ 0, 0, 0 ); ++ continue; ++ } ++ } ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_convert: WARN: could not stat PEM dir, will try to create it.\n", ++ 0, 0, 0 ); ++ if ( 0 == tlsmc_prepare_dir( dir ) ) { ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_convert: WARN: cannot prepare the PEM dir, will try another one.\n", ++ 0, 0, 0 ); ++ continue; ++ } ++ if ( 0 == tlsmc_extract_nssdb( dir, ld_cacertdir, ld_cert, ld_key ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: FATAL: could not extract from the NSS DB.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ readme_path = PR_smprintf( "%s/" TLSMC_README_FILE_NAME, dir ); ++ tlsmc_write_file( readme_path, data, S_IRUSR ); ++ rv = 1; ++ break; ++ } ++ ++ if ( dir == NULL ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: FATAL: no usable PEM dir.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ if (*ld_cacertdir) free(*ld_cacertdir); ++ *ld_cacertdir = PR_smprintf( "%s/" TLSMC_CACERTS_DIR_NAME, dir ); ++ if ( ! ( ( 0 == stat( *ld_cacertdir, &stat_buf ) ) ++ && S_ISDIR(stat_buf.st_mode) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: WARN: extracted cacerts dir is not present.\n", ++ 0, 0, 0 ); ++ *ld_cacertdir = NULL; ++ } ++ ++ if (*ld_cert) free(*ld_cert); ++ *ld_cert = PR_smprintf( "%s/" TLSMC_CERT_FILE_NAME, dir ); ++ if ( ! ( ( 0 == stat( *ld_cert, &stat_buf ) ) ++ && S_ISREG(stat_buf.st_mode) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: WARN: extracted cert file is not present.\n", ++ 0, 0, 0 ); ++ *ld_cert = NULL; ++ } ++ ++ if (*ld_key) free(*ld_key); ++ *ld_key = PR_smprintf( "%s/" TLSMC_KEY_FILE_NAME, dir ); ++ if ( ! ( ( 0 == stat( *ld_key, &stat_buf ) ) ++ && S_ISREG(stat_buf.st_mode) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_convert: WARN: extracted key file is not present.\n", ++ 0, 0, 0 ); ++ *ld_key = NULL; ++ } ++ ++ rv = 1; ++ ++bail: ++ if ( pem_dirs[0] ) PR_smprintf_free( pem_dirs[0] ); ++ if ( pem_dirs[1] ) PR_smprintf_free( pem_dirs[1] ); ++ if ( nssdb_prefix ) free( nssdb_prefix ); ++ if ( nssdb_dir_path ) free( nssdb_dir_path ); ++ if ( nss_ctx ) tlsmc_close_nssdb( &nss_ctx ); ++ ++#ifdef LDAP_R_COMPILE ++ ldap_pvt_thread_mutex_unlock( &tlsmc_mutex ); ++#endif ++ ++ return rv; ++} ++ ++ ++ ++ ++// returns 0 when successful ++int ++tlsmc_intercept_initialization( struct ldapoptions *lo, int is_server ) ++{ ++ int rv = 0; ++ char *ld_cacertdir = NULL; ++ char *ld_cert = NULL; ++ char *ld_key = NULL; ++ ++ ld_cacertdir = lo->ldo_tls_cacertdir ? LDAP_STRDUP( (char *) lo->ldo_tls_cacertdir ) : NULL; ++ ld_cert = lo->ldo_tls_certfile ? LDAP_STRDUP( (char *) lo->ldo_tls_certfile ) : NULL; ++ ld_key = lo->ldo_tls_keyfile ? LDAP_STRDUP( (char *) lo->ldo_tls_keyfile ) : NULL; ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_intercept_initialization: INFO: entry options follow:\n" ++ "tlsmc_intercept_initialization: INFO: cacertdir = `%s'\n" ++ "tlsmc_intercept_initialization: INFO: certfile = `%s'\n" ++ "tlsmc_intercept_initialization: INFO: keyfile = `%s'\n", ++ lo->ldo_tls_cacertdir, lo->ldo_tls_certfile, lo->ldo_tls_keyfile ); ++ ++ if ( 0 == tlsmc_convert( &ld_cacertdir, &ld_cert, &ld_key ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_intercept_initialization: FATAL: could not intercept TLS initialization. TLS will not work!\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir ); ++ lo->ldo_tls_cacertdir = ld_cacertdir ? LDAP_STRDUP( (char *) ld_cacertdir ) : NULL; ++ ++ if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile ); ++ lo->ldo_tls_certfile = ld_cert ? LDAP_STRDUP( (char *) ld_cert ) : NULL; ++ ++ if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile ); ++ lo->ldo_tls_keyfile = ld_key ? LDAP_STRDUP( (char *) ld_key ) : NULL; ++ ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_intercept_initialization: INFO: altered options follow:\n" ++ "tlsmc_intercept_initialization: INFO: cacertdir = `%s'\n" ++ "tlsmc_intercept_initialization: INFO: certfile = `%s'\n" ++ "tlsmc_intercept_initialization: INFO: keyfile = `%s'\n", ++ lo->ldo_tls_cacertdir, lo->ldo_tls_certfile, lo->ldo_tls_keyfile ); ++ ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_intercept_initialization: INFO: successfully intercepted TLS initialization. Continuing with OpenSSL only.\n", ++ 0, 0, 0 ); ++ rv = 1; ++bail: ++ if ( ld_cacertdir ) LDAP_FREE( ld_cacertdir ); ++ if ( ld_cert ) LDAP_FREE( ld_cert ); ++ if ( ld_key ) LDAP_FREE( ld_key ); ++ return rv; ++} ++ ++#endif /* HAVE_MOZNSS_COMPATIBILITY */ ++/* ++ emacs settings ++ Local Variables: ++ indent-tabs-mode: t ++ tab-width: 4 ++ End: ++*/ +diff --git a/libraries/libldap/tls_mc.h b/libraries/libldap/tls_mc.h +new file mode 100644 +index 000000000..2e6e567dc +--- /dev/null ++++ b/libraries/libldap/tls_mc.h +@@ -0,0 +1,18 @@ ++#ifndef _LDAP_TLSMC_H ++#define _LDAP_TLSMC_H ++ ++#include "portable.h" ++ ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ ++#include "ldap-int.h" ++ ++int ++tlsmc_convert( char **ld_cacertdir, char **ld_cert, char **ld_key ); ++ ++int ++tlsmc_intercept_initialization( struct ldapoptions *lo, int is_server ); ++ ++ ++#endif /* HAVE_MOZNSS_COMPATIBILITY */ ++#endif /* _LDAP_TLSMC_H */ +diff --git a/libraries/libldap/tls_mc_ossl.c b/libraries/libldap/tls_mc_ossl.c +new file mode 100644 +index 000000000..d61ec207c +--- /dev/null ++++ b/libraries/libldap/tls_mc_ossl.c +@@ -0,0 +1,90 @@ ++#include "portable.h" ++ ++/* This file contains functions that require OpenSSL headers due to some ++ conflicts with what MozNSS defines. ++*/ ++ ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ ++#include ++#include ++#include "ldap-int.h" ++#include ++#include ++#include ++ ++ ++int ++tlsmc_cert_create_hash_symlink( char *cert_path, char *cacerts_dir ) ++{ ++ int rv = 0; ++ X509 *cert = NULL; ++ FILE *fp = NULL; ++ unsigned long hash = 0; ++ char *cert_filename_p = NULL; ++ char *last_slash_p = NULL; ++ char *symlink_path = NULL; ++ int cnt = 0; ++ ++ if ( NULL == ( fp = fopen( cert_path, "r" ) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: ERROR: could not open the cert file.\n", ++ 0, 0, 0 ); ++ perror( "tlsmc_cert_create_hash_symlink: ERROR: OS error" ); ++ goto bail; ++ } ++ if ( NULL == PEM_read_X509( fp, &cert, NULL, NULL ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: ERROR: could not read PEM data.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ if ( 0 == ( hash = X509_subject_name_hash( cert ) ) ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: ERROR: could not hash subject.\n", ++ 0, 0, 0 ); ++ goto bail; ++ } ++ ++ last_slash_p = strrchr( cert_path, '/' ); ++ cert_filename_p = last_slash_p ? last_slash_p + 1 : cert_path; ++ for ( cnt = 0; cnt < 10; cnt++ ) { ++ symlink_path = PR_smprintf( "%s/%08lx.%d", cacerts_dir, hash, cnt ); ++ if ( 0 != symlink( cert_filename_p, symlink_path ) ) { ++ if ( errno == EEXIST ) { ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: INFO: symlink `%s' already exists.\n", ++ 0, 0, 0 ); ++ if ( symlink_path ) PR_smprintf( symlink_path ); ++ continue; ++ } ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: ERROR: could not create symlink.\n", ++ 0, 0, 0 ); ++ perror( "tlsmc_cert_create_hash_symlink: ERROR: OS error" ); ++ goto bail; ++ } ++ Debug( LDAP_DEBUG_TRACE, ++ "tlsmc_cert_create_hash_symlink: INFO: the cert is now symlinked to %s.\n", ++ symlink_path, 0, 0 ); ++ rv = 1; ++ goto bail; ++ } ++ Debug( LDAP_DEBUG_ANY, ++ "tlsmc_cert_create_hash_symlink: INFO: could not create symlink (all possible file names taken).\n", ++ 0, 0, 0 ); ++bail: ++ if ( symlink_path ) PR_smprintf_free( symlink_path ); ++ if ( cert ) X509_free( cert ); ++ if ( fp ) fclose( fp ); ++ return rv; ++} ++ ++#endif /* HAVE_MOZNSS_COMPATIBILITY */ ++/* ++ emacs settings ++ Local Variables: ++ indent-tabs-mode: t ++ tab-width: 4 ++ End: ++*/ +diff --git a/libraries/libldap/tls_mc_ossl.h b/libraries/libldap/tls_mc_ossl.h +new file mode 100644 +index 000000000..1b4284576 +--- /dev/null ++++ b/libraries/libldap/tls_mc_ossl.h +@@ -0,0 +1,12 @@ ++#ifndef _LDAP_TLSMC_OSSL_H ++#define _LDAP_TLSMC_OSSL_H ++ ++#include "portable.h" ++ ++#ifdef HAVE_MOZNSS_COMPATIBILITY ++ ++int ++tlsmc_cert_create_hash_symlink( char *cert_path, char *cacerts_dir ); ++ ++#endif ++#endif +diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in +index cdf4070dd..c7a86c95f 100644 +--- a/libraries/libldap_r/Makefile.in ++++ b/libraries/libldap_r/Makefile.in +@@ -28,7 +28,7 @@ XXSRCS = apitest.c test.c \ + request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ + init.c options.c print.c string.c util-int.c schema.c \ + charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ +- tls2.c tls_o.c tls_g.c tls_m.c \ ++ tls2.c tls_o.c tls_g.c tls_m.c tls_mc.c tls_mc_ossl.c \ + turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ + assertion.c deref.c ldif.c fetch.c + SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \ +@@ -46,7 +46,7 @@ OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \ + request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ + init.lo options.lo print.lo string.lo util-int.lo schema.lo \ + charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ +- tls2.lo tls_o.lo tls_g.lo tls_m.lo \ ++ tls2.lo tls_o.lo tls_g.lo tls_m.lo tls_mc.lo tls_mc_ossl.lo \ + turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ + assertion.lo deref.lo ldif.lo fetch.lo + diff --git a/openldap.spec b/openldap.spec index 12df3b8..4e996c4 100644 --- a/openldap.spec +++ b/openldap.spec @@ -5,7 +5,7 @@ Name: openldap Version: 2.4.45 -Release: 3%{?dist} +Release: 4%{?dist} Summary: LDAP support libraries Group: System Environment/Daemons License: OpenLDAP @@ -27,12 +27,6 @@ Patch1: openldap-sql-linking.patch Patch2: openldap-reentrant-gethostby.patch Patch3: openldap-smbk5pwd-overlay.patch Patch5: openldap-ai-addrconfig.patch -# nss patches, unlikely to ever get upstreamed -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 Patch17: openldap-allop-overlay.patch # fix back_perl problems with lt_dlopen() @@ -42,24 +36,16 @@ Patch17: openldap-allop-overlay.patch Patch19: openldap-switch-to-lt_dlopenadvise-to-get-RTLD_GLOBAL-set.patch # ldapi sasl fix pending upstream inclusion Patch20: openldap-ldapi-sasl.patch -Patch22: openldap-nss-protocol-version-new-api.patch - -Patch50: openldap-nss-cipher-attributes.patch -Patch51: openldap-nss-ciphers-parsing.patch -Patch52: openldap-nss-ciphers-use-nss-defaults.patch -Patch53: openldap-nss-ciphers-definitions.patch # check-password module specific patches Patch90: check-password-makefile.patch Patch91: check-password.patch -# Fedora specific patches -Patch100: openldap-autoconf-pkgconfig-nss.patch +# MozNSS compatibility layer +Patch100: openldap-tlsmc.patch -BuildRequires: cyrus-sasl-devel, nss-devel, krb5-devel, tcp_wrappers-devel, unixODBC-devel +BuildRequires: cyrus-sasl-devel, nss-devel, openssl-devel, krb5-devel, tcp_wrappers-devel, unixODBC-devel BuildRequires: glibc-devel, libtool, libtool-ltdl-devel, groff, perl-interpreter, perl-devel, perl-generators, perl(ExtUtils::Embed) -# smbk5pwd overlay: -BuildRequires: openssl-devel Recommends: nss-tools %description @@ -126,13 +112,12 @@ programs needed for accessing and modifying OpenLDAP directories. pushd openldap-%{version} -# use pkg-config for Mozilla NSS library -%patch100 -p1 - # alternative include paths for Mozilla NSS ln -s %{_includedir}/nss3 include/nss ln -s %{_includedir}/nspr4 include/nspr +%patch100 -p1 + AUTOMAKE=%{_bindir}/true autoreconf -fi %patch0 -p1 @@ -140,20 +125,9 @@ AUTOMAKE=%{_bindir}/true autoreconf -fi %patch2 -p1 %patch3 -p1 %patch5 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 %patch17 -p1 %patch19 -p1 %patch20 -p1 -%patch22 -p1 - -%patch50 -p1 -%patch51 -p1 -%patch52 -p1 -%patch53 -p1 # build smbk5pwd with other overlays ln -s ../../../contrib/slapd-modules/smbk5pwd/smbk5pwd.c servers/slapd/overlays @@ -219,11 +193,12 @@ pushd openldap-%{version} \ --disable-static \ \ + --enable-moznss-compatibility=yes \ + \ --with-cyrus-sasl \ --without-fetch \ --with-threads \ --with-pic \ - --with-tls=moznss \ --with-gnu-ld \ \ --libexecdir=%{_libdir} @@ -546,6 +521,9 @@ exit 0 %{_mandir}/man3/* %changelog +* Fri Nov 3 2017 Matus Honek - 2.4.45-4 +- Build with OpenSSL with MozNSS compatibility layer (#1400570) + * Thu Aug 03 2017 Fedora Release Engineering - 2.4.45-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild