Hi,

these patches add flags to LDAPClient and IPAdmin constructors which can be used to disable schema retrieval and decoding of attributes. This should make interacting with AD easier (see <http://www.redhat.com/archives/freeipa-devel/2013-March/msg00076.html>).

Honza

--
Jan Cholasta
>From 33142d7e0a8508a783e1a1b4a7a22525337ce54d Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 7 Mar 2013 10:50:57 +0100
Subject: [PATCH 1/4] Do not fail if schema cannot be retrieved from LDAP
 server.

---
 ipaserver/ipaldap.py | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index 4a46532..e6f82dc 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -270,13 +270,19 @@ class IPASimpleLDAPObject(object):
         self.log = log_mgr.get_logger(self)
         self.uri = uri
         self.conn = SimpleLDAPObject(uri)
+        self._has_schema = False
         self._schema = None
         self._force_schema_updates = force_schema_updates
 
     def _get_schema(self):
-        if self._schema is None:
-            self._schema = schema_cache.get_schema(
-                self.uri, self.conn, force_update=self._force_schema_updates)
+        if not self._has_schema:
+            try:
+                self._schema = schema_cache.get_schema(
+                    self.uri, self.conn,
+                    force_update=self._force_schema_updates)
+            except:
+                pass
+            self._has_schema = True
         return self._schema
 
     schema = property(_get_schema, None, None, 'schema associated with this LDAP server')
@@ -307,6 +313,7 @@ class IPASimpleLDAPObject(object):
         # logical operations that have the potential to cause a schema
         # change.
 
+        self._has_schema = False
         self._schema = None
 
     def get_syntax(self, attr):
@@ -315,6 +322,9 @@ class IPASimpleLDAPObject(object):
         if syntax is not None:
             return syntax
 
+        if self.schema is None:
+            return None
+
         # Try to lookup the syntax in the schema returned by the server
         obj = self.schema.get_obj(ldap.schema.AttributeType, attr)
         if obj is not None:
-- 
1.8.1

>From d4fccb0c9fac71f0c0be90cd19ec737fbff8c428 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 7 Mar 2013 10:52:57 +0100
Subject: [PATCH 2/4] Allow disabling LDAP schema retrieval in LDAPClient and
 IPAdmin.

---
 ipaserver/ipaldap.py | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index e6f82dc..9d350f7 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -255,7 +255,7 @@ class IPASimpleLDAPObject(object):
         'originscope':     DN_SYNTAX_OID, # DN
     })
 
-    def __init__(self, uri, force_schema_updates):
+    def __init__(self, uri, force_schema_updates, no_schema=False):
         """An internal LDAP connection object
 
         :param uri: The LDAP URI to connect to
@@ -266,15 +266,19 @@ class IPASimpleLDAPObject(object):
             Generally, it should be true if the API context is 'installer' or
             'updates', but it must be given explicitly since the API object
             is not always available
+        :param no_schema: If true, schema is never requested from the server.
         """
         self.log = log_mgr.get_logger(self)
         self.uri = uri
         self.conn = SimpleLDAPObject(uri)
+        self._no_schema = no_schema
         self._has_schema = False
         self._schema = None
         self._force_schema_updates = force_schema_updates
 
     def _get_schema(self):
+        if self._no_schema:
+            return None
         if not self._has_schema:
             try:
                 self._schema = schema_cache.get_schema(
@@ -1649,7 +1653,7 @@ class IPAdmin(LDAPClient):
 
     def __init__(self, host='', port=389, cacert=None, debug=None, ldapi=False,
                  realm=None, protocol=None, force_schema_updates=True,
-                 start_tls=False, ldap_uri=None):
+                 start_tls=False, ldap_uri=None, no_schema=False):
         self.conn = None
         log_mgr.get_logger(self, True)
         if debug and debug.lower() == "on":
@@ -1669,7 +1673,8 @@ class IPAdmin(LDAPClient):
 
         LDAPClient.__init__(self, ldap_uri)
 
-        self.conn = IPASimpleLDAPObject(ldap_uri, force_schema_updates=True)
+        self.conn = IPASimpleLDAPObject(ldap_uri, force_schema_updates=True,
+                                        no_schema=no_schema)
 
         if start_tls:
             self.conn.start_tls_s()
-- 
1.8.1

>From 8c89c1058ba1fa9798b284c9ed3efa5cd8d5a844 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 7 Mar 2013 10:56:03 +0100
Subject: [PATCH 3/4] Allow disabling attribute decoding in LDAPClient and
 IPAdmin.

---
 ipaserver/ipaldap.py | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index 9d350f7..a2152c4 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -255,7 +255,8 @@ class IPASimpleLDAPObject(object):
         'originscope':     DN_SYNTAX_OID, # DN
     })
 
-    def __init__(self, uri, force_schema_updates, no_schema=False):
+    def __init__(self, uri, force_schema_updates, no_schema=False,
+                 decode_attrs=True):
         """An internal LDAP connection object
 
         :param uri: The LDAP URI to connect to
@@ -267,6 +268,9 @@ class IPASimpleLDAPObject(object):
             'updates', but it must be given explicitly since the API object
             is not always available
         :param no_schema: If true, schema is never requested from the server.
+        :param decode_attrs:
+            If true, attributes are decoded to Python types according to their
+            syntax.
         """
         self.log = log_mgr.get_logger(self)
         self.uri = uri
@@ -275,6 +279,7 @@ class IPASimpleLDAPObject(object):
         self._has_schema = False
         self._schema = None
         self._force_schema_updates = force_schema_updates
+        self._decode_attrs = decode_attrs
 
     def _get_schema(self):
         if self._no_schema:
@@ -377,6 +382,9 @@ class IPASimpleLDAPObject(object):
         '''
         '''
 
+        if not self._decode_attrs:
+            return values
+
         ipa_values = []
 
         for original_value in values:
@@ -1653,7 +1661,8 @@ class IPAdmin(LDAPClient):
 
     def __init__(self, host='', port=389, cacert=None, debug=None, ldapi=False,
                  realm=None, protocol=None, force_schema_updates=True,
-                 start_tls=False, ldap_uri=None, no_schema=False):
+                 start_tls=False, ldap_uri=None, no_schema=False,
+                 decode_attrs=True):
         self.conn = None
         log_mgr.get_logger(self, True)
         if debug and debug.lower() == "on":
@@ -1674,7 +1683,8 @@ class IPAdmin(LDAPClient):
         LDAPClient.__init__(self, ldap_uri)
 
         self.conn = IPASimpleLDAPObject(ldap_uri, force_schema_updates=True,
-                                        no_schema=no_schema)
+                                        no_schema=no_schema,
+                                        decode_attrs=decode_attrs)
 
         if start_tls:
             self.conn.start_tls_s()
-- 
1.8.1

>From 5b83c1060b0a6bd147f003ca7d2b6031d76940be Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 7 Mar 2013 10:56:49 +0100
Subject: [PATCH 4/4] Disable schema retrieval and attribute decoding when
 talking to AD GC.

---
 ipaserver/dcerpc.py  | 7 ++-----
 ipaserver/ipaldap.py | 4 ++++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
index 4e85dc7..b99804c 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -434,7 +434,7 @@ class DomainValidator(object):
         Actual search in AD LDAP server, using SASL GSSAPI authentication
         Returns LDAP result or None
         """
-        conn = IPAdmin(host=host, port=port)
+        conn = IPAdmin(host=host, port=port, no_schema=True, decode_attrs=False)
         auth = self.__extract_trusted_auth(info)
         if attrs is None:
             attrs = []
@@ -450,10 +450,7 @@ class DomainValidator(object):
                 if basedn is None:
                     # Use domain root base DN
                     basedn = DN(*map(lambda p: ('dc', p), info['dns_domain'].split('.')))
-                # We don't use conn.getEntry() because it will attempt to fetch schema from GC and that will fail
-                filterstr = conn.encode(filter)
-                attrlist = conn.encode(attrs)
-                entries = conn.conn.conn.search_s(str(basedn), scope, filterstr, attrlist, 0)
+                entries = conn.search_s(basedn, scope, filter, attrs, 0)
                 os.environ["KRB5CCNAME"] = old_ccache
                 return entries
 
diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index a2152c4..02c23cd 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -1811,6 +1811,10 @@ class IPAdmin(LDAPClient):
         # FIXME: for backwards compatibility only
         return self.conn.set_option(*args, **kwargs)
 
+    def search_s(self, *args, **kwargs):
+        # FIXME: for backwards compatibility only
+        return self.conn.search_s(*args, **kwargs)
+
     def encode(self, *args, **kwargs):
         # FIXME: for backwards compatibility only
         return self.conn.encode(*args, **kwargs)
-- 
1.8.1

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

Reply via email to