diff --git a/install/share/Makefile.am b/install/share/Makefile.am index 547729e17..8c7522b81 100644 --- a/install/share/Makefile.am +++ b/install/share/Makefile.am @@ -94,6 +94,7 @@ dist_app_DATA = \ ipa-kdc-proxy.conf.template \ ipa-pki-proxy.conf.template \ ipa-rewrite.conf.template \ + min-ssf.ldif \ $(NULL) kdcproxyconfdir = $(IPA_SYSCONF_DIR)/kdcproxy diff --git a/install/share/min-ssf.ldif b/install/share/min-ssf.ldif new file mode 100644 index 000000000..1c2566f84 --- /dev/null +++ b/install/share/min-ssf.ldif @@ -0,0 +1,14 @@ +# config +# pretend SSF for LDAPI connections +# nsslapd-localssf must be equal to or greater than nsslapd-minssf +dn: cn=config +changetype: modify +replace: nsslapd-localssf +nsslapd-localssf: 256 + +# minimum security strength factor for SASL and TLS +# 56 is considered weak, but some old clients announce wrong SSF. +dn: cn=config +changetype: modify +replace: nsslapd-minssf +nsslapd-minssf: 56 diff --git a/ipalib/constants.py b/ipalib/constants.py index 3bb0628fb..2f66fa958 100644 --- a/ipalib/constants.py +++ b/ipalib/constants.py @@ -309,6 +309,9 @@ TLS_VERSIONS = [ ] TLS_VERSION_MINIMAL = "tls1.0" +# minimum SASL secure strength factor for LDAP connections +# 56 provides backwards compatibility with old libraries. +LDAP_SSF_MIN_THRESHOLD = 56 # Use cache path USER_CACHE_PATH = ( diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py index 9ff443fe4..d9d67be1d 100644 --- a/ipapython/ipaldap.py +++ b/ipapython/ipaldap.py @@ -43,7 +43,9 @@ import six # pylint: disable=ipa-forbidden-import from ipalib import errors, x509, _ -from ipalib.constants import LDAP_GENERALIZED_TIME_FORMAT +from ipalib.constants import ( + LDAP_GENERALIZED_TIME_FORMAT, LDAP_SSF_MIN_THRESHOLD +) # pylint: enable=ipa-forbidden-import from ipaplatform.paths import paths from ipapython.ipautil import format_netloc, CIDict @@ -103,7 +105,8 @@ def realm_to_ldapi_uri(realm_name): return 'ldapi://' + ldapurl.ldapUrlEscape(socketname) -def ldap_initialize(uri, cacertfile=None): +def ldap_initialize(uri, cacertfile=None, + ssf_min_threshold=LDAP_SSF_MIN_THRESHOLD): """Wrapper around ldap.initialize() The function undoes global and local ldap.conf settings that may cause @@ -114,6 +117,10 @@ def ldap_initialize(uri, cacertfile=None): locations, also known as system-wide trust store. * Cert validation is enforced. * SSLv2 and SSLv3 are disabled. + * Require a minimum SASL security factor of 56. That level ensures + data integrity and confidentiality. Although at least AES128 is + enforced pretty much everywhere, 56 is required for backwards + compatibility with systems that announce wrong SSF. """ conn = ldap.initialize(uri) @@ -121,6 +128,12 @@ def ldap_initialize(uri, cacertfile=None): conn.set_option(ldap.OPT_X_SASL_NOCANON, ldap.OPT_ON) if not uri.startswith('ldapi://'): + # require a minimum SSF for TCP connections, but don't lower SSF_MIN + # if the current value is already larger. + cur_min_ssf = conn.get_option(ldap.OPT_X_SASL_SSF_MIN) + if cur_min_ssf < ssf_min_threshold: + conn.set_option(ldap.OPT_X_SASL_SSF_MIN, ssf_min_threshold) + if cacertfile: if not os.path.isfile(cacertfile): raise IOError(errno.ENOENT, cacertfile) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 72ae650b4..5eebdb09b 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -324,6 +324,8 @@ class DsInstance(service.Service): else: self.step("importing CA certificates from LDAP", self.__import_ca_certs) + # set min SSF after DS is configured for TLS + self.step("require minimal SSF", self.__min_ssf) self.step("restarting directory server", self.__restart_instance) self.start_creation() @@ -1241,6 +1243,9 @@ class DsInstance(service.Service): dm_password=self.dm_password ) + def __min_ssf(self): + self._ldap_mod("min-ssf.ldif") + def __add_sudo_binduser(self): self._ldap_mod("sudobind.ldif", self.sub_dict)