How to test:
1) Add new naming context (suffix) to your LDAP database with installed
IPA (see attached LDIF). The server should return the new suffix as the
first one. You can change with its base DN if it does not.
2) Install IPA client against the server. ipa-client-install should the
LDAP server as the IPA one only if the patch is applied on the client

---

When LDAP server contains more that one suffixes, the ipa client
installation does not detect it as IPA server and fails to install.
Fix ipa server discovery so that it correctly searches all naming
contexts for the IPA one.

https://fedorahosted.org/freeipa/ticket/1868

>From 51fd1fc23fe0a65ff63e20b9314f385158e22510 Mon Sep 17 00:00:00 2001
From: Martin Kosek <mko...@redhat.com>
Date: Thu, 29 Sep 2011 15:10:03 +0200
Subject: [PATCH] ipa-client assumes a single namingcontext

When LDAP server contains more that one suffixes, the ipa client
installation does not detect it as IPA server and fails to install.
Fix ipa server discovery so that it correctly searches all naming
contexts for the IPA one.

https://fedorahosted.org/freeipa/ticket/1868
---
 ipa-client/ipaclient/ipadiscovery.py |   24 +++----------------
 ipapython/ipautil.py                 |   42 ++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py
index 9d909fd1323ba29527ef6f8b9788135c42fd4322..6b4e0e2acc1ab9e1e7c9d7ae9fef315a25aaf919 100644
--- a/ipa-client/ipaclient/ipadiscovery.py
+++ b/ipa-client/ipaclient/ipadiscovery.py
@@ -24,7 +24,7 @@ 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
 
 
 NOT_FQDN = -1
@@ -220,25 +220,9 @@ 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]
-
-            logging.debug("Search for (info=*) in "+self.basedn+"(base)")
-            lret = lh.search_s(self.basedn, ldap.SCOPE_BASE, "(info=IPA*)")
-            if not lret:
-                return []
-            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 []
+            # get IPA base DN
+            logging.debug("Search LDAP server for IPA base DN")
+            self.basedn = get_ipa_basedn(lh)
 
             #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 490981a4a903a68996e306548f9b16c64feed8ac..64b8dea004f4d44ab225c1c2cf1ca5d00b42302a 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,8 @@ import stat
 import shutil
 import urllib2
 import socket
+import ldap
+from ldap import LDAPError
 
 from ipapython import ipavalidate
 from types import *
@@ -1127,3 +1131,41 @@ def bind_port_responder(port, socket_stream=True, socket_timeout=None, responder
     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
+    """
+    try:
+        entries = conn.search_ext_s(
+            '', scope=ldap.SCOPE_BASE, attrlist=['namingcontexts']
+        )
+    except ldap.LDAPError, e:
+        logging.error('Cannot retrieve naming contexts from LDAP server: %s' % str(e))
+        return None
+
+    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.LDAPError, e:
+            logging.debug("Check of '%s' was not successful: %s" % (context, str(e)))
+            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
+
-- 
1.7.6.2

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to