Trusting TLS Certificates

Jurjen Bokma

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

Abstract

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 mydomain.mycompany.com:636 -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
    DONE
    root@freebsdhost:~# openssl x509 -in server.cert -text -noout
    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number:
    6b:00:00:00:55:75:fd:a6:ba:10:85:c3:5e:00:00:00:00:00:55
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: DC=com, DC=mycompany, DC=mydomain, CN=MyCompany Issuing CA 01
    <snip>
    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
    <snip>

  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://mydomain.mycompany.com -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
    <snip>

  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
    -----BEGIN CERTIFICATE-----
    <snip>
      

  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 mydomain.mycompany.com:636 < /dev/null
          <snip>
    Verify return code: 0 (ok)
    ---
          DONE

  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 mydomain.mycompany.com       
    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://mydomain.mycompany.com -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.