Пример #1
0
    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))
Пример #2
0
 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))
Пример #3
0
            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)
Пример #4
0
    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
Пример #5
0
    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))
Пример #6
0
    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))
Пример #7
0
    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
Пример #8
0
 def _dn_to_id_value(self, dn):
     return core.utf8_decode(ldap.dn.str2dn(core.utf8_encode(dn))[0][0][1])
Пример #9
0
    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
Пример #10
0
 def _dn_to_id_value(self, dn):
     return core.utf8_decode(ldap.dn.str2dn(core.utf8_encode(dn))[0][0][1])
Пример #11
0
    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
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
    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