On May 17th I posted a bug in Mozilla’s bugzilla trouble ticket system, regarding X.509 certificates which aren’t retrieved via LDAP on a connection which requires credentials. This has been biting me quite a bit and I’ve finally found a solution.


I offer limited LDAP directory services to clients who connect over SSL. The service is limited in as much as the number and types of attributes which are returned to the clients are limited as well as the number of entries. To this effect, an OpenLDAP proxy server with a back-ldap backend fronts the connections from the Internet as proxies them in to an internal directory server (also OpenLDAP).

The proxy

The configuration of the proxy is quite simple and well documented in slapd- ldap. Here is my configuration:

    include         /usr/local/etc/openldap/schema/core.schema
    include         /usr/local/etc/openldap/schema/cosine.schema
    include         /usr/local/etc/openldap/schema/inetorgperson.schema
    include         /usr/local/etc/openldap/schema/custom.schema
    pidfile         /var/run/slapd.pid
    argsfile        /var/run/slapd.args
    loglevel 256
    allow bind_v2
    TLSCACertificateFile /usr/local/etc/openldap/chain.pem
    TLSCertificateFile /usr/local/etc/openldap/pub.crt
    TLSCertificateKeyFile /usr/local/etc/openldap/priv.key
    TLSVerifyClient   never
    database        ldap
    uri             "ldap://in1.example.com/ ldap://in2.example.com/"
    suffixmassage   "ou=People,o=EXT"  "ou=People,dc=example,dc=com"
    suffix          "ou=People,o=EXT"
    map             attribute "display-name" "displayname"
    map             attribute uid           *
    map             attribute cn            *
    map             attribute sn            *
    map             attribute givenname     *
    map             attribute mail          *
    map             attribute telephonenumber *
    map             attribute usercertificate;binary *
    map             attribute *
    map             objectclass person      *
    map             objectclass inetorgperson       *
    map             objectclass *
    lastmod         off
    access to dn.base="" by * read
    access to dn.base="cn=Subschema" by * read
    access to attrs=userpassword
            by anonymous auth
    # Allow anon access to the usercertificate. The attrs= must
    # contain the entry!
    access to dn.children="ou=People,o=EXT"
            by anonymous read
            by users read
            by * none
    access to *
            by users read
            by anonymous auth

The Queries

When an authenticated client performs an LDAP search, all works well. This can be tested with the ldapsearch utility (do remember to use -H ldaps://hostname) or by configuring Mozilla Thunderbird appropriately and setting credentials for the bind (DN of the user and password).

Upon performing address-book queries, Thunderbird contacts the server, binds as the user and does it search. Upon composing a new message in Thunderbird, the logs on the LDAP proxy show the request:

    conn=43 op=0 BIND dn="cn=smith,ou=people,o=ext" method=128
    conn=43 op=0 RESULT tag=97 err=0 text=
    conn=43 op=0 BIND dn="cn=smith,ou=people,o=ext" mech=SIMPLE ssf=0
    conn=43 op=0 RESULT tag=97 err=0 text=
    conn=43 op=1 SRCH base="ou=people,o=ext" scope=2 deref=0 filter="(|(cn=smith*)(mail=smith*)(sn=smith*))"
    conn=43 op=1 SRCH attr=cn mail
    conn=43 op=1 SEARCH RESULT tag=101 err=0 nentries=2 text=

Iff the user now chooses to encrypt that message, upon hitting the Security button in the compose window, Thunderbird tries to fetch the userCertificate for that address. Notice how the LDAP server logs an anonymous bind!

    conn=57 op=0 BIND dn="" method=128
    conn=57 op=0 RESULT tag=97 err=0 text=
    conn=57 op=1 SRCH base="ou=people,o=ext" scope=2 deref=0 filter="(mail=smith@example.com)"
    conn=57 op=1 SRCH attr=usercertificate;binary
    conn=57 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
    conn=57 op=2 UNBIND
    conn=57 fd=10 closed

In order for this anonymous bind to get through, I’ve added an ACL to the proxy configuration as seen above; this allows the proxy to return the binary userCertificate to the client.