LDAP Over SSL vs LDAP with STARTTLS
There are two ways to encrypt LDAP connections with SSL/TLS.
Traditionally, LDAP connections that needed to be encrypted were handled on a separate port, typically 636. The entire connection would be wrapped with SSL/TLS. This process, called LDAP over SSL, uses the ldaps:// protocol. This method of encryption is now deprecated.
STARTTLS is an alternative approach that is now the preferred method of encrypting an LDAP connection. STARTTLS "upgrades" a non-encrypted connection by wrapping it with SSL/TLS after/during the connection process. This allows unencrypted and encrypted connections to be handled by the same port. This guide will utilize STARTTLS to encrypt connections.
This is not the proper way to create a certificate chain.
1. create a certificate authority 2. create a server certificate 3. sign the server certificate with the CA 4. extract the password from server certificate into a key
https://www.digitalocean.com/community/tutorials/how-to-encrypt-openldap-connections-using-starttls
Generate a certificate OK
TMPDIR=/etc/openldap/ssl/templates PRIVDIR=/etc/openldap/ssl/private CERTDIR=/etc/openldap/certs mkdir -p $TMPDIR mkdir -p $PRIVDIR mkdir -p $CERTDIR cat > $TMPDIR/ca_server.conf << EOF cn = LDAP Server CA ca cert_signing_key EOF cat > $TMPDIR/ldap_server.conf << EOF organization = "My Company Luxembourg" cn = lnxldap1.tst.com tls_www_server encryption_key signing_key expiration_days = 3652 EOF certtool -p --outfile $PRIVDIR/ca_server.key certtool -s --load-privkey $PRIVDIR/ca_server.key --template $TMPDIR/ca_server.conf --outfile $CERTDIR/ca_server.pem certtool -p --sec-param high --outfile $PRIVDIR/ldap_server.key certtool -c --load-privkey $PRIVDIR/ldap_server.key --load-ca-certificate $CERTDIR/ca_server.pem --load-ca-privkey $PRIVDIR/ca_server.key --template $TMPDIR/ldap_server.conf --outfile $CERTDIR/ldap_server.pem chmod 640 $PRIVDIR/ldap_server.key chown :ldap $PRIVDIR/ldap_server.key ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF dn: cn=config changetype: modify replace: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/openldap/certs/ca_server.pem - replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/openldap/certs/ldap_server.pem - replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/openldap/ssl/private/ldap_server.key EOF service slapd force-reload
install certtool
# yum -y install gnutls-utils
install certtool
# certtool --generate-privkey --outfile /etc/pki/CA/private/ca-key.key # certtool --generate-self-signed --load-privkey /etc/pki/CA/private/ca-key.key --outfile /etc/pki/CA/certs/ca-cert.pem --template /etc/pki/CA/private/cert.cfg # certtool --generate-privkey --outfile /etc/pki/tls/private/ldap.key # certtool --generate-certificate --load-privkey /etc/pki/tls/private/ldap.key --outfile /etc/pki/tls/certs/ldap.pem --load-ca-certificate /etc/pki/CA/certs/ca-cert.pem --load-ca-privkey /etc/pki/CA/private/ca-key.key --template /etc/pki/CA/private/cert.cfg
cat cert.cfg
# X.509 Certificate options # # DN options # The organization of the subject. organization = "Koko inc." # The organizational unit of the subject. unit = "sleeping dept." # The locality of the subject. # locality = # The state of the certificate owner. state = "Attiki" # The country of the subject. Two letter code. country = GR # The common name of the certificate owner. cn = "Cindy Lauper" # A user id of the certificate owner. #uid = "clauper" # Set domain components #dc = "name" #dc = "domain" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12 Dr." #dn_oid = "2.5.4.65 jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # An alternative way to set the certificate's distinguished name directly # is with the "dn" option. The attribute names allowed are: # C (country), street, O (organization), OU (unit), title, CN (common name), # L (locality), ST (state), placeOfBirth, gender, countryOfCitizenship, # countryOfResidence, serialNumber, telephoneNumber, surName, initials, # generationQualifier, givenName, pseudonym, dnQualifier, postalCode, name, # businessCategory, DC, UID, jurisdictionOfIncorporationLocalityName, # jurisdictionOfIncorporationStateOrProvinceName, # jurisdictionOfIncorporationCountryName, XmppAddr, and numeric OIDs. #dn = "cn = Nikos,st = New\, Something,C=GR,surName=Mavrogiannopoulos,2.5.4.9=Arkadias" # The serial number of the certificate # Comment the field for a time-based serial number. serial = 007 # In how many days, counting from today, this certificate will expire. # Use -1 if there is no expiration date. expiration_days = 700 # Alternatively you may set concrete dates and time. The GNU date string # formats are accepted. See: # http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html #activation_date = "2004-02-29 16:21:42" #expiration_date = "2025-02-29 16:24:41" # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An othername defined by an OID and a hex encoded string #other_name = "1.3.6.1.5.2.2 302ca00d1b0b56414e5245494e2e4f5247a11b3019a006020400000002a10f300d1b047269636b1b0561646d696e" #other_name_utf8 = "1.2.4.5.6 A UTF8 string" #other_name_octet = "1.2.4.5.6 A string that will be encoded as ASN.1 octet string" # Allows writing an XmppAddr Identifier #xmpp_name = juliet@im.example.com # Names used in PKINIT #krb5_principal = user@REALM.COM #krb5_principal = HTTP/user@REALM.COM # A subject alternative name URI #uri = "http://www.example.com" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "none@none.org" # TLS feature (rfc7633) extension. That can is used to indicate mandatory TLS # extension features to be provided by the server. In practice this is used # to require the Status Request (extid: 5) extension from the server. That is, # to require the server holding this certificate to provide a stapled OCSP response. # You can have multiple lines for multiple TLS features. # To ask for OCSP status request use: #tls_feature = 5 # Challenge password used in certificate requests challenge_password = 123456 # Password when encrypting a private key #password = secret # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "http://www.getcrl.crl/getcrl/" # Whether this is a CA certificate or not #ca # Subject Unique ID (in hex) #subject_unique_id = 00153224 # Issuer Unique ID (in hex) #issuer_unique_id = 00153225 #### Key usage # The following key usage flags are used by CAs and end certificates # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). This is the digitalSignature flag # in RFC5280 terminology. signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is preferred to use different # keys for encryption and signing. This is the keyEncipherment flag # in RFC5280 terminology. encryption_key # Whether this key will be used to sign other certificates. The # keyCertSign flag in RFC5280 terminology. #cert_signing_key # Whether this key will be used to sign CRLs. The # cRLSign flag in RFC5280 terminology. #crl_signing_key # The keyAgreement flag of RFC5280. It's purpose is loosely # defined. Not use it unless required by a protocol. #key_agreement # The dataEncipherment flag of RFC5280. It's purpose is loosely # defined. Not use it unless required by a protocol. #data_encipherment # The nonRepudiation flag of RFC5280. It's purpose is loosely # defined. Not use it unless required by a protocol. #non_repudiation #### Extended key usage (key purposes) # The following extensions are used in an end certificate # to clarify its purpose. Some CAs also use it to indicate # the types of certificates they are purposed to sign. # Whether this certificate will be used for a TLS client; # this sets the id-kp-serverAuth (1.3.6.1.5.5.7.3.1) of # extended key usage. #tls_www_client # Whether this certificate will be used for a TLS server; # This sets the id-kp-clientAuth (1.3.6.1.5.5.7.3.2) of # extended key usage. #tls_www_server # Whether this key will be used to sign code. This sets the # id-kp-codeSigning (1.3.6.1.5.5.7.3.3) of extended key usage # extension. #code_signing_key # Whether this key will be used to sign OCSP data. This sets the # id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) of extended key usage extension. #ocsp_signing_key # Whether this key will be used for time stamping. This sets the # id-kp-timeStamping (1.3.6.1.5.5.7.3.8) of extended key usage extension. #time_stamping_key # Whether this key will be used for email protection. This sets the # id-kp-emailProtection (1.3.6.1.5.5.7.3.4) of extended key usage extension. #email_protection_key # Whether this key will be used for IPsec IKE operations (1.3.6.1.5.5.7.3.17). #ipsec_ike_key ## adding custom key purpose OIDs # for microsoft smart card logon # key_purpose_oid = 1.3.6.1.4.1.311.20.2.2 # for email protection # key_purpose_oid = 1.3.6.1.5.5.7.3.4 # for any purpose (must not be used in intermediate CA certificates) # key_purpose_oid = 2.5.29.37.0 ### end of key purpose OIDs ### Adding arbitrary extensions # This requires to provide the extension OIDs, as well as the extension data in # hex format. The following two options are available since GnuTLS 3.5.3. #add_extension = "1.2.3.4 0x0AAB01ACFE" # As above but encode the data as an octet string #add_extension = "1.2.3.4 octet_string(0x0AAB01ACFE)" # For portability critical extensions shouldn't be set to certificates. #add_critical_extension = "5.6.7.8 0x1AAB01ACFE" # When generating a certificate from a certificate # request, then honor the extensions stored in the request # and store them in the real certificate. #honor_crq_extensions # Alternatively only specific extensions can be copied. #honor_crq_ext = 2.5.29.17 #honor_crq_ext = 2.5.29.15 # Path length contraint. Sets the maximum number of # certificates that can be used to certify this certificate. # (i.e. the certificate chain length) #path_len = -1 #path_len = 2 # OCSP URI # ocsp_uri = http://my.ocsp.server/ocsp # CA issuers URI # ca_issuers_uri = http://my.ca.issuer # Certificate policies #policy1 = 1.3.6.1.4.1.5484.1.10.99.1.0 #policy1_txt = "This is a long policy to summarize" #policy1_url = http://www.example.com/a-policy-to-read #policy2 = 1.3.6.1.4.1.5484.1.10.99.1.1 #policy2_txt = "This is a short policy" #policy2_url = http://www.example.com/another-policy-to-read # Name constraints # DNS #nc_permit_dns = example.com #nc_exclude_dns = test.example.com # EMAIL #nc_permit_email = "nmav@ex.net" # Exclude subdomains of example.com #nc_exclude_email = .example.com # Exclude all e-mail addresses of example.com #nc_exclude_email = example.com # IP #nc_permit_ip = 192.168.0.0/16 #nc_exclude_ip = 192.168.5.0/24 #nc_permit_ip = fc0a:eef2:e7e7:a56e::/64 # Options for proxy certificates #proxy_policy_language = 1.3.6.1.5.5.7.21.1 # Options for generating a CRL # The number of days the next CRL update will be due. # next CRL update will be in 43 days #crl_next_update = 43 # this is the 5th CRL by this CA # Comment the field for a time-based number. #crl_number = 5 # Specify the update dates more precisely. #crl_this_update_date = "2004-02-29 16:21:42" #crl_next_update_date = "2025-02-29 16:24:41" # The date that the certificates will be made seen as # being revoked. #crl_revocation_date = "2025-02-29 16:24:41"
chmod 640 /etc/pki/tls/certs/ldap.pem chmod 640 /etc/pki/tls/private/ldap.key chmod 644 /etc/pki/CA/certs/ca-cert.pem chgrp ldap /etc/pki/tls/certs/ldap.pem chgrp ldap /etc/pki/tls/private/ldap.key chgrp ldap /etc/pki/CA/certs/ca-cert.pem
Verify the certificate:
# certtool --certificate-info --infile /etc/pki/CA/certs/ca-cert.pem # openssl x509 -noout -text -in /etc/pki/CA/certs/ca-cert.pem
Apply olcTLS directive in LDAP server configuration:
[root@rhldap1 private]# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF dn: cn=config changetype: modify replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/pki/tls/certs/ldap.pem EOF modifying entry "cn=config" [root@rhldap1 private]# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF dn: cn=config changetype: modify replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/pki/tls/private/ldap.key EOF modifying entry "cn=config" [root@rhldap1 private]# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF dn: cn=config changetype: modify add: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/pki/CA/certs/ca-cert.pem EOF modifying entry "cn=config" [root@rhldap1 private]# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config | grep olcTLS SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 olcTLSCipherSuite: HIGH:MEDIUM:-SSLv2 olcTLSVerifyClient: demand olcTLSCertificateFile: /etc/pki/tls/certs/ldap.pem olcTLSCertificateKeyFile: /etc/pki/tls/private/ldap.key olcTLSCACertificateFile: /etc/pki/CA/certs/ca-cert.pem
Check you config
[root@rhldap1 private]# gnutls-cli-debug -p 636 localhost unknown protocol ldaps Checking for SSL 3.0 support... yes unknown protocol ldaps Checking whether %COMPAT is required... no unknown protocol ldaps Checking for TLS 1.0 support... yes unknown protocol ldaps Checking for TLS 1.1 support... yes unknown protocol ldaps Checking fallback from TLS 1.1 to... N/A Checking for TLS 1.2 support... yes unknown protocol ldaps Checking whether we need to disable TLS 1.2... N/A Checking whether we need to disable TLS 1.1... N/A Checking whether we need to disable TLS 1.0... N/A Checking for Safe renegotiation support... no unknown protocol ldaps Checking for Safe renegotiation support (SCSV)... yes unknown protocol ldaps Checking for HTTPS server name... not checked unknown protocol ldaps Checking for version rollback bug in RSA PMS... dunno unknown protocol ldaps Checking for version rollback bug in Client Hello... no unknown protocol ldaps Checking whether the server ignores the RSA PMS version... yes unknown protocol ldaps Checking whether the server can accept Hello Extensions... yes unknown protocol ldaps Checking whether the server can accept HeartBeat Extension... yes unknown protocol ldaps Checking whether the server can accept small records (512 bytes)... yes unknown protocol ldaps Checking whether the server can accept cipher suites not in SSL 3.0 spec... yes unknown protocol ldaps Checking whether the server can accept a bogus TLS record version in the client hello... yes unknown protocol ldaps Checking for certificate information... N/A Checking for trusted CAs... N/A Checking whether the server understands TLS closure alerts... partially unknown protocol ldaps Checking whether the server supports session resumption... no unknown protocol ldaps Checking for anonymous authentication support... no unknown protocol ldaps Checking anonymous Diffie-Hellman group info... N/A Checking for ephemeral Diffie-Hellman support... yes unknown protocol ldaps Checking ephemeral Diffie-Hellman group info... N/A Checking for ephemeral EC Diffie-Hellman support... yes unknown protocol ldaps Checking ephemeral EC Diffie-Hellman group info... Curve SECP256R1 unknown protocol ldaps Checking for AES-128-GCM cipher support... yes unknown protocol ldaps Checking for AES-128-CBC cipher support... yes unknown protocol ldaps Checking for CAMELLIA-128-GCM cipher support... no unknown protocol ldaps Checking for CAMELLIA-128-CBC cipher support... yes unknown protocol ldaps Checking for 3DES-CBC cipher support... yes unknown protocol ldaps Checking for ARCFOUR 128 cipher support... yes unknown protocol ldaps Checking for MD5 MAC support... yes unknown protocol ldaps Checking for SHA1 MAC support... yes unknown protocol ldaps Checking for SHA256 MAC support... yes unknown protocol ldaps Checking for ZLIB compression support... no unknown protocol ldaps Checking for max record size... no unknown protocol ldaps Checking for OpenPGP authentication support... no
[root@rhldap1 private]# nmap -Pn -p T:636 --script ssl-enum-ciphers localhost Starting Nmap 6.40 ( http://nmap.org ) at 2016-12-13 15:01 CET Nmap scan report for localhost (127.0.0.1) Host is up (-1400s latency). Other addresses for localhost (not scanned): 127.0.0.1 PORT STATE SERVICE 636/tcp open ldapssl | ssl-enum-ciphers: | TLSv1.2: | ciphers: | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong | TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - strong | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - strong | TLS_DHE_RSA_WITH_AES_256_CBC_SHA - strong | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - strong | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - strong | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - strong | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - strong | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - strong | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - strong | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - strong | TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong | TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong | TLS_RSA_WITH_AES_128_CBC_SHA - strong | TLS_RSA_WITH_AES_128_CBC_SHA256 - strong | TLS_RSA_WITH_AES_128_GCM_SHA256 - strong | TLS_RSA_WITH_AES_256_CBC_SHA - strong | TLS_RSA_WITH_AES_256_CBC_SHA256 - strong | TLS_RSA_WITH_AES_256_GCM_SHA384 - strong | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - strong | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - strong | TLS_RSA_WITH_RC4_128_MD5 - strong | TLS_RSA_WITH_RC4_128_SHA - strong | TLS_RSA_WITH_SEED_CBC_SHA - strong | compressors: | NULL |_ least strength: strong Nmap done: 1 IP address (1 host up) scanned in 0.71 seconds
https://www.gnutls.org/manual/html_node/certtool-Invocation.html
https://help.ubuntu.com/lts/serverguide/openldap-server.html