diff options
author | Simo Sorce <ssorce@redhat.com> | 2007-08-28 10:46:03 -0400 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2007-08-28 10:46:03 -0400 |
commit | 46eeca740ee4d66bfd4f062896220dfb5527f5b6 (patch) | |
tree | b5a91cf249e823ddb9ab01e9797c742caa90de50 /ipa-server/xmlrpc-server/funcs.py | |
parent | 4702eb907585556d83b3373bf06705d83ae3ed2d (diff) | |
parent | 6eea6664e079d187c3b0420b4283af35205d3b03 (diff) | |
download | freeipa.git-46eeca740ee4d66bfd4f062896220dfb5527f5b6.tar.gz freeipa.git-46eeca740ee4d66bfd4f062896220dfb5527f5b6.tar.xz freeipa.git-46eeca740ee4d66bfd4f062896220dfb5527f5b6.zip |
Merge in with upstream
Diffstat (limited to 'ipa-server/xmlrpc-server/funcs.py')
-rw-r--r-- | ipa-server/xmlrpc-server/funcs.py | 163 |
1 files changed, 107 insertions, 56 deletions
diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index f388f3f4..fe48a1ff 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -90,42 +90,27 @@ class IPAServer: filter = "(krbPrincipalName=" + princ + ")" # The only anonymous search we should have m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,None) - ent = m1.getEntry(self.basedn, self.scope, filter, ['dn']) - _LDAPPool.releaseConn(m1) + try: + ent = m1.getEntry(self.basedn, self.scope, filter, ['dn']) + finally: + _LDAPPool.releaseConn(m1) return "dn:" + ent.dn def convert_entry(self, ent): - - # Convert to LDIF - entry = str(ent) + entry = dict(ent.data) + entry['dn'] = ent.dn + # For now convert single entry lists to a string for the ui. + # TODO: we need to deal with multi-values better + for key,value in entry.iteritems(): + if isinstance(value,list) or isinstance(value,tuple): + if len(value) == 0: + entry[key] = '' + elif len(value) == 1: + entry[key] = value[0] + return entry - # Strip off any junk - entry = entry.strip() - # Don't need to identify binary fields and this breaks the parser so - # remove double colons - entry = entry.replace('::', ':') - specs = [spec.split(':') for spec in entry.split('\n')] - - # Convert into a dict. We need to handle multi-valued attributes as well - # so we'll convert those into lists. - obj={} - for (k,v) in specs: - k = k.lower() - if obj.get(k) is not None: - if isinstance(obj[k],list): - obj[k].append(v.strip()) - else: - first = obj[k] - obj[k] = [] - obj[k].append(first) - obj[k].append(v.strip()) - else: - obj[k] = v.strip() - - return obj - def __get_entry (self, base, filter, sattrs=None, opts=None): """Get a specific entry. Return as a dict of values. Multi-valued fields are represented as lists. @@ -139,8 +124,10 @@ class IPAServer: dn = self.get_dn_from_principal(self.princ) m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - ent = m1.getEntry(base, self.scope, filter, sattrs) - _LDAPPool.releaseConn(m1) + try: + ent = m1.getEntry(base, self.scope, filter, sattrs) + finally: + _LDAPPool.releaseConn(m1) return self.convert_entry(ent) @@ -169,8 +156,10 @@ class IPAServer: proxydn = self.get_dn_from_principal(self.princ) m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,proxydn) - res = m1.updateEntry(moddn, oldentry, newentry) - _LDAPPool.releaseConn(m1) + try: + res = m1.updateEntry(moddn, oldentry, newentry) + finally: + _LDAPPool.releaseConn(m1) return res def __safe_filter(self, criteria): @@ -181,9 +170,34 @@ class IPAServer: # where the second byte in a multi-byte character # is (illegally) ')' and make sure python-ldap # bombs out. - criteria = re.sub(r'[\(\)\\]', ldap_search_escape, criteria) + criteria = re.sub(r'[\(\)\\\*]', ldap_search_escape, criteria) return criteria + + def __generate_match_filters(self, search_fields, criteria_words): + """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)...) + search_pattern = "(|" + for field in search_fields: + search_pattern += "(" + field + "=%(match)s)" + search_pattern += ")" + gen_search_pattern = lambda word: search_pattern % {'match':word} + + # construct the giant match for all words + exact_match_filter = "(&" + partial_match_filter = "(&" + for word in criteria_words: + exact_match_filter += gen_search_pattern(word) + partial_match_filter += gen_search_pattern("*%s*" % word) + exact_match_filter += ")" + partial_match_filter += ")" + + return (exact_match_filter, partial_match_filter) # User support @@ -192,11 +206,10 @@ class IPAServer: uid = self.__safe_filter(uid) filter = "(&(uid=%s)(objectclass=posixAccount))" % uid - entry = self.__get_entry(self.basedn, filter, ['dn','uid'], opts) - - if entry is not None: + try: + entry = self.__get_entry(self.basedn, filter, ['dn','uid'], opts) return 0 - else: + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): return 1 def get_user_by_uid (self, uid, sattrs=None, opts=None): @@ -283,8 +296,10 @@ class IPAServer: dn = self.get_dn_from_principal(self.princ) m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - res = m1.addEntry(entry) - _LDAPPool.releaseConn(m1) + try: + res = m1.addEntry(entry) + finally: + _LDAPPool.releaseConn(m1) return res def get_add_schema (self): @@ -345,8 +360,10 @@ class IPAServer: filter = "(objectclass=posixAccount)" m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - all_users = m1.getList(self.basedn, self.scope, filter, None) - _LDAPPool.releaseConn(m1) + try: + all_users = m1.getList(self.basedn, self.scope, filter, None) + finally: + _LDAPPool.releaseConn(m1) users = [] for u in all_users: @@ -365,20 +382,46 @@ class IPAServer: dn = self.get_dn_from_principal(self.princ) + # 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 = "uid,givenName,sn,telephoneNumber" + 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 [] - filter = "(|(uid=%s)(cn=%s))" % (criteria, criteria) + (exact_match_filter, partial_match_filter) = self.__generate_match_filters( + search_fields, criteria_words) + + m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) try: - m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - results = m1.getList(self.basedn, self.scope, filter, sattrs) + try: + exact_results = m1.getList(self.basedn, self.scope, + exact_match_filter, sattrs) + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + exact_results = [] + + try: + partial_results = m1.getList(self.basedn, self.scope, + partial_match_filter, sattrs) + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + partial_results = [] + finally: _LDAPPool.releaseConn(m1) - except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): - results = [] + + # 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) users = [] - for u in results: + for u in exact_results + partial_results: users.append(self.convert_entry(u)) - + return users def convert_scalar_values(self, orig_dict): @@ -417,8 +460,10 @@ class IPAServer: has_key = False m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,proxydn) - res = m1.inactivateEntry(user['dn'], has_key) - _LDAPPool.releaseConn(m1) + try: + res = m1.inactivateEntry(user['dn'], has_key) + finally: + _LDAPPool.releaseConn(m1) return res # Group support @@ -485,8 +530,10 @@ class IPAServer: dn = self.get_dn_from_principal(self.princ) m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - res = m1.addEntry(entry) - _LDAPPool.releaseConn(m1) + try: + res = m1.addEntry(entry) + finally: + _LDAPPool.releaseConn(m1) def find_groups (self, criteria, sattrs=None, opts=None): """Return a list containing a User object for each @@ -502,12 +549,13 @@ class IPAServer: criteria = self.__safe_filter(criteria) filter = "(&(cn=%s)(objectClass=posixGroup))" % criteria + m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) try: - m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) results = m1.getList(self.basedn, self.scope, filter, sattrs) - _LDAPPool.releaseConn(m1) except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): results = [] + finally: + _LDAPPool.releaseConn(m1) groups = [] for u in results: @@ -646,5 +694,8 @@ def ldap_search_escape(match): return "\\29" elif value == "\\": return "\\5c" + elif value == "*": + # drop '*' from input. search performs its own wildcarding + return "" else: return value |