summaryrefslogtreecommitdiffstats
path: root/ipa_server
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2008-10-15 16:11:34 -0400
committerRob Crittenden <rcritten@redhat.com>2008-10-15 16:12:27 -0400
commit3268b65ae0dfc7ffdeba685e8e2515a437bf092e (patch)
treea791d5d9f6daeb11e3d8644c0ba8b95d46889011 /ipa_server
parentaf7c0ee595bf522a7f52e5e1b6515a3a27292846 (diff)
downloadfreeipa-3268b65ae0dfc7ffdeba685e8e2515a437bf092e.tar.gz
freeipa-3268b65ae0dfc7ffdeba685e8e2515a437bf092e.tar.xz
freeipa-3268b65ae0dfc7ffdeba685e8e2515a437bf092e.zip
Initial implementation of a generic search routine.
Diffstat (limited to 'ipa_server')
-rw-r--r--ipa_server/plugins/b_ldap.py74
-rw-r--r--ipa_server/servercore.py96
2 files changed, 88 insertions, 82 deletions
diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py
index c4823038..42fa65a5 100644
--- a/ipa_server/plugins/b_ldap.py
+++ b/ipa_server/plugins/b_ldap.py
@@ -60,9 +60,8 @@ class ldap(CrudBackend):
object_type = "posixGroup"
elif key_attribute == "krbprincipal": # Service
object_type = "krbPrincipal"
-
- if not object_type:
- return None
+ else:
+ return None
filter = "(&(%s=%s)(objectclass=%s))" % (
key_attribute,
@@ -76,6 +75,31 @@ class ldap(CrudBackend):
return entry['dn']
+ def generate_search_filters(self, **kw):
+ """Generates a search filter based on a list of words and a list
+ of fields to search against.
+
+ Returns a tuple of two filters: (exact_match, partial_match)
+ """
+
+ # construct search pattern for a single word
+ # (|(f1=word)(f2=word)...)
+ exact_pattern = "(|"
+ for field in kw.keys():
+ exact_pattern += "(%s=%s)" % (field, kw[field])
+ exact_pattern += ")"
+
+ sub_pattern = "(|"
+ for field in kw.keys():
+ sub_pattern += "(%s=*%s*)" % (field, kw[field])
+ sub_pattern += ")"
+
+ # construct the giant match for all words
+ exact_match_filter = "(&" + exact_pattern + ")"
+ partial_match_filter = "(|" + sub_pattern + ")"
+
+ return (exact_match_filter, partial_match_filter)
+
def create(self, **kw):
if servercore.entry_exists(kw['dn']):
raise errors.DuplicateEntry("entry already exists")
@@ -107,6 +131,50 @@ class ldap(CrudBackend):
def delete(self, dn):
return servercore.delete_entry(dn)
+ def search(self, **kw):
+ objectclass = kw.get('objectclass')
+ if objectclass:
+ del kw['objectclass']
+ (exact_match_filter, partial_match_filter) = self.generate_search_filters(**kw)
+ if objectclass:
+ exact_match_filter = "(&(objectClass=%s)%s)" % (objectclass, exact_match_filter)
+ partial_match_filter = "(&(objectClass=%s)%s)" % (objectclass, partial_match_filter)
+
+ search_base = "%s, %s" % (self.api.env.container_accounts, self.api.env.basedn)
+ try:
+ exact_results = servercore.search(search_base,
+ exact_match_filter, ["*"])
+ except errors.NotFound:
+ exact_results = [0]
+
+ try:
+ partial_results = servercore.search(search_base,
+ partial_match_filter, ["*"])
+ except errors.NotFound:
+ partial_results = [0]
+
+ exact_counter = exact_results[0]
+ partial_counter = partial_results[0]
+
+ exact_results = exact_results[1:]
+ partial_results = partial_results[1:]
+
+ # Remove exact matches from the partial_match list
+ exact_dns = set(map(lambda e: e.get('dn'), exact_results))
+ partial_results = filter(lambda e: e.get('dn') not in exact_dns,
+ partial_results)
+
+ if (exact_counter == -1) or (partial_counter == -1):
+ counter = -1
+ else:
+ counter = len(exact_results) + len(partial_results)
+
+ results = [counter]
+ for r in exact_results + partial_results:
+ results.append(r)
+
+ return results
+
api.register(ldap)
def delete(self, dn):
diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py
index 7310104d..ea6beecf 100644
--- a/ipa_server/servercore.py
+++ b/ipa_server/servercore.py
@@ -230,85 +230,6 @@ def uid_too_long(uid):
return False
-def find_users (criteria, sattrs, sizelimit=-1, timelimit=-1):
- """Returns a list: counter followed by the results.
- If the results are truncated, counter will be set to -1."""
-
- """
- if not isinstance(criteria,basestring) or len(criteria) == 0:
- raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
- if sattrs is not None and not isinstance(sattrs, list):
- raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
- if not isinstance(sizelimit,int):
- raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
- if not isinstance(timelimit,int):
- raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
- """
-
-# logging.info("IPA: find_users '%s'" % criteria)
- config = get_ipa_config()
- if timelimit < 0:
- timelimit = float(config.get('ipasearchtimelimit'))
- if sizelimit < 0:
- sizelimit = int(config.get('ipasearchrecordslimit'))
-
- # Assume the list of fields to search will come from a central
- # configuration repository. A good format for that would be
- # a comma-separated list of fields
- search_fields_conf_str = config.get('ipausersearchfields')
- search_fields = string.split(search_fields_conf_str, ",")
-
-# criteria = self.__safe_filter(criteria)
- criteria_words = re.split(r'\s+', criteria)
- criteria_words = filter(lambda value:value!="", criteria_words)
- if len(criteria_words) == 0:
- return [0]
-
- (exact_match_filter, partial_match_filter) = generate_match_filters(
- search_fields, criteria_words)
-
- #
- # further constrain search to just the objectClass
- # TODO - need to parameterize this into generate_match_filters,
- # and work it into the field-specification search feature
- #
- exact_match_filter = "(&(objectClass=person)%s)" % exact_match_filter
- partial_match_filter = "(&(objectClass=person)%s)" % partial_match_filter
-
- try:
- exact_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, exact_match_filter, sattrs, 0, None, None, timelimit, sizelimit)
-# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- except Exception:
- exact_results = [0]
-
- try:
- partial_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, partial_match_filter, sattrs, 0, None, None, timelimit, sizelimit)
-# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- except Exception:
- partial_results = [0]
-
- exact_counter = exact_results[0]
- partial_counter = partial_results[0]
-
- exact_results = exact_results[1:]
- partial_results = partial_results[1:]
-
- # Remove exact matches from the partial_match list
- exact_dns = set(map(lambda e: e.dn, exact_results))
- partial_results = filter(lambda e: e.dn not in exact_dns,
- partial_results)
-
- if (exact_counter == -1) or (partial_counter == -1):
- counter = -1
- else:
- counter = len(exact_results) + len(partial_results)
-
- users = [counter]
- for u in exact_results + partial_results:
- users.append(convert_entry(u))
-
- return users
-
def update_entry (entry):
"""Update an LDAP entry
@@ -341,6 +262,23 @@ def delete_entry(dn):
"""Remove an entry"""
return context.conn.getConn().deleteEntry(dn)
+# FIXME, get time and search limit from cn=ipaconfig
+def search(base, filter, attributes, timelimit=1, sizelimit=3000):
+ """Perform an LDAP query"""
+ try:
+ timelimit = float(timelimit)
+ results = context.conn.getConn().getListAsync(base, ldap.SCOPE_SUBTREE,
+ filter, attributes, 0, None, None, timelimit, sizelimit)
+ except ldap.NO_SUCH_OBJECT:
+ raise errors.NotFound
+
+ counter = results[0]
+ entries = [counter]
+ for r in results[1:]:
+ entries.append(convert_entry(r))
+
+ return entries
+
def uniq_list(x):
"""Return a unique list, preserving order and ignoring case"""
myset = {}