The Problem
We've created an Open Directory master on OSX 10.10 Yosemite + Server.app v4:
$ sudo slapconfig -createldapmasterandadmin admin Administrator 1000
Which generates a root CA, an intermediate CA and a host SSL certificate (all correctly placed in both the system keychain and in the /etc/certificates
directory). However, when connecting over SSL, slapd
provides only the host certificate, rather than the entire certificate chain:
$ openssl s_client -connect a.b.c:636
CONNECTED(00000003)
depth=0 CN = a.b.c, C = GB, emailAddress = a@b.c.
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = a.b.c, C = GB, emailAddress = a@b.c
verify error:num=27:certificate not trusted
verify return:1
depth=0 CN = a.b.c, C = GB, emailAddress = a@b.c
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=a.b.c/C=GB/emailAddress=a@b.c
i:/CN=IntermediateCA_A.B.C_1/O=b/OU=MACOSX OpenDirectory Intermediate CA/emailAddress=a@b.c
---
This is a problem, of course, because clients (who trust only the root CA) fail to validate the host certificate and abort the connection.
Documented solutions
According to OpenLDAP Software 2.4 Administrator's Guide, Chapter 16 "Using TLS":
16.2.1.1. TLSCACertificateFile <filename>
This directive specifies the PEM-format file containing certificates for the CA's that slapd will trust. The certificate for the CA that signed the server certificate must be included among these certificates. If the signing CA was not a top-level (root) CA, certificates for the entire sequence of CA's from the signing CA to the top-level CA should be present. Multiple certificates are simply appended to the file; the order is not significant.
(For the avoidance of doubt, the fact that slapd
will then provide the certificate chain to connecting clients was recently confirmed on the openldap-technical mailing list—although it has been previously noted that this gives rise to a problematic conflict where different trust anchors are used for TLS client certificates).
Apple peculiarities
Since Apple's build uses slapd.d
, one would normally expect this option to be configured via olcTLSCACertificateFile
—however, according to slapd-config(5)
(emphasis added):
olcTLSCACertificateFile: <filename>
Specifies the file that contains certificates for all of the Certificate Authorities that slapd will recognize.
When using SecureTransport this option is not valid. Instead use the olcTLSTrustedCerts option.
[ deletia ]olcTLSTrustedCerts
Lists the trusted certificates in the system keychain separated by '|'. For example: olcTLSTrustedCerts Frobozz, Inc.|Widgets R Us|www.example.com
Used by SecureTransport instead of olcTLSCACertificateFile and olcTLSCACertificatePath. Ignored by OpenSSL, GnuTLS and Mozilla NSS.
(SecureTransport is Apple's SSL library).
Our attempts…
Surprisingly, olcTLSTrustedCerts
was not created in our directory by slapconfig
, although the host certificate was named in (the related) olcTLSIdentity
. That said, slapd
was in any event ignoring olcTLSIdentity
in favour of the OPENDIRECTORY_SSL_IDENTITY
preference in the system keychain:
TLS: OPENDIRECTORY_SSL_IDENTITY identity preference overrode configured olcTLSIdentity "a.b.c"
So, we have tried the following (both independently and together):
Adding
olcTLSTrustedCerts
.slapd
clearly parses the CNs listed in this option and locates the CA certificates in the system keychain, as it logs cases where a deliberately incorrect value is provided:TLS: SecItemCopyMatching(foo.bar) failed (check olcTLSTrustedCerts setting): The specified item could not be found in the keychain. (-25300)
Removing the
OPENDIRECTORY_SSL_IDENTITY
preference from the system keychain.slapd
no longer complains thatolcTLSIdentity
has been overridden (and it only continues to support SSL so long as the value of that configuration option matches the CN of a certificate in the system keychain, else it complains similarly to the error quoted above—suggesting that it's using that configuration option as expected).
Yet the full certificate chain is still not provided to connecting clients. How can this be fixed?