diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index e6557f6a0..ca33e5698 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -1572,7 +1572,7 @@ def cert_summary(msg, certs, indent=' '): def get_certs_from_ldap(server, base_dn, realm, ca_enabled): ldap_uri = ipaldap.get_ldap_uri(server) - conn = ipaldap.LDAPClient(ldap_uri, sasl_nocanon=True) + conn = ipaldap.LDAPClient(ldap_uri) try: conn.gssapi_bind() certs = certstore.get_ca_certs(conn, base_dn, realm, ca_enabled) diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py index dcac32c31..58a6437d8 100644 --- a/ipapython/ipaldap.py +++ b/ipapython/ipaldap.py @@ -20,6 +20,7 @@ # import binascii +import errno import logging import time import datetime @@ -87,28 +88,34 @@ if six.PY2 and hasattr(ldap, 'LDAPBytesWarning'): def ldap_initialize(uri, cacertfile=None): """Wrapper around ldap.initialize() + + The function undoes global and local ldap.conf settings that may cause + issues or reduce security: + + * Canonization of SASL host names is disabled. + * With cacertfile=None, the connection uses OpenSSL's default verify + locations, also known as system-wide trust store. + * Cert validation is enforced. + * SSLv2 and SSLv3 are disabled. """ conn = ldap.initialize(uri) + # Do not perform reverse DNS lookups to canonicalize SASL host names + conn.set_option(ldap.OPT_X_SASL_NOCANON, ldap.OPT_ON) + if not uri.startswith('ldapi://'): if cacertfile: + if not os.path.isfile(cacertfile): + raise IOError(errno.ENOENT, cacertfile) conn.set_option(ldap.OPT_X_TLS_CACERTFILE, cacertfile) - newctx = True - else: - newctx = False - req_cert = conn.get_option(ldap.OPT_X_TLS_REQUIRE_CERT) - if req_cert != ldap.OPT_X_TLS_DEMAND: - # libldap defaults to cert validation, but the default can be - # overridden in global or user local ldap.conf. - conn.set_option( - ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND - ) - newctx = True - - # reinitialize TLS context - if newctx: - conn.set_option(ldap.OPT_X_TLS_NEWCTX, 0) + # SSLv3 and SSLv2 are insecure + conn.set_option(ldap.OPT_X_TLS_PROTOCOL_MIN, 0x301) # TLS 1.0 + # libldap defaults to cert validation, but the default can be + # overridden in global or user local ldap.conf. + conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND) + # reinitialize TLS context to materialize settings + conn.set_option(ldap.OPT_X_TLS_NEWCTX, 0) return conn @@ -733,7 +740,7 @@ class LDAPClient(object): def __init__(self, ldap_uri, start_tls=False, force_schema_updates=False, no_schema=False, decode_attrs=True, cacert=None, - sasl_nocanon=False): + sasl_nocanon=True): """Create LDAPClient object. :param ldap_uri: The LDAP URI to connect to @@ -1120,8 +1127,10 @@ class LDAPClient(object): def _connect(self): with self.error_handler(): conn = ldap_initialize(self.ldap_uri, cacertfile=self._cacert) - if self._sasl_nocanon: - conn.set_option(ldap.OPT_X_SASL_NOCANON, ldap.OPT_ON) + # SASL_NOCANON is set to ON in Fedora's default ldap.conf and + # in the ldap_initialize() function. + if not self._sasl_nocanon: + conn.set_option(ldap.OPT_X_SASL_NOCANON, ldap.OPT_OFF) if self._start_tls: conn.start_tls_s() diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index e3aa9f6a6..2e5a7bf6c 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -728,11 +728,8 @@ class DomainValidator(object): conn = ipaldap.LDAPClient( ldap_uri, no_schema=True, - decode_attrs=False, - sasl_nocanon=True) - # sasl_nocanon used to avoid hard requirement for PTR - # records pointing back to the same host name - + decode_attrs=False + ) conn.gssapi_bind() if basedn is None: