Trusting TLS Certificates

Jurjen Bokma

Last modified: "2016-09-26 09:35:38 jurjen"


How to add a certificate to the list of trusted certificates, in order to trust some other certificates.

  1. root@freebsdhost:~# openssl s_client -connect -showcerts </dev/null |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > server.cert
    depth=1 DC = com, DC = mycompany, DC = mydomain, CN = MyCompany Issuing CA 01
    verify error:num=20:unable to get local issuer certificate
    verify return:0
    root@freebsdhost:~# openssl x509 -in server.cert -text -noout
    Version: 3 (0x2)
    Serial Number:
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: DC=com, DC=mycompany, DC=mydomain, CN=MyCompany Issuing CA 01
    Authority Information Access:
    CA Issuers - URI:http://CAL002/certenroll/CAL002.mydomain.mycompany.com_MyDomain%20Issuing%20CA%2001.crt
    CA Issuers - URI:http://CAL003/certenroll/CAL002.mydomain.mycompany.com_MyDomain%20Issuing%20CA%2001.crt
    CA Issuers - URI:ldap:///CN=MyDomain%20Issuing%20CA%2001,CN=AIA,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=mydomain,DC=mycompany,DC=com?cACertificate?base?objectClass=certificationAuthority

  2. Judging from the previous step's output, AD is using a self-signed certificate. We can fetch it from LDAP (using a non-SSL connection for the moment) with this somewhat ad-hoc command:

    root@freebsdhost:~# ldapsearch -U u123456 -R MYDOMAIN.MYCOMPANY.COM -E pr=1000/noprompt -H ldap:// -b "$(openssl x509 -in server.cert -text -noout|grep 'CA Issuers'|grep '///CN='|awk '{print $4}'|sed 's%^.*/%%g ; s/?.*//g; s/%20/ /g')" caCertificate 2>/dev/null|tee ca-search.out

  3. Extract the certificate from the previous step:

    root@freebsdhost:~# ( echo '-----BEGIN CERTIFICATE-----'; grep -v 'DC=' ca-search.out|sed -n 's/cacertificate:://gI ; /^ / p'; echo '-----END CERTIFICATE-----' ) |tee cacert.pem

  4. apprentice@ubuntuhost:~$ sudo mkdir /usr/local/share/ca-certificates/mydomain
    apprentice@ubuntuhost:~$ sudo cp cacert.pem !$/MYDOMAIN_ROOT_CA.pem #NB the .pem extension matters!
    apprentice@ubuntuhost:~$ sudo update-ca-certificates
    apprentice@ubuntuhost:~$ sudo c_rehash

    On CentOS 7:

    [apprentice@centoshost ~]$ sudo certutil -d/etc/openldap/certs -A -n MYDOMAIN_ROO_CA -t C -a -i MYDOMAIN_ROOTCA.pem

    On FreeBSD there is no /etc/ssl/cert.pem yet, so we copy the root certificate there. Then the openssl connect below already works.

    Now the connection will work:

    apprentice@ubuntuhost:~$ openssl s_client -connect < /dev/null
    Verify return code: 0 (ok)

  5. An intermediate certificate in the chain is broken: it uses an unknown signing algorithm. OpenSSL doesn't complain, but ldapsearch uses libgnutls, and it refuses to connect to the server. We used gnutls-cli and certtool to figure that out:

    certtool --certificate-info --infile /usr/local/share/ca-certificates/mydomain/MYDOMAIN_ROOT_CA.pem|grep -i broken
    gnutls-cli -p 636       
    certtool --certificate-info --infile /usr/local/share/ca-certificates/mydomain/MYDOMAIN_ISSUER.pem|grep -i broken

    While we wait for the certificate to get fixed, we put in /etc/ldap/ldap.conf:

    TLS_REQCERT  allow

    That allows ldapsearch to ignore the certificate if it can't be verified. Not very secure, but the show must go on.

  6. On Xenial and Centos 7, this should work (after getting a ticket):

    ldapsearch -E pr=1000/noprompt -O minssf=56,maxssf=128 -H ldaps:// -b "dc=mydomain,dc=mycompany,dc=com" CN=u123456

    On FreeBSD, it doesn't, presumably because it uses OpenSSL instead of GnuTLS, and the signing conflict between Windows and Linux is handled differently. ToDo.