Control: tag -1 confirmed upstream
Control: retitle -1 libldap-2.4-2: default TLS context setup ignores options 
set on connection

Hello,

Sorry for the delayed response.

On Mon, May 02, 2016 at 05:44:58PM +0300, Aki Tuomi wrote:
Most simple usecase:
1. Install slapd with non-default CA signed certificate
2. Try connect with openldap -Z -H ldap://server ...

Expected behaviour
Invalid cert ignored, and TLS continues

Actual behaviour
Failure with non-descriptive error, debug shows
ldap_start_tls: Connect error (-11)

This appears to work for me, tested as follows:

- in a clean jessie system, apt-get install ssl-cert slapd ldap-utils
- add the openldap user to the ssl-cert group
- configure slapd to use the snakeoil (self-signed) certs

$ LDAPTLS_REQCERT=allow ldapwhoami -ZZ -x
anonymous

Another option, which I personally would prefer, is to set the CA cert just for LDAP:

$ LDAPTLS_CACERT=/etc/ssl/certs/ssl-cert-snakeoil.pem ldapwhoami -ZZ -x
anonymous

Workaround, of course, is to install the non-standard CA as trusted CA
certificate. But the man page *does* say that it really should work.

Right, installing the non-standard CA system wide should not be necessary, for either of the options above.

The same behaviour occurs with direct LDAP library usage with

 int opt = LDAP_OPT_X_TLS_ALLOW;
 ldap_set_option(conn->conn, LDAP_OPT_X_TLS, &opt);
 ldap_set_option(conn->conn, LDAP_OPT_X_TLS_REQUIRE_CERT, &opt);

Again, this should allow non-trusted certificate on peer, which is appears
not to do.

As a side note, the LDAP_OPT_X_TLS option is deprecated in favour of ldap_start_tls(3):

http://www.openldap.org/lists/openldap-software/200706/msg00159.html

The documentation apparently doesn't talk about this, but it looks like what happens is that you get a default TLS context, initialized using the global options, unless you specifically ask for a new one using LDAP_OPT_X_TLS_NEWCTX.

So this works:

        int require_cert = LDAP_OPT_X_TLS_ALLOW;
        rc = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &require_cert);
        assert(rc == LDAP_SUCCESS);

        int new_ctx = 0;
        rc = ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &new_ctx);
        assert (rc == LDAP_SUCCESS);

        rc = ldap_start_tls_s(ld, NULL, NULL);
        assert(rc == LDAP_SUCCESS);

and this works:

        int require_cert = LDAP_OPT_X_TLS_ALLOW;
        rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &require_cert);
        assert(rc == LDAP_SUCCESS);

        LDAP *ld;
        rc = ldap_initialize(&ld, "ldap://";);
        assert(rc == LDAP_SUCCESS);

        rc = ldap_start_tls_s(ld, NULL, NULL);
        assert(rc == LDAP_SUCCESS);

but this doesn't work:

        int require_cert = LDAP_OPT_X_TLS_ALLOW;
        rc = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &require_cert);
        assert(rc == LDAP_SUCCESS);

        rc = ldap_start_tls_s(ld, NULL, NULL);
        assert(rc == LDAP_SUCCESS);

Other people have noticed this, too:

http://stackoverflow.com/a/27713355
http://www.openldap.org/its/?findid=7843

I'm guessing this is intended behaviour, and the documentation should be clarified. I'll follow up with upstream. Thanks for the report!

Reply via email to