diff options
-rw-r--r-- | ipa-client/ipaclient/ipadiscovery.py | 32 | ||||
-rw-r--r-- | ipapython/ipautil.py | 37 |
2 files changed, 51 insertions, 18 deletions
diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py index c5567822e..f6c13fb67 100644 --- a/ipa-client/ipaclient/ipadiscovery.py +++ b/ipa-client/ipaclient/ipadiscovery.py @@ -24,7 +24,8 @@ import ipapython.dnsclient import tempfile import ldap from ldap import LDAPError -from ipapython.ipautil import run, CalledProcessError, valid_ip +from ipapython.ipautil import run, CalledProcessError, valid_ip, get_ipa_basedn, \ + realm_to_suffix NOT_FQDN = -1 @@ -176,9 +177,15 @@ class IPADiscovery: self.server = ldapret[1] self.realm = ldapret[2] - if ldapret[0] == NO_ACCESS_TO_LDAP and self.realm == None: + if ldapret[0] == NO_ACCESS_TO_LDAP and self.realm is None: # Assume realm is the same as domain.upper() self.realm = self.domain.upper() + logging.debug("Assuming realm is the same as domain: %s" % self.realm) + + if ldapret[0] == NO_ACCESS_TO_LDAP and self.basedn is None: + # Generate suffix from realm + self.basedn = realm_to_suffix(self.realm) + logging.debug("Generate basedn from realm: %s" % self.basedn) return ldapret[0] @@ -229,25 +236,14 @@ class IPADiscovery: lh.start_tls_s() lh.simple_bind_s("","") - logging.debug("Search rootdse") - lret = lh.search_s("", ldap.SCOPE_BASE, "(objectClass=*)") - for lattr in lret[0][1]: - if lattr.lower() == "namingcontexts": - self.basedn = lret[0][1][lattr][0] + # get IPA base DN + logging.debug("Search LDAP server for IPA base DN") + basedn = get_ipa_basedn(lh) - logging.debug("Search for (info=*) in "+self.basedn+"(base)") - lret = lh.search_s(self.basedn, ldap.SCOPE_BASE, "(info=IPA*)") - if not lret: + if basedn is None: return [NOT_IPA_SERVER] - logging.debug("Found: "+str(lret)) - for lattr in lret[0][1]: - if lattr.lower() == "info": - linfo = lret[0][1][lattr][0].lower() - break - - if not linfo or linfo.lower() != 'ipa v2.0': - return [NOT_IPA_SERVER] + self.basedn = basedn #search and return known realms logging.debug("Search for (objectClass=krbRealmContainer) in "+self.basedn+"(sub)") diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index 72cf400f9..cfc979edb 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -22,6 +22,8 @@ PLUGINS_SHARE_DIR = "/usr/share/ipa/plugins" GEN_PWD_LEN = 12 +IPA_BASEDN_INFO = 'ipa v2.0' + import string import tempfile import logging @@ -33,6 +35,7 @@ import stat import shutil import urllib2 import socket +import ldap from ipapython import ipavalidate from types import * @@ -1126,3 +1129,37 @@ def bind_port_responder(port, socket_stream=True, socket_timeout=None, responder s.sendto(responder_data, addr) finally: s.close() + +def get_ipa_basedn(conn): + """ + Get base DN of IPA suffix in given LDAP server. + + None is returned if the suffix is not found + + :param conn: Bound LDAP connection that will be used for searching + """ + entries = conn.search_ext_s( + '', scope=ldap.SCOPE_BASE, attrlist=['namingcontexts'] + ) + + contexts = entries[0][1]['namingcontexts'] + for context in contexts: + logging.debug("Check if naming context '%s' is for IPA" % context) + try: + entry = conn.search_s(context, ldap.SCOPE_BASE, "(info=IPA*)") + except ldap.NO_SUCH_OBJECT: + logging.debug("LDAP server did not return info attribute to check for IPA version") + continue + if len(entry) == 0: + logging.debug("Info attribute with IPA server version not found") + continue + info = entry[0][1]['info'][0].lower() + if info != IPA_BASEDN_INFO: + logging.debug("Detected IPA server version (%s) did not match the client (%s)" \ + % (info, IPA_BASEDN_INFO)) + continue + logging.debug("Naming context '%s' is a valid IPA context" % context) + return context + + return None + |