On Thu, 2011-09-29 at 17:56 +0200, Martin Kosek wrote:
> On Thu, 2011-09-29 at 11:44 -0400, Simo Sorce wrote:
> > On Thu, 2011-09-29 at 17:41 +0200, Martin Kosek wrote:
> > > On Wed, 2011-09-28 at 18:43 -0400, Simo Sorce wrote:
> > > > This patch allows ipa-client-install to successfully complete if
> > > > anonymous access is not allowed on the LDAP server.
> > > > 
> > > > I have tested this by changing the value of
> > > > nsslapd-allow-anonymous-access from 'on' to 'rootdse' in cn=config
> > > > See NOTE about this option.
> > > > 
> > > > This patch warns the user that full verification of the LDAP server was
> > > > not possible and may even assume realm is domain.upper() if DNS
> > > > discovery is not possible.
> > > > 
> > > > With these caveats the installation on a DNS compliant domain works fine
> > > > against a IPA server with anonynous access to LDAP disabled with this
> > > > patch.
> > > > 
> > > > Fixes #1881
> > > > 
> > > > Simo.
> > > > 
> > > > 
> > > > NOTE: Setting rootdse nsslapd-allow-anonymous-access is standards
> > > > compliant as it still allows access anonymously to the rootdse entry.
> > > > Setting this option to 'off' prevents access even to rootdse and is not
> > > > a good idea (the client doesn't know what auth methods are avilable to
> > > > authenticate w/o access to rootdse)
> > > 
> > > NACK. The approach looks good, but I found several errors:
> > > 
> > > 1) IPA discovery for servers with anonymous access _allowed_ is broken
> > > because of the following lines:
> > > 
> > > 
> > > +        if ldapret[0] == 0:
> > > +            self.server = ldapret[0] <<< This should be ldapret[1]
> > > +            self.realm = ldapret[1] <<<< This should be ldapret[2]
> > > ...
> > 
> > Ouch I swear I was sure I changed those lines ...
> > 
> > > @@ -259,24 +268,29 @@ class IPADiscovery:
> > >                      if trealm == r:
> > >                          return [thost, trealm]  <<<<< This should be [0, 
> > > thost, trealm]
> > >                  # must match or something is very wrong
> > > -                return []
> > > +                return [REALM_NOT_FOUND]
> > > 
> > > 
> > > 2) If anonymous access is forbidden, IPA base DN cannot be searched
> > > since we can't read it's contents and check that it belongs to IPA. If
> > > you apply my patch 130, you will see this error:
> > > 
> > > # ipa-client-install --server vm-103.idm.lab.bos.redhat.com --domain 
> > > idm.lab.bos.redhat.com -p admin -w kokos123 
> > > Warning: Anonymous access to the LDAP server is disabled.
> > > Proceeding without strict verification.
> > > Note: This is not an error if anonymous access has been explicitly 
> > > restricted.
> > > DNS domain '' is not configured for automatic KDC address lookup.
> > > KDC address will be set to fixed value.
> > > 
> > > Discovery was successful!
> > > Hostname: vm-050.idm.lab.bos.redhat.com
> > > Realm: 
> > > DNS Domain: idm.lab.bos.redhat.com
> > > IPA Server: vm-103.idm.lab.bos.redhat.com
> > > Traceback (most recent call last):
> > >   File "/usr/sbin/ipa-client-install", line 1148, in <module>
> > >     sys.exit(main())
> > >   File "/usr/sbin/ipa-client-install", line 1137, in main
> > >     rval = install(options, env, fstore, statestore)
> > >   File "/usr/sbin/ipa-client-install", line 866, in install
> > >     print "BaseDN: "+cli_basedn
> > > TypeError: cannot concatenate 'str' and 'NoneType' objects
> > > 
> > > 
> > > We will have to add user a possibility to pass base DN for IPA since we
> > > cannot check it ourselves. Something like --basedn=BASEDN. I can do it
> > > in a scope of my patch after you fix 1) if you don't feel comfortable
> > > hacking ipa-client-install.
> > 
> > The basedn comes from rootdse, that one can be searched. (if you set the
> > option in DS to off and din't read my note, you got what you deserve :-)
> > 
> > Simo.
> > 
> 
> I read every word of it :-) My point was that you can have more
> databases (basedns, suffixes) configured on the server and when the
> anonymous access is disabled we cannot check which one is for IPA.
> That's what my patch 130 fixes. Before it, we just took the first
> suffix.

Ok this patch fixes the problems above with the wrong returns and the
issue with the realm being empty (the dns search function for kdb was
setting realm to "" instead of None by deafult.

The rest I think is on your side to deal with.

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York
>From 54c19bac1b2c0dcf8525936b440024e141d3098c Mon Sep 17 00:00:00 2001
From: Simo Sorce <sso...@redhat.com>
Date: Wed, 28 Sep 2011 16:31:38 -0400
Subject: [PATCH] ipa-client-install: Fix joining when LDAP access is
 restricted

Fixes: https://fedorahosted.org/freeipa/ticket/1881
---
 ipa-client/ipa-install/ipa-client-install |    7 +++
 ipa-client/ipaclient/ipadiscovery.py      |   58 ++++++++++++++++++-----------
 2 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 5ea055ff1967cc819baafd7bd3ae455b25b41e32..efa39cd6f58e4b41d65c0892c4cb6367892a206b 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -818,6 +818,13 @@ def install(options, env, fstore, statestore):
     if ret == ipadiscovery.NOT_IPA_SERVER:
         print >>sys.stderr, "%s is not an IPA v2 Server." % cli_server
         return CLIENT_INSTALL_ERROR
+
+    if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
+        print "Warning: Anonymous access to the LDAP server is disabled."
+        print "Proceeding without strict verification."
+        print "Note: This is not an error if anonymous access has been explicitly restricted."
+        ret = 0
+
     if ret != 0:
         print >>sys.stderr, "Failed to verify that "+cli_server+" is an IPA Server."
         print >>sys.stderr, "This may mean that the remote server is not up or is not reachable"
diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py
index 9d909fd1323ba29527ef6f8b9788135c42fd4322..c5567822e0274660690b7c8d65620874d6341ce7 100644
--- a/ipa-client/ipaclient/ipadiscovery.py
+++ b/ipa-client/ipaclient/ipadiscovery.py
@@ -31,7 +31,9 @@ NOT_FQDN = -1
 NO_LDAP_SERVER = -2
 REALM_NOT_FOUND = -3
 NOT_IPA_SERVER = -4
+NO_ACCESS_TO_LDAP = -5
 BAD_HOST_CONFIG = -10
+UNKNOWN_ERROR = -15
 
 class IPADiscovery:
 
@@ -170,13 +172,15 @@ class IPADiscovery:
         # check ldap now
         ldapret = self.ipacheckldap(self.server, self.realm)
 
-        if not ldapret:
-            return NOT_IPA_SERVER
+        if ldapret[0] == 0:
+            self.server = ldapret[1]
+            self.realm = ldapret[2]
 
-        self.server = ldapret[0]
-        self.realm = ldapret[1]
+        if ldapret[0] == NO_ACCESS_TO_LDAP and self.realm == None:
+            # Assume realm is the same as domain.upper()
+            self.realm = self.domain.upper()
 
-        return 0
+        return ldapret[0]
 
     def ipacheckldap(self, thost, trealm):
         """
@@ -185,7 +189,12 @@ class IPADiscovery:
         so the remote IPA CA cert must be available at
         http://HOST/ipa/config/ca.crt
 
-        Returns a list [host, realm] or an empty list on error.
+        Returns a list [errno, host, realm] or an empty list on error.
+        Errno is an error number:
+            0 means all ok
+            1 means we could not check the info in LDAP (may happend when
+                anonymous binds are siabled)
+            2 means the server is certainly not an IPA server
         """
 
         lret = []
@@ -207,7 +216,7 @@ class IPADiscovery:
             run(["/usr/bin/wget", "-O", "%s/ca.crt" % temp_ca_dir, "http://%s/ipa/config/ca.crt"; % thost])
         except CalledProcessError, e:
             logging.debug('Retrieving CA from %s failed.\n%s' % (thost, str(e)))
-            return []
+            return [NOT_IPA_SERVER]
 
         #now verify the server is really an IPA server
         try:
@@ -229,7 +238,7 @@ class IPADiscovery:
             logging.debug("Search for (info=*) in "+self.basedn+"(base)")
             lret = lh.search_s(self.basedn, ldap.SCOPE_BASE, "(info=IPA*)")
             if not lret:
-                return []
+                return [NOT_IPA_SERVER]
             logging.debug("Found: "+str(lret))
 
             for lattr in lret[0][1]:
@@ -238,14 +247,14 @@ class IPADiscovery:
                     break
 
             if not linfo or linfo.lower() != 'ipa v2.0':
-                return []
+                return [NOT_IPA_SERVER]
 
             #search and return known realms
             logging.debug("Search for (objectClass=krbRealmContainer) in "+self.basedn+"(sub)")
             lret = lh.search_s("cn=kerberos,"+self.basedn, ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
             if not lret:
                 #something very wrong
-                return []
+                return [REALM_NOT_FOUND]
             logging.debug("Found: "+str(lret))
 
             for lres in lret:
@@ -257,26 +266,31 @@ class IPADiscovery:
             if trealm:
                 for r in lrealms:
                     if trealm == r:
-                        return [thost, trealm]
+                        return [0, thost, trealm]
                 # must match or something is very wrong
-                return []
+                return [REALM_NOT_FOUND]
             else:
                 if len(lrealms) != 1:
                     #which one? we can't attach to a multi-realm server without DNS working
-                    return []
+                    return [REALM_NOT_FOUND]
                 else:
-                    return [thost, lrealms[0]]
+                    return [0, thost, lrealms[0]]
 
             #we shouldn't get here
-            return []
+            return [UNKNOWN_ERROR]
 
         except LDAPError, err:
-            if not isinstance(err, ldap.TIMEOUT):
-                logging.error("LDAP Error: %s: %s" %
-                   (err.args[0]['desc'], err.args[0].get('info', '')))
-            else:
+            if isinstance(err, ldap.TIMEOUT):
                 logging.error("LDAP Error: timeout")
-            return []
+                return [NO_LDAP_SERVER]
+
+            if isinstance(err, ldap.INAPPROPRIATE_AUTH):
+                logging.debug("LDAP Error: Anonymous acces not allowed")
+                return [NO_ACCESS_TO_LDAP]
+
+            logging.error("LDAP Error: %s: %s" %
+               (err.args[0]['desc'], err.args[0].get('info', '')))
+            return [UNKNOWN_ERROR]
 
         finally:
             os.remove("%s/ca.crt" % temp_ca_dir)
@@ -307,8 +321,8 @@ class IPADiscovery:
         return servers
 
     def ipadnssearchkrb(self, tdomain):
-        realm = ""
-        kdc = ""
+        realm = None
+        kdc = None
         # now, check for a Kerberos realm the local host or domain is in
         qname = "_kerberos." + tdomain
         # terminate the name
-- 
1.7.6.2

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

Reply via email to