#48782 Replication + SSLCLIENTAUTH failure: setup_ol_tls_conn - failed: unable to create new TLS context
Closed: Fixed None Opened 3 years ago by minfrin.

When an attempt is made to configure a master to replicate with a slave using SSLCLIENTAUTH, the attempt to connect to the slave fails as follows:

[30/Mar/2016:17:19:19 +0000] setup_ol_tls_conn - failed: unable to create new TLS context
[30/Mar/2016:17:19:19 +0000] slapi_ldap_bind - Error: could not configure the server for cert auth - error -1 - make sure the server is correctly configured for SSL/TLS
[30/Mar/2016:17:19:19 +0000] NSMMReplicationPlugin - agmt="cn=Agreement ldap.example.com" (ldap:636): Replication bind with EXTERNAL auth failed: LDAP error 0 (Success) ()

The origin of the error appears to be the following code in ldap/servers/slapd/ldaputil.c:

    /* have to do this last - this creates the new TLS handle and sets/copies
       all of the parameters set above into that TLS handle context - note
       that optval is ignored - what matters is that it is not NULL */
    if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &optval))) {
        slapi_log_error(SLAPI_LOG_FATAL, "setup_ol_tls_conn",
                        "failed: unable to create new TLS context - %d\n", rc);
    }

The clue is in the comment "note that optval is ignored - what matters is that it is not NULL". This is contradicted at http://linux.die.net/man/3/ldap_set_option and at https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/ldap_set_option.3.html where it says "invalue must be const int *. A non-zero value pointed to by invalue tells the library to create a context for a server.".

It looks like optval needs to be set to zero explicitly for this code to work.

Looking at the code this probably worked by accident, until this code was introduced:

#if defined(LDAP_OPT_X_TLS_PROTOCOL_MIN)
    optval = LDAP_OPT_X_TLS_PROTOCOL_SSL3;
    if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, &optval))) {
        slapi_log_error(SLAPI_LOG_FATAL, "setup_ol_tls_conn",
                        "failed: unable to set minimum TLS protocol level to SSL3\n");
    }
#endif /* LDAP_OPT_X_TLS_PROTOCOL_MIN */

In theory, this should fix it:

{{{
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index e62d1f2..3851be5 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -605,7 +605,8 @@ setup_ol_tls_conn(LDAP *ld, int clientauth)

 /* have to do this last - this creates the new TLS handle and sets/copies
    all of the parameters set above into that TLS handle context - note
  • that optval is ignored - what matters is that it is not NULL */
  • that optval is zero, meaning create a context for a client */
  • optval = 0;
    if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &optval))) {
    slapi_log_error(SLAPI_LOG_FATAL, "setup_ol_tls_conn",
    "failed: unable to create new TLS context - %d\n", rc);
    }}}

Basically, the ssl range follows the same configuration the server side uses:
{{{
dn: cn=encryption,cn=config
sslVersionMin: TLS1.0
sslVersionMax: TLS1.3
}}}

Please note that we don't recommend to enable SSLv3, which could be vulnerable.

optval = LDAP_OPT_X_TLS_PROTOCOL_SSL3;

If you really need to enable SSLv3, please set these:
{{{
dn: cn=encryption,cn=config
nsSSL3: on
sslVersionMin: SSL3
sslVersionMax: TLS1.3
}}}

Much stepping through code later.

It turns out that on Ubuntu Trusty, 389ds the server is backed with NSS as the security library, however 389ds’s replication plugin is backed with gnutls.

The NSS nicknames for certfile, keyfile and cacertdir are passed into gnutls, which then fails here as follows:

{{{
/ OpenSSL builds the cert chain for us, but GnuTLS
* expects it to be present in the certfile. If it's
* not, we have to build it ourselves. So we have to
* do some special checks here...
/
rc = tlsg_getfile( lt->lt_keyfile, &buf );
if ( rc ) return -1;
}}}

{{{
397 in tls_g.c
(gdb) print rc
$5 = <optimized out="">
(gdb) print *lt
$6 = {
lt_certfile = 0x7f1f9801f3a0 "Internal (Software) Token:ldap.example.com", lt_keyfile = 0x7f1f980187b0 "Server-Key", lt_dhfile = 0x0, lt_cacertfile = 0x0,
lt_cacertdir = 0x7f1f98013960 "/etc/dirsrv/slapd-hg", lt_ciphersuite = 0x0, lt_crlfile = 0x0, lt_randfile = 0x0,
lt_protocol_min = 768}
(gdb) print buf
$7 = 0x0
}}}

The “return -1” above is the origin of the “-1” return code in the logged error message.

Running ldd against the ns-slapd binary shows this (snipped):

{{{
root@ldap.example.com:~/src/openldap-2.4.31# ldd /usr/sbin/ns-slapd
libnss3.so => /usr/lib/x86_64-linux-gnu/libnss3.so (0x00007f0e14e60000)
libgnutls.so.26 => /usr/lib/x86_64-linux-gnu/libgnutls.so.26 (0x00007f0e12def000)
}}}

It looks like no kind of replication could ever work on Ubuntu Trusty, as NSS parameters are passed to gnutls, which can only fail.

Make sure that when LDAP_OPT_X_TLS_NEWCTX is set, the value is set to zero.
0001-Make-sure-that-when-LDAP_OPT_X_TLS_NEWCTX-is-set-the.patch

The attached patch is for the optval issue described above. Optval is explicitly set to zero, rather than using whatever arbitrary value is present in optval from the earlier ldap_set_option call.

Ack to the patch 0001-Make-sure-that-when-LDAP_OPT_X_TLS_NEWCTX-is-set-the.patch.

I'm going to push your patch to the 389-ds-base git repo.

Thanks to Graham Leggett for the patch. Pushed it to master on behalf of him.

5cfd3de..16445ac master -> master
commit 16445ac

And sorry about my comment #comment:2, which is totally bogus. I'm opening a ticket to fix it, as well.

Is it ok to close this ticket although this patch may not solve your original problem (openldap + gnutls), though.

Metadata Update from @minfrin:
- Issue set to the milestone: 1.3.5.2

2 years ago

Login to comment on this ticket.

Metadata