def normalize_dn(dn): # Capitalize the attribute names as an LDAP server might. # NOTE(blk-u): Special case for this tested value, used with # test_user_id_comma. The call to str2dn here isn't always correct # here, because `dn` is escaped for an LDAP filter. str2dn() normally # works only because there's no special characters in `dn`. if dn == 'cn=Doe\\5c, John,ou=Users,cn=example,cn=com': return 'CN=Doe\\, John,OU=Users,CN=example,CN=com' # NOTE(blk-u): Another special case for this tested value. When a # roleOccupant has an escaped comma, it gets converted to \2C. if dn == 'cn=Doe\\, John,ou=Users,cn=example,cn=com': return 'CN=Doe\\2C John,OU=Users,CN=example,CN=com' try: dn = ldap.dn.str2dn(core.utf8_encode(dn)) except ldap.DECODING_ERROR: # NOTE(amakarov): In case of IDs instead of DNs in group members # they must be handled as regular values. return normalize_value(dn) norm = [] for part in dn: name, val, i = part[0] name = core.utf8_decode(name) name = name.upper() name = core.utf8_encode(name) norm.append([(name, val, i)]) return core.utf8_decode(ldap.dn.dn2str(norm))
def normalize_dn(dn): # Capitalize the attribute names as an LDAP server might. dn = ldap.dn.str2dn(core.utf8_encode(dn)) norm = [] for part in dn: name, val, i = part[0] name = core.utf8_decode(name) name = name.upper() name = core.utf8_encode(name) norm.append([(name, val, i)]) return core.utf8_decode(ldap.dn.dn2str(norm))
def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in self.db.items(): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v)
def simple_bind_s(self, who='', cred='', serverctrls=None, clientctrls=None): """Provide for compatibility but this method is ignored.""" if server_fail: raise ldap.SERVER_DOWN whos = ['cn=Admin', CONF.ldap.user] if (core.utf8_decode(who) in whos and core.utf8_decode(cred) in ['password', CONF.ldap.password]): return try: attrs = self.db[self.key(who)] except KeyError: LOG.debug('bind fail: who=%s not found', core.utf8_decode(who)) raise ldap.NO_SUCH_OBJECT db_password = None try: db_password = attrs['userPassword'][0] except (KeyError, IndexError): LOG.debug('bind fail: password for who=%s not found', core.utf8_decode(who)) raise ldap.INAPPROPRIATE_AUTH if cred != core.utf8_encode(db_password): LOG.debug('bind fail: password for who=%s does not match', core.utf8_decode(who)) raise ldap.INVALID_CREDENTIALS
def normalize_dn(dn): # Capitalize the attribute names as an LDAP server might. # NOTE(blk-u): Special case for this tested value, used with # test_user_id_comma. The call to str2dn here isn't always correct # here, because `dn` is escaped for an LDAP filter. str2dn() normally # works only because there's no special characters in `dn`. if dn == 'cn=Doe\\5c, John,ou=Users,cn=example,cn=com': return 'CN=Doe\\, John,OU=Users,CN=example,CN=com' dn = ldap.dn.str2dn(core.utf8_encode(dn)) norm = [] for part in dn: name, val, i = part[0] name = core.utf8_decode(name) name = name.upper() name = core.utf8_encode(name) norm.append([(name, val, i)]) return core.utf8_decode(ldap.dn.dn2str(norm))
def normalize_dn(dn): # Capitalize the attribute names as an LDAP server might. # NOTE(blk-u): Special case for this tested value, used with # test_user_id_comma. The call to str2dn here isn't always correct # here, because `dn` is escaped for an LDAP filter. str2dn() normally # works only because there's no special characters in `dn`. if dn == 'cn=Doe\\5c, John,ou=Users,cn=example,cn=com': return 'CN=Doe\\, John,OU=Users,CN=example,CN=com' # NOTE(blk-u): Another special case for this tested value. When a # roleOccupant has an escaped comma, it gets converted to \2C. if dn == 'cn=Doe\\, John,ou=Users,cn=example,cn=com': return 'CN=Doe\\2C John,OU=Users,CN=example,CN=com' dn = ldap.dn.str2dn(core.utf8_encode(dn)) norm = [] for part in dn: name, val, i = part[0] name = core.utf8_decode(name) name = name.upper() name = core.utf8_encode(name) norm.append([(name, val, i)]) return core.utf8_decode(ldap.dn.dn2str(norm))
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- search scope (base, subtree, onelevel) filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if (not filterstr) and (scope != ldap.SCOPE_BASE): raise AssertionError('Search without filter on onelevel or ' 'subtree scope') if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: # FIXME - LDAP search with SUBTREE scope must return the base # entry, but the code below does _not_. Unfortunately, there are # several tests that depend on this broken behavior, and fail # when the base entry is returned in the search results. The # fix is easy here, just initialize results as above for # the SCOPE_BASE case. # https://bugs.launchpad.net/keystone/+bug/1368772 try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_SUBTREE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] extraresults = [ (k[len(self.__prefix):], v) for k, v in self.db.items() if re.match( '%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k) ] results.extend(extraresults) elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in self.db.items(): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: # openldap client/server raises PROTOCOL_ERROR for unexpected scope raise ldap.PROTOCOL_ERROR objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] attrs_checked = set() if not filterstr or _match_query(filterstr, match_attrs, attrs_checked): if (filterstr and (scope != ldap.SCOPE_BASE) and ('objectclass' not in attrs_checked)): raise AssertionError('No objectClass in search filter') # filter the attributes by attrlist attrs = { k: v for k, v in attrs.items() if not attrlist or k in attrlist } objects.append((dn, attrs)) return objects
def _dn_to_id_value(self, dn): return core.utf8_decode(ldap.dn.str2dn(core.utf8_encode(dn))[0][0][1])
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- search scope (base, subtree, onelevel) filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if (not filterstr) and (scope != ldap.SCOPE_BASE): raise AssertionError('Search without filter on onelevel or ' 'subtree scope') if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: # FIXME - LDAP search with SUBTREE scope must return the base # entry, but the code below does _not_. Unfortunately, there are # several tests that depend on this broken behavior, and fail # when the base entry is returned in the search results. The # fix is easy here, just initialize results as above for # the SCOPE_BASE case. # https://bugs.launchpad.net/keystone/+bug/1368772 try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_SUBTREE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] extraresults = [(k[len(self.__prefix):], v) for k, v in self.db.items() if re.match('%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k)] results.extend(extraresults) elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in self.db.items(): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: # openldap client/server raises PROTOCOL_ERROR for unexpected scope raise ldap.PROTOCOL_ERROR objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] attrs_checked = set() if not filterstr or _match_query(filterstr, match_attrs, attrs_checked): if (filterstr and (scope != ldap.SCOPE_BASE) and ('objectclass' not in attrs_checked)): raise AssertionError('No objectClass in search filter') # filter the attributes by attrlist attrs = {k: v for k, v in attrs.items() if not attrlist or k in attrlist} objects.append((dn, attrs)) return objects
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- only SCOPE_BASE and SCOPE_SUBTREE are supported filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: results = [ (k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match( '%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k) ] elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in six.iteritems(self.db): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: LOG.debug('search fail: unknown scope %s', scope) raise NotImplementedError('Search scope %s not implemented.' % scope) objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] if not filterstr or _match_query(filterstr, match_attrs): # filter the attributes by attrlist attrs = dict([(k, v) for k, v in six.iteritems(attrs) if not attrlist or k in attrlist]) objects.append((dn, attrs)) return objects
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- only SCOPE_BASE and SCOPE_SUBTREE are supported filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: results = [(k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match('%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k)] elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in six.iteritems(self.db): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: LOG.debug('search fail: unknown scope %s', scope) raise NotImplementedError('Search scope %s not implemented.' % scope) objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] if not filterstr or _match_query(filterstr, match_attrs): # filter the attributes by attrlist attrs = dict([(k, v) for k, v in six.iteritems(attrs) if not attrlist or k in attrlist]) objects.append((dn, attrs)) return objects
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- only SCOPE_BASE and SCOPE_SUBTREE are supported filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: # FIXME - LDAP search with SUBTREE scope must return the base # entry, but the code below does _not_. Unfortunately, there are # several tests that depend on this broken behavior, and fail # when the base entry is returned in the search results. The # fix is easy here, just initialize results as above for # the SCOPE_BASE case. # https://bugs.launchpad.net/keystone/+bug/1368772 results = [] try: item_dict = self.db[self.key(base)] results.extend([(base, item_dict)]) except KeyError: LOG.debug('search fail: dn not found for SCOPE_SUBTREE') extraresults = [ (k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match( '%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k) ] results.extend(extraresults) elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in six.iteritems(self.db): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: LOG.debug('search fail: unknown scope %s', scope) raise NotImplementedError('Search scope %s not implemented.' % scope) objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] if not filterstr or _match_query(filterstr, match_attrs): # filter the attributes by attrlist attrs = dict([(k, v) for k, v in six.iteritems(attrs) if not attrlist or k in attrlist]) objects.append((dn, attrs)) return objects
def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0): """Search for all matching objects under base using the query. Args: base -- dn to search under scope -- only SCOPE_BASE and SCOPE_SUBTREE are supported filterstr -- filter objects by attrlist -- attrs to return. Returns all attrs if not specified """ if server_fail: raise ldap.SERVER_DOWN if scope == ldap.SCOPE_BASE: try: item_dict = self.db[self.key(base)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(base, item_dict)] elif scope == ldap.SCOPE_SUBTREE: # FIXME - LDAP search with SUBTREE scope must return the base # entry, but the code below does _not_. Unfortunately, there are # several tests that depend on this broken behavior, and fail # when the base entry is returned in the search results. The # fix is easy here, just initialize results as above for # the SCOPE_BASE case. # https://bugs.launchpad.net/keystone/+bug/1368772 results = [] try: item_dict = self.db[self.key(base)] results.extend([(base, item_dict)]) except KeyError: LOG.debug('search fail: dn not found for SCOPE_SUBTREE') extraresults = [(k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match('%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base))), k)] results.extend(extraresults) elif scope == ldap.SCOPE_ONELEVEL: def get_entries(): base_dn = ldap.dn.str2dn(core.utf8_encode(base)) base_len = len(base_dn) for k, v in six.iteritems(self.db): if not k.startswith(self.__prefix): continue k_dn_str = k[len(self.__prefix):] k_dn = ldap.dn.str2dn(core.utf8_encode(k_dn_str)) if len(k_dn) != base_len + 1: continue if k_dn[-base_len:] != base_dn: continue yield (k_dn_str, v) results = list(get_entries()) else: LOG.debug('search fail: unknown scope %s', scope) raise NotImplementedError('Search scope %s not implemented.' % scope) objects = [] for dn, attrs in results: # filter the objects by filterstr id_attr, id_val, _ = ldap.dn.str2dn(core.utf8_encode(dn))[0][0] id_attr = core.utf8_decode(id_attr) id_val = core.utf8_decode(id_val) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] if not filterstr or _match_query(filterstr, match_attrs): # filter the attributes by attrlist attrs = dict([(k, v) for k, v in six.iteritems(attrs) if not attrlist or k in attrlist]) objects.append((dn, attrs)) return objects