Example #1
0
    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        assert nulldn.ldap_text() == nulldn.x500_text()

        # reverse a DN with a single RDN
        assert self.dn1.ldap_text() == self.dn1.x500_text()

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        assert dn3_rev.ldap_text() == dn3_x500

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            assert longdn_rev[i] == self.base_container_dn[l - 1 - i]
Example #2
0
    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        self.assertEqual(nulldn.ldap_text(), nulldn.x500_text())

        # reverse a DN with a single RDN
        self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text())

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        self.assertEqual(dn3_rev.ldap_text(), dn3_x500)

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            self.assertEqual(longdn_rev[i], self.base_container_dn[l - 1 - i])
Example #3
0
    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        self.assertEqual(nulldn.ldap_text(), nulldn.x500_text())

        # reverse a DN with a single RDN
        self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text())

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        self.assertEqual(dn3_rev.ldap_text(), dn3_x500)

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            self.assertEqual(longdn_rev[i], self.base_container_dn[l-1-i])
Example #4
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
                     **options):
        # Fill in a default UUID when not specified.
        if entry_attrs.get('ipatokenuniqueid', None) is None:
            entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4())
            dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'],
                    dn)

        if not _check_interval(options.get('ipatokennotbefore', None),
                               options.get('ipatokennotafter', None)):
            raise ValidationError(name='not_after',
                                  error='is before the validity start')

        # Set the object class and defaults for specific token types
        options['type'] = options['type'].lower()
        entry_attrs['objectclass'] = otptoken.object_class + [
            'ipatoken' + options['type']
        ]
        for ttype, tattrs in TOKEN_TYPES.items():
            if ttype != options['type']:
                for tattr in tattrs:
                    if tattr in entry_attrs:
                        del entry_attrs[tattr]

        # If owner was not specified, default to the person adding this token.
        # If managedby was not specified, attempt a sensible default.
        if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs:
            cur_dn = DN(self.api.Backend.ldap2.conn.whoami_s()[4:])
            if cur_dn:
                cur_uid = cur_dn[0].value
                prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid)
                if cur_uid == prev_uid:
                    entry_attrs.setdefault('managedby', cur_dn.ldap_text())

        # Resolve the owner's dn
        _normalize_owner(self.api.Object.user, entry_attrs)

        # Get the issuer for the URI
        owner = entry_attrs.get('ipatokenowner', None)
        issuer = api.env.realm
        if owner is not None:
            try:
                issuer = ldap.get_entry(
                    owner, ['krbprincipalname'])['krbprincipalname'][0]
            except (NotFound, IndexError):
                pass

        # Check if key is not empty
        if entry_attrs['ipatokenotpkey'] is None:
            raise ValidationError(name='key', error=_(u'cannot be empty'))

        # Build the URI parameters
        args = {}
        args['issuer'] = issuer
        args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey'])
        args['digits'] = entry_attrs['ipatokenotpdigits']
        args['algorithm'] = entry_attrs['ipatokenotpalgorithm'].upper()
        if options['type'] == 'totp':
            args['period'] = entry_attrs['ipatokentotptimestep']
        elif options['type'] == 'hotp':
            args['counter'] = entry_attrs['ipatokenhotpcounter']

        # Build the URI
        label = urllib.parse.quote(entry_attrs['ipatokenuniqueid'])
        parameters = urllib.parse.urlencode(args)
        uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label,
                                          parameters)
        setattr(context, 'uri', uri)

        attrs_list.append("objectclass")
        return dn
Example #5
0
class TestDN:
    @pytest.fixture(autouse=True)
    def dn_setup(self):
        # ava1 must sort before ava2
        self.attr1    = 'cn'
        self.value1   = u'Bob'
        self.str_ava1 = '%s=%s' % (self.attr1, self.value1)
        self.ava1     = AVA(self.attr1, self.value1)

        self.str_rdn1 = '%s=%s' % (self.attr1, self.value1)
        self.rdn1     = RDN((self.attr1, self.value1))

        self.attr2    = 'ou'
        self.value2   = u'people'
        self.str_ava2 = '%s=%s' % (self.attr2, self.value2)
        self.ava2     = AVA(self.attr2, self.value2)

        self.str_rdn2 = '%s=%s' % (self.attr2, self.value2)
        self.rdn2     = RDN((self.attr2, self.value2))

        self.str_dn1 = self.str_rdn1
        self.dn1 = DN(self.rdn1)

        self.str_dn2 = self.str_rdn2
        self.dn2 = DN(self.rdn2)

        self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2)
        self.dn3 = DN(self.rdn1, self.rdn2)

        self.base_rdn1 = RDN(('dc', 'redhat'))
        self.base_rdn2 = RDN(('dc', 'com'))
        self.base_dn = DN(self.base_rdn1, self.base_rdn2)

        self.container_rdn1 = RDN(('cn', 'sudorules'))
        self.container_rdn2 = RDN(('cn', 'sudo'))
        self.container_dn = DN(self.container_rdn1, self.container_rdn2)

        self.base_container_dn = DN((self.attr1, self.value1),
                                    self.container_dn, self.base_dn)

        ou = x509.NameAttribute(
            x509.NameOID.ORGANIZATIONAL_UNIT_NAME, self.value2)
        cn = x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1)
        c = x509.NameAttribute(x509.NameOID.COUNTRY_NAME, 'AU')
        st = x509.NameAttribute(
            x509.NameOID.STATE_OR_PROVINCE_NAME, 'Queensland')
        self.x500name = x509.Name([ou, cn])
        self.x500nameMultiRDN = x509.Name([
            x509.RelativeDistinguishedName([c, st]),
            x509.RelativeDistinguishedName([cn]),
        ])
        self.x500nameMultiRDN2 = x509.Name([
            x509.RelativeDistinguishedName([st, c]),
            x509.RelativeDistinguishedName([cn]),
        ])

    def assertExpectedClass(self, klass, obj, component):
        assert obj.__class__ is expected_class(klass, component)

    def test_create(self):
        # Create with single attr,value pair
        dn1 = DN((self.attr1, self.value1))
        assert len(dn1) == 1
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
        assert isinstance(dn1[0].attr, unicode)
        assert isinstance(dn1[0].value, unicode)
        assert dn1[0] == self.rdn1

        # Create with single attr,value pair passed as a tuple
        dn1 = DN((self.attr1, self.value1))
        assert len(dn1) == 1
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1

        # Creation with multiple attr,value string pairs should fail
        with pytest.raises(ValueError):
            dn1 = DN(self.attr1, self.value1, self.attr2, self.value2)

        # Create with multiple attr,value pairs passed as tuples & lists
        dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2])
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1
        assert dn1[1] == self.rdn2

        # Create with multiple attr,value pairs passed as tuple and RDN
        dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2)))
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1
        assert dn1[1] == self.rdn2

        # Create with multiple attr,value pairs but reverse
        # constructor parameter ordering. RDN ordering should also be
        # reversed because DN's are a ordered sequence of RDN's
        dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1))
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn2
        assert dn1[1] == self.rdn1

        # Create with single RDN object
        dn1 = DN(self.rdn1)
        assert len(dn1) == 1
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1

        # Create with multiple RDN objects, assure ordering is preserved.
        dn1 = DN(self.rdn1, self.rdn2)
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1
        assert dn1[1] == self.rdn2

        # Create with multiple RDN objects in different order, assure
        # ordering is preserved.
        dn1 = DN(self.rdn2, self.rdn1)
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn2
        assert dn1[1] == self.rdn1

        # Create with single string with 1 RDN
        dn1 = DN(self.str_rdn1)
        assert len(dn1) == 1
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1

        # Create with single string with 2 RDN's
        dn1 = DN(self.str_dn3)
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1
        assert dn1[1] == self.rdn2

        # Create with a python-cryptography 'Name'
        dn1 = DN(self.x500name)
        assert len(dn1) == 2
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            assert isinstance(dn1[i].attr, unicode)
            assert isinstance(dn1[i].value, unicode)
        assert dn1[0] == self.rdn1
        assert dn1[1] == self.rdn2

        # Create from 'Name' with multi-valued RDN
        dn1 = DN(self.x500nameMultiRDN)
        assert len(dn1) == 2
        assert len(dn1[1]) == 2
        assert AVA('c', 'au') in dn1[1]
        assert AVA('st', 'queensland') in dn1[1]
        assert len(dn1[0]) == 1
        assert self.ava1 in dn1[0]

        # Create with RDN, and 2 DN's (e.g. attr + container + base)
        dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn)
        assert len(dn1) == 5
        dn_str = ','.join([str(self.rdn1),
                            str(self.container_rdn1), str(self.container_rdn2),
                            str(self.base_rdn1), str(self.base_rdn2)])
        assert str(dn1) == dn_str

    def test_str(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        assert str(dn1) == self.str_dn1
        assert isinstance(str(dn1), str)

        assert str(dn2) == self.str_dn2
        assert isinstance(str(dn2), str)

        assert str(dn3) == self.str_dn3
        assert isinstance(str(dn3), str)

    def test_cmp(self):
        # Equality
        dn1 = DN((self.attr1, self.value1))

        assert dn1 == self.dn1
        assert dn1 == self.dn1

        assert dn1 == self.str_dn1
        assert dn1 == self.str_dn1

        result = cmp(dn1, self.dn1)
        assert result == 0

        # Make dn1's attr greater
        with pytest.raises(AttributeError):
            dn1[0].attr = self.attr1 + "1"
        dn1 = DN((self.attr1 + "1", self.value1))

        assert dn1 != self.dn1
        assert dn1 != self.dn1

        result = cmp(dn1, self.dn1)
        assert result == 1

        result = cmp(self.dn1, dn1)
        assert result == -1

        # Reset dn1's attr, should be equal again
        with pytest.raises(AttributeError):
            dn1[0].attr = self.attr1
        dn1 = DN((self.attr1, self.value1))

        result = cmp(dn1, self.dn1)
        assert result == 0

        # Make dn1's value greater
        # attr will be equal, this tests secondary comparision component
        with pytest.raises(AttributeError):
            dn1[0].value = self.value1 + "1"
        dn1 = DN((self.attr1, self.value1 + "1"))

        result = cmp(dn1, self.dn1)
        assert result == 1

        result = cmp(self.dn1, dn1)
        assert result == -1

        # Make sure dn's with more rdn's are greater
        result = cmp(self.dn1, self.dn3)
        assert result == -1
        result = cmp(self.dn3, self.dn1)
        assert result == 1


        # Test startswith, endswith
        container_dn = DN(self.container_dn)
        base_container_dn = DN(self.base_container_dn)

        assert base_container_dn.startswith(self.rdn1)
        assert base_container_dn.startswith(self.dn1)
        assert base_container_dn.startswith(self.dn1 + container_dn)
        assert not base_container_dn.startswith(self.dn2)
        assert not base_container_dn.startswith(self.rdn2)
        assert base_container_dn.startswith((self.dn1))
        assert base_container_dn.startswith((self.rdn1))
        assert not base_container_dn.startswith((self.rdn2))
        assert base_container_dn.startswith((self.rdn2, self.rdn1))
        assert base_container_dn.startswith((self.dn1, self.dn2))

        assert base_container_dn.endswith(self.base_dn)
        assert base_container_dn.endswith(container_dn + self.base_dn)
        assert not base_container_dn.endswith(DN(self.base_rdn1))
        assert base_container_dn.endswith(DN(self.base_rdn2))
        assert base_container_dn.endswith(
            (DN(self.base_rdn1), DN(self.base_rdn2)))

        # Test "in" membership
        assert self.container_rdn1 in container_dn
        # pylint: disable=comparison-with-itself
        assert container_dn in container_dn
        assert self.base_rdn1 not in container_dn

        assert self.container_rdn1 in base_container_dn
        assert container_dn in base_container_dn
        assert container_dn + self.base_dn in base_container_dn
        assert self.dn1 + container_dn + self.base_dn in base_container_dn
        assert self.dn1 + container_dn + self.base_dn == base_container_dn

        assert self.container_rdn1 not in self.base_dn

    def test_eq_multi_rdn(self):
        dn1 = DN(self.ava1, 'ST=Queensland+C=AU')
        dn2 = DN(self.ava1, 'C=AU+ST=Queensland')
        assert dn1 == dn2

        # ensure AVAs get sorted when constructing from x509.Name
        dn3 = DN(self.x500nameMultiRDN)
        dn4 = DN(self.x500nameMultiRDN2)
        assert dn3 == dn4

        # ensure AVAs get sorted in the same way regardless of what
        # the DN was constructed from
        assert dn1 == dn3
        assert dn1 == dn4
        assert dn2 == dn3
        assert dn2 == dn4

    def test_indexing(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        assert dn1[0] == self.rdn1
        assert dn1[self.rdn1.attr] == self.rdn1.value
        with pytest.raises(KeyError):
            dn1['foo']  # pylint: disable=pointless-statement

        assert dn2[0] == self.rdn2
        assert dn2[self.rdn2.attr] == self.rdn2.value
        with pytest.raises(KeyError):
            dn2['foo']  # pylint: disable=pointless-statement

        assert dn3[0] == self.rdn1
        assert dn3[self.rdn1.attr] == self.rdn1.value
        assert dn3[1] == self.rdn2
        assert dn3[self.rdn2.attr] == self.rdn2.value
        with pytest.raises(KeyError):
            dn3['foo']  # pylint: disable=pointless-statement

        with pytest.raises(TypeError):
            dn3[1.0]  # pylint: disable=pointless-statement

    def test_assignments(self):
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with pytest.raises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0] = RDN('t=a')
        with pytest.raises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0:1] = [RDN('t=a'), RDN('t=b')]

    def test_iter(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        assert len(dn1) == 1
        assert dn1[:] == self.rdn1
        for i, ava in enumerate(dn1):
            if i == 0:
                assert ava == self.rdn1
            else:
                pytest.fail(
                    "got iteration index %d, but len=%d" % (i, len(self.rdn1)))

        assert len(dn2) == 1
        assert dn2[:] == self.rdn2
        for i, ava in enumerate(dn2):
            if i == 0:
                assert ava == self.rdn2
            else:
                pytest.fail(
                    "got iteration index %d, but len=%d" % (i, len(self.rdn2)))

        assert len(dn3) == 2
        assert dn3[:] == DN(self.rdn1, self.rdn2)
        for i, ava in enumerate(dn3):
            if i == 0:
                assert ava == self.rdn1
            elif i == 1:
                assert ava == self.rdn2
            else:
                pytest.fail(
                    "got iteration index %d, but len=%d" % (i, len(dn3)))

    def test_concat(self):
        dn1 = DN((self.attr1, self.value1))
        dn2 = DN([self.attr2, self.value2])

        # in-place addtion

        dn1 += dn2
        assert dn1 == self.dn3
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.rdn2
        assert dn1 == self.dn3
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.dn2
        assert dn1 == self.dn3
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.str_dn2
        assert dn1 == self.dn3
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        # concatenation
        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + dn2
        assert dn3 == self.dn3
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + self.rdn2
        assert dn3 == self.dn3
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.str_rdn2
        assert dn3 == self.dn3
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            self.assertExpectedClass(DN, dn3[i][0], 'AVA')

        dn3 = dn1 + self.str_dn2
        assert dn3 == self.dn3
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.dn2
        assert dn3 == self.dn3
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

    def test_find(self):
        #        -10 -9  -8     -7  -6  -5  -4     -3  -2  -1
        dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9')
        pat = DN('cn=bob')

        # forward
        assert dn.find(pat) == 2
        assert dn.find(pat, 1) == 2
        assert dn.find(pat, 1, 3) == 2
        assert dn.find(pat, 2, 3) == 2
        assert dn.find(pat, 6) == 6

        assert dn.find(pat, 7) == -1
        assert dn.find(pat, 1, 2) == -1

        with pytest.raises(ValueError):
            assert dn.index(pat, 7) == -1
        with pytest.raises(ValueError):
            assert dn.index(pat, 1, 2) == -1

        # reverse
        assert dn.rfind(pat) == 6
        assert dn.rfind(pat, -4) == 6
        assert dn.rfind(pat, 6) == 6
        assert dn.rfind(pat, 6, 8) == 6
        assert dn.rfind(pat, 6, 8) == 6
        assert dn.rfind(pat, -8) == 6
        assert dn.rfind(pat, -8, -4) == 6
        assert dn.rfind(pat, -8, -5) == 2

        assert dn.rfind(pat, 7) == -1
        assert dn.rfind(pat, -3) == -1

        with pytest.raises(ValueError):
            assert dn.rindex(pat, 7) == -1
        with pytest.raises(ValueError):
            assert dn.rindex(pat, -3) == -1

    def test_replace(self):
        # pylint: disable=no-member
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with pytest.raises(AttributeError):
            dn.replace  # pylint: disable=pointless-statement

    def test_hashing(self):
        # create DN's that are equal but differ in case
        dn1 = DN((self.attr1.lower(), self.value1.upper()))
        dn2 = DN((self.attr1.upper(), self.value1.lower()))

        # DNs that are equal should hash to the same value.
        assert dn1 == dn2

        # Good, everyone's equal, now verify their hash values

        assert hash(dn1) == hash(dn2)

        # Different DN objects with the same value should
        # map to 1 common key and 1 member in a set. The key and
        # member are based on the object's value.

        dn1_a = DN(self.dn1)
        dn1_b = DN(self.dn1)

        dn2_a = DN(self.dn2)
        dn2_b = DN(self.dn2)

        dn3_a = DN(self.dn3)
        dn3_b = DN(self.dn3)

        assert dn1_a == dn1_b
        assert dn2_a == dn2_b
        assert dn3_a == dn3_b

        d = dict()
        s = set()

        d[dn1_a] = str(dn1_a)
        d[dn1_b] = str(dn1_b)
        d[dn2_a] = str(dn2_a)
        d[dn2_b] = str(dn2_b)

        s.add(dn1_a)
        s.add(dn1_b)
        s.add(dn2_a)
        s.add(dn2_b)

        assert len(d) == 2
        assert len(s) == 2
        assert sorted(d) == sorted([dn1_a, dn2_a])
        assert sorted(s) == sorted([dn1_a, dn2_a])

        assert dn1_a in d
        assert dn1_b in d
        assert dn2_a in d
        assert dn2_b in d
        assert dn3_a not in d
        assert dn3_b not in d

        assert dn1_a in s
        assert dn1_b in s
        assert dn2_a in s
        assert dn2_b in s
        assert dn3_a not in s
        assert dn3_b not in s

    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        assert nulldn.ldap_text() == nulldn.x500_text()

        # reverse a DN with a single RDN
        assert self.dn1.ldap_text() == self.dn1.x500_text()

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        assert dn3_rev.ldap_text() == dn3_x500

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            assert longdn_rev[i] == self.base_container_dn[l - 1 - i]
Example #6
0
class TestDN(unittest.TestCase):
    def setUp(self):
        # ava1 must sort before ava2
        self.attr1 = 'cn'
        self.value1 = u'Bob'
        self.str_ava1 = '%s=%s' % (self.attr1, self.value1)
        self.ava1 = AVA(self.attr1, self.value1)

        self.str_rdn1 = '%s=%s' % (self.attr1, self.value1)
        self.rdn1 = RDN((self.attr1, self.value1))

        self.attr2 = 'ou'
        self.value2 = u'people'
        self.str_ava2 = '%s=%s' % (self.attr2, self.value2)
        self.ava2 = AVA(self.attr2, self.value2)

        self.str_rdn2 = '%s=%s' % (self.attr2, self.value2)
        self.rdn2 = RDN((self.attr2, self.value2))

        self.str_dn1 = self.str_rdn1
        self.dn1 = DN(self.rdn1)

        self.str_dn2 = self.str_rdn2
        self.dn2 = DN(self.rdn2)

        self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2)
        self.dn3 = DN(self.rdn1, self.rdn2)

        self.base_rdn1 = RDN(('dc', 'redhat'))
        self.base_rdn2 = RDN(('dc', 'com'))
        self.base_dn = DN(self.base_rdn1, self.base_rdn2)

        self.container_rdn1 = RDN(('cn', 'sudorules'))
        self.container_rdn2 = RDN(('cn', 'sudo'))
        self.container_dn = DN(self.container_rdn1, self.container_rdn2)

        self.base_container_dn = DN((self.attr1, self.value1),
                                    self.container_dn, self.base_dn)

        self.x500name = x509.Name([
            x509.NameAttribute(x509.NameOID.ORGANIZATIONAL_UNIT_NAME,
                               self.value2),
            x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1),
        ])

    def assertExpectedClass(self, klass, obj, component):
        self.assertIs(obj.__class__, expected_class(klass, component))

    def test_create(self):
        # Create with single attr,value pair
        dn1 = DN((self.attr1, self.value1))
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
        self.assertIsInstance(dn1[0].attr, unicode)
        self.assertIsInstance(dn1[0].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with single attr,value pair passed as a tuple
        dn1 = DN((self.attr1, self.value1))
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Creation with multiple attr,value string pairs should fail
        with self.assertRaises(ValueError):
            dn1 = DN(self.attr1, self.value1, self.attr2, self.value2)

        # Create with multiple attr,value pairs passed as tuples & lists
        dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2])
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple attr,value pairs passed as tuple and RDN
        dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2)))
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple attr,value pairs but reverse
        # constructor parameter ordering. RDN ordering should also be
        # reversed because DN's are a ordered sequence of RDN's
        dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1))
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn2)
        self.assertEqual(dn1[1], self.rdn1)

        # Create with single RDN object
        dn1 = DN(self.rdn1)
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with multiple RDN objects, assure ordering is preserved.
        dn1 = DN(self.rdn1, self.rdn2)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple RDN objects in different order, assure
        # ordering is preserved.
        dn1 = DN(self.rdn2, self.rdn1)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn2)
        self.assertEqual(dn1[1], self.rdn1)

        # Create with single string with 1 RDN
        dn1 = DN(self.str_rdn1)
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with single string with 2 RDN's
        dn1 = DN(self.str_dn3)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with a python-cryptography 'Name'
        dn1 = DN(self.x500name)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with RDN, and 2 DN's (e.g. attr + container + base)
        dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn)
        self.assertEqual(len(dn1), 5)
        dn_str = ','.join([
            str(self.rdn1),
            str(self.container_rdn1),
            str(self.container_rdn2),
            str(self.base_rdn1),
            str(self.base_rdn2)
        ])
        self.assertEqual(str(dn1), dn_str)

    def test_str(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(str(dn1), self.str_dn1)
        self.assertIsInstance(str(dn1), str)

        self.assertEqual(str(dn2), self.str_dn2)
        self.assertIsInstance(str(dn2), str)

        self.assertEqual(str(dn3), self.str_dn3)
        self.assertIsInstance(str(dn3), str)

    def test_cmp(self):
        # Equality
        dn1 = DN((self.attr1, self.value1))

        self.assertTrue(dn1 == self.dn1)
        self.assertFalse(dn1 != self.dn1)

        self.assertTrue(dn1 == self.str_dn1)
        self.assertFalse(dn1 != self.str_dn1)

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 0)

        # Make dn1's attr greater
        with self.assertRaises(AttributeError):
            dn1[0].attr = self.attr1 + "1"
        dn1 = DN((self.attr1 + "1", self.value1))

        self.assertFalse(dn1 == self.dn1)
        self.assertTrue(dn1 != self.dn1)

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 1)

        result = cmp(self.dn1, dn1)
        self.assertEqual(result, -1)

        # Reset dn1's attr, should be equal again
        with self.assertRaises(AttributeError):
            dn1[0].attr = self.attr1
        dn1 = DN((self.attr1, self.value1))

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 0)

        # Make dn1's value greater
        # attr will be equal, this tests secondary comparision component
        with self.assertRaises(AttributeError):
            dn1[0].value = self.value1 + "1"
        dn1 = DN((self.attr1, self.value1 + "1"))

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 1)

        result = cmp(self.dn1, dn1)
        self.assertEqual(result, -1)

        # Make sure dn's with more rdn's are greater
        result = cmp(self.dn1, self.dn3)
        self.assertEqual(result, -1)
        result = cmp(self.dn3, self.dn1)
        self.assertEqual(result, 1)

        # Test startswith, endswith
        container_dn = DN(self.container_dn)
        base_container_dn = DN(self.base_container_dn)

        self.assertTrue(base_container_dn.startswith(self.rdn1))
        self.assertTrue(base_container_dn.startswith(self.dn1))
        self.assertTrue(base_container_dn.startswith(self.dn1 + container_dn))
        self.assertFalse(base_container_dn.startswith(self.dn2))
        self.assertFalse(base_container_dn.startswith(self.rdn2))
        self.assertTrue(base_container_dn.startswith((self.dn1)))
        self.assertTrue(base_container_dn.startswith((self.rdn1)))
        self.assertFalse(base_container_dn.startswith((self.rdn2)))
        self.assertTrue(base_container_dn.startswith((self.rdn2, self.rdn1)))
        self.assertTrue(base_container_dn.startswith((self.dn1, self.dn2)))

        self.assertTrue(base_container_dn.endswith(self.base_dn))
        self.assertTrue(base_container_dn.endswith(container_dn +
                                                   self.base_dn))
        self.assertFalse(base_container_dn.endswith(DN(self.base_rdn1)))
        self.assertTrue(base_container_dn.endswith(DN(self.base_rdn2)))
        self.assertTrue(
            base_container_dn.endswith(
                (DN(self.base_rdn1), DN(self.base_rdn2))))

        # Test "in" membership
        self.assertTrue(self.container_rdn1 in container_dn)
        self.assertTrue(container_dn in container_dn)
        self.assertFalse(self.base_rdn1 in container_dn)

        self.assertTrue(self.container_rdn1 in base_container_dn)
        self.assertTrue(container_dn in base_container_dn)
        self.assertTrue(container_dn + self.base_dn in base_container_dn)
        self.assertTrue(self.dn1 + container_dn +
                        self.base_dn in base_container_dn)
        self.assertTrue(self.dn1 + container_dn +
                        self.base_dn == base_container_dn)

        self.assertFalse(self.container_rdn1 in self.base_dn)

    def test_indexing(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[self.rdn1.attr], self.rdn1.value)
        with self.assertRaises(KeyError):
            dn1['foo']  # pylint: disable=pointless-statement

        self.assertEqual(dn2[0], self.rdn2)
        self.assertEqual(dn2[self.rdn2.attr], self.rdn2.value)
        with self.assertRaises(KeyError):
            dn2['foo']  # pylint: disable=pointless-statement

        self.assertEqual(dn3[0], self.rdn1)
        self.assertEqual(dn3[self.rdn1.attr], self.rdn1.value)
        self.assertEqual(dn3[1], self.rdn2)
        self.assertEqual(dn3[self.rdn2.attr], self.rdn2.value)
        with self.assertRaises(KeyError):
            dn3['foo']  # pylint: disable=pointless-statement

        with self.assertRaises(TypeError):
            dn3[1.0]  # pylint: disable=pointless-statement

    def test_assignments(self):
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with self.assertRaises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0] = RDN('t=a')
        with self.assertRaises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0:1] = [RDN('t=a'), RDN('t=b')]

    def test_iter(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(len(dn1), 1)
        self.assertEqual(dn1[:], self.rdn1)
        for i, ava in enumerate(dn1):
            if i == 0:
                self.assertEqual(ava, self.rdn1)
            else:
                self.fail("got iteration index %d, but len=%d" %
                          (i, len(self.rdn1)))

        self.assertEqual(len(dn2), 1)
        self.assertEqual(dn2[:], self.rdn2)
        for i, ava in enumerate(dn2):
            if i == 0:
                self.assertEqual(ava, self.rdn2)
            else:
                self.fail("got iteration index %d, but len=%d" %
                          (i, len(self.rdn2)))

        self.assertEqual(len(dn3), 2)
        self.assertEqual(dn3[:], DN(self.rdn1, self.rdn2))
        for i, ava in enumerate(dn3):
            if i == 0:
                self.assertEqual(ava, self.rdn1)
            elif i == 1:
                self.assertEqual(ava, self.rdn2)
            else:
                self.fail("got iteration index %d, but len=%d" % (i, len(dn3)))

    def test_concat(self):
        dn1 = DN((self.attr1, self.value1))
        dn2 = DN([self.attr2, self.value2])

        # in-place addtion

        dn1 += dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')

        dn1 = DN((self.attr1, self.value1))
        dn1 += self.rdn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')

        dn1 = DN((self.attr1, self.value1))
        dn1 += self.dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')

        dn1 = DN((self.attr1, self.value1))
        dn1 += self.str_dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')

        # concatenation
        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + self.rdn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.str_rdn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            self.assertExpectedClass(DN, dn3[i][0], 'AVA')

        dn3 = dn1 + self.str_dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

    def test_find(self):
        #        -10 -9  -8     -7  -6  -5  -4     -3  -2  -1
        dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9')
        pat = DN('cn=bob')

        # forward
        self.assertEqual(dn.find(pat), 2)
        self.assertEqual(dn.find(pat, 1), 2)
        self.assertEqual(dn.find(pat, 1, 3), 2)
        self.assertEqual(dn.find(pat, 2, 3), 2)
        self.assertEqual(dn.find(pat, 6), 6)

        self.assertEqual(dn.find(pat, 7), -1)
        self.assertEqual(dn.find(pat, 1, 2), -1)

        with self.assertRaises(ValueError):
            self.assertEqual(dn.index(pat, 7), -1)
        with self.assertRaises(ValueError):
            self.assertEqual(dn.index(pat, 1, 2), -1)

        # reverse
        self.assertEqual(dn.rfind(pat), 6)
        self.assertEqual(dn.rfind(pat, -4), 6)
        self.assertEqual(dn.rfind(pat, 6), 6)
        self.assertEqual(dn.rfind(pat, 6, 8), 6)
        self.assertEqual(dn.rfind(pat, 6, 8), 6)
        self.assertEqual(dn.rfind(pat, -8), 6)
        self.assertEqual(dn.rfind(pat, -8, -4), 6)
        self.assertEqual(dn.rfind(pat, -8, -5), 2)

        self.assertEqual(dn.rfind(pat, 7), -1)
        self.assertEqual(dn.rfind(pat, -3), -1)

        with self.assertRaises(ValueError):
            self.assertEqual(dn.rindex(pat, 7), -1)
        with self.assertRaises(ValueError):
            self.assertEqual(dn.rindex(pat, -3), -1)

    def test_replace(self):
        # pylint: disable=no-member
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with self.assertRaises(AttributeError):
            dn.replace  # pylint: disable=pointless-statement

    def test_hashing(self):
        # create DN's that are equal but differ in case
        dn1 = DN((self.attr1.lower(), self.value1.upper()))
        dn2 = DN((self.attr1.upper(), self.value1.lower()))

        # DNs that are equal should hash to the same value.
        self.assertEqual(dn1, dn2)

        # Good, everyone's equal, now verify their hash values

        self.assertEqual(hash(dn1), hash(dn2))

        # Different DN objects with the same value should
        # map to 1 common key and 1 member in a set. The key and
        # member are based on the object's value.

        dn1_a = DN(self.dn1)
        dn1_b = DN(self.dn1)

        dn2_a = DN(self.dn2)
        dn2_b = DN(self.dn2)

        dn3_a = DN(self.dn3)
        dn3_b = DN(self.dn3)

        self.assertEqual(dn1_a, dn1_b)
        self.assertEqual(dn2_a, dn2_b)
        self.assertEqual(dn3_a, dn3_b)

        d = dict()
        s = set()

        d[dn1_a] = str(dn1_a)
        d[dn1_b] = str(dn1_b)
        d[dn2_a] = str(dn2_a)
        d[dn2_b] = str(dn2_b)

        s.add(dn1_a)
        s.add(dn1_b)
        s.add(dn2_a)
        s.add(dn2_b)

        self.assertEqual(len(d), 2)
        self.assertEqual(len(s), 2)
        self.assertEqual(sorted(d), sorted([dn1_a, dn2_a]))
        self.assertEqual(sorted(s), sorted([dn1_a, dn2_a]))

        self.assertTrue(dn1_a in d)
        self.assertTrue(dn1_b in d)
        self.assertTrue(dn2_a in d)
        self.assertTrue(dn2_b in d)
        self.assertFalse(dn3_a in d)
        self.assertFalse(dn3_b in d)

        self.assertTrue(dn1_a in s)
        self.assertTrue(dn1_b in s)
        self.assertTrue(dn2_a in s)
        self.assertTrue(dn2_b in s)
        self.assertFalse(dn3_a in s)
        self.assertFalse(dn3_b in s)

    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        self.assertEqual(nulldn.ldap_text(), nulldn.x500_text())

        # reverse a DN with a single RDN
        self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text())

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        self.assertEqual(dn3_rev.ldap_text(), dn3_x500)

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            self.assertEqual(longdn_rev[i], self.base_container_dn[l - 1 - i])
Example #7
0
class TestDN(unittest.TestCase):
    def setUp(self):
        # ava1 must sort before ava2
        self.attr1    = 'cn'
        self.value1   = u'Bob'
        self.str_ava1 = '%s=%s' % (self.attr1, self.value1)
        self.ava1     = AVA(self.attr1, self.value1)

        self.str_rdn1 = '%s=%s' % (self.attr1, self.value1)
        self.rdn1     = RDN((self.attr1, self.value1))

        self.attr2    = 'ou'
        self.value2   = u'people'
        self.str_ava2 = '%s=%s' % (self.attr2, self.value2)
        self.ava2     = AVA(self.attr2, self.value2)

        self.str_rdn2 = '%s=%s' % (self.attr2, self.value2)
        self.rdn2     = RDN((self.attr2, self.value2))

        self.str_dn1 = self.str_rdn1
        self.dn1 = DN(self.rdn1)

        self.str_dn2 = self.str_rdn2
        self.dn2 = DN(self.rdn2)

        self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2)
        self.dn3 = DN(self.rdn1, self.rdn2)

        self.base_rdn1 = RDN(('dc', 'redhat'))
        self.base_rdn2 = RDN(('dc', 'com'))
        self.base_dn = DN(self.base_rdn1, self.base_rdn2)

        self.container_rdn1 = RDN(('cn', 'sudorules'))
        self.container_rdn2 = RDN(('cn', 'sudo'))
        self.container_dn = DN(self.container_rdn1, self.container_rdn2)

        self.base_container_dn = DN((self.attr1, self.value1),
                                    self.container_dn, self.base_dn)

        self.x500name = x509.Name([
            x509.NameAttribute(
                x509.NameOID.ORGANIZATIONAL_UNIT_NAME, self.value2),
            x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1),
        ])

    def assertExpectedClass(self, klass, obj, component):
        self.assertIs(obj.__class__, expected_class(klass, component))

    def test_create(self):
        # Create with single attr,value pair
        dn1 = DN((self.attr1, self.value1))
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
        self.assertIsInstance(dn1[0].attr, unicode)
        self.assertIsInstance(dn1[0].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with single attr,value pair passed as a tuple
        dn1 = DN((self.attr1, self.value1))
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Creation with multiple attr,value string pairs should fail
        with self.assertRaises(ValueError):
            dn1 = DN(self.attr1, self.value1, self.attr2, self.value2)

        # Create with multiple attr,value pairs passed as tuples & lists
        dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2])
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple attr,value pairs passed as tuple and RDN
        dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2)))
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple attr,value pairs but reverse
        # constructor parameter ordering. RDN ordering should also be
        # reversed because DN's are a ordered sequence of RDN's
        dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1))
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn2)
        self.assertEqual(dn1[1], self.rdn1)

        # Create with single RDN object
        dn1 = DN(self.rdn1)
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with multiple RDN objects, assure ordering is preserved.
        dn1 = DN(self.rdn1, self.rdn2)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with multiple RDN objects in different order, assure
        # ordering is preserved.
        dn1 = DN(self.rdn2, self.rdn1)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn2)
        self.assertEqual(dn1[1], self.rdn1)

        # Create with single string with 1 RDN
        dn1 = DN(self.str_rdn1)
        self.assertEqual(len(dn1), 1)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)

        # Create with single string with 2 RDN's
        dn1 = DN(self.str_dn3)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with a python-cryptography 'Name'
        dn1 = DN(self.x500name)
        self.assertEqual(len(dn1), 2)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')
            self.assertIsInstance(dn1[i].attr, unicode)
            self.assertIsInstance(dn1[i].value, unicode)
        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[1], self.rdn2)

        # Create with RDN, and 2 DN's (e.g. attr + container + base)
        dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn)
        self.assertEqual(len(dn1), 5)
        dn_str = ','.join([str(self.rdn1),
                            str(self.container_rdn1), str(self.container_rdn2),
                            str(self.base_rdn1), str(self.base_rdn2)])
        self.assertEqual(str(dn1), dn_str)

    def test_str(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(str(dn1), self.str_dn1)
        self.assertIsInstance(str(dn1), str)

        self.assertEqual(str(dn2), self.str_dn2)
        self.assertIsInstance(str(dn2), str)

        self.assertEqual(str(dn3), self.str_dn3)
        self.assertIsInstance(str(dn3), str)

    def test_cmp(self):
        # Equality
        dn1 = DN((self.attr1, self.value1))

        self.assertTrue(dn1 == self.dn1)
        self.assertFalse(dn1 != self.dn1)

        self.assertTrue(dn1 == self.str_dn1)
        self.assertFalse(dn1 != self.str_dn1)

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 0)

        # Make dn1's attr greater
        with self.assertRaises(AttributeError):
            dn1[0].attr = self.attr1 + "1"
        dn1 = DN((self.attr1 + "1", self.value1))

        self.assertFalse(dn1 == self.dn1)
        self.assertTrue(dn1 != self.dn1)

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 1)

        result = cmp(self.dn1, dn1)
        self.assertEqual(result, -1)

        # Reset dn1's attr, should be equal again
        with self.assertRaises(AttributeError):
            dn1[0].attr = self.attr1
        dn1 = DN((self.attr1, self.value1))

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 0)

        # Make dn1's value greater
        # attr will be equal, this tests secondary comparision component
        with self.assertRaises(AttributeError):
            dn1[0].value = self.value1 + "1"
        dn1 = DN((self.attr1, self.value1 + "1"))

        result = cmp(dn1, self.dn1)
        self.assertEqual(result, 1)

        result = cmp(self.dn1, dn1)
        self.assertEqual(result, -1)

        # Make sure dn's with more rdn's are greater
        result = cmp(self.dn1, self.dn3)
        self.assertEqual(result, -1)
        result = cmp(self.dn3, self.dn1)
        self.assertEqual(result, 1)


        # Test startswith, endswith
        container_dn = DN(self.container_dn)
        base_container_dn = DN(self.base_container_dn)

        self.assertTrue(base_container_dn.startswith(self.rdn1))
        self.assertTrue(base_container_dn.startswith(self.dn1))
        self.assertTrue(base_container_dn.startswith(self.dn1 + container_dn))
        self.assertFalse(base_container_dn.startswith(self.dn2))
        self.assertFalse(base_container_dn.startswith(self.rdn2))
        self.assertTrue(base_container_dn.startswith((self.dn1)))
        self.assertTrue(base_container_dn.startswith((self.rdn1)))
        self.assertFalse(base_container_dn.startswith((self.rdn2)))
        self.assertTrue(base_container_dn.startswith((self.rdn2, self.rdn1)))
        self.assertTrue(base_container_dn.startswith((self.dn1, self.dn2)))

        self.assertTrue(base_container_dn.endswith(self.base_dn))
        self.assertTrue(base_container_dn.endswith(container_dn + self.base_dn))
        self.assertFalse(base_container_dn.endswith(DN(self.base_rdn1)))
        self.assertTrue(base_container_dn.endswith(DN(self.base_rdn2)))
        self.assertTrue(base_container_dn.endswith((DN(self.base_rdn1), DN(self.base_rdn2))))

        # Test "in" membership
        self.assertTrue(self.container_rdn1 in container_dn)
        self.assertTrue(container_dn in container_dn)
        self.assertFalse(self.base_rdn1 in container_dn)

        self.assertTrue(self.container_rdn1 in base_container_dn)
        self.assertTrue(container_dn in base_container_dn)
        self.assertTrue(container_dn + self.base_dn in
                        base_container_dn)
        self.assertTrue(self.dn1 + container_dn + self.base_dn in
                        base_container_dn)
        self.assertTrue(self.dn1 + container_dn + self.base_dn ==
                        base_container_dn)

        self.assertFalse(self.container_rdn1 in self.base_dn)

    def test_indexing(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(dn1[0], self.rdn1)
        self.assertEqual(dn1[self.rdn1.attr], self.rdn1.value)
        with self.assertRaises(KeyError):
            dn1['foo']  # pylint: disable=pointless-statement

        self.assertEqual(dn2[0], self.rdn2)
        self.assertEqual(dn2[self.rdn2.attr], self.rdn2.value)
        with self.assertRaises(KeyError):
            dn2['foo']  # pylint: disable=pointless-statement

        self.assertEqual(dn3[0], self.rdn1)
        self.assertEqual(dn3[self.rdn1.attr], self.rdn1.value)
        self.assertEqual(dn3[1], self.rdn2)
        self.assertEqual(dn3[self.rdn2.attr], self.rdn2.value)
        with self.assertRaises(KeyError):
            dn3['foo']  # pylint: disable=pointless-statement

        with self.assertRaises(TypeError):
            dn3[1.0]  # pylint: disable=pointless-statement

    def test_assignments(self):
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with self.assertRaises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0] = RDN('t=a')
        with self.assertRaises(TypeError):
            # pylint: disable=unsupported-assignment-operation
            dn[0:1] = [RDN('t=a'), RDN('t=b')]

    def test_iter(self):
        dn1 = DN(self.dn1)
        dn2 = DN(self.dn2)
        dn3 = DN(self.dn3)

        self.assertEqual(len(dn1), 1)
        self.assertEqual(dn1[:], self.rdn1)
        for i, ava in enumerate(dn1):
            if i == 0:
                self.assertEqual(ava, self.rdn1)
            else:
                self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn1)))

        self.assertEqual(len(dn2), 1)
        self.assertEqual(dn2[:], self.rdn2)
        for i, ava in enumerate(dn2):
            if i == 0:
                self.assertEqual(ava, self.rdn2)
            else:
                self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn2)))

        self.assertEqual(len(dn3), 2)
        self.assertEqual(dn3[:], DN(self.rdn1, self.rdn2))
        for i, ava in enumerate(dn3):
            if i == 0:
                self.assertEqual(ava, self.rdn1)
            elif i == 1:
                self.assertEqual(ava, self.rdn2)
            else:
                self.fail("got iteration index %d, but len=%d" % (i, len(dn3)))

    def test_concat(self):
        dn1 = DN((self.attr1, self.value1))
        dn2 = DN([self.attr2, self.value2])

        # in-place addtion

        dn1 += dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.rdn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn1 += self.str_dn2
        self.assertEqual(dn1, self.dn3)
        self.assertExpectedClass(DN, dn1, 'self')
        for i in range(0, len(dn1)):
            self.assertExpectedClass(DN, dn1[i], 'RDN')
            for j in range(0, len(dn1[i])):
                self.assertExpectedClass(DN, dn1[i][j], 'AVA')


        # concatenation
        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')


        dn1 = DN((self.attr1, self.value1))
        dn3 = dn1 + self.rdn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.str_rdn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            self.assertExpectedClass(DN, dn3[i][0], 'AVA')

        dn3 = dn1 + self.str_dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

        dn3 = dn1 + self.dn2
        self.assertEqual(dn3, self.dn3)
        self.assertExpectedClass(DN, dn3, 'self')
        self.assertExpectedClass(DN, dn3, 'self')
        for i in range(0, len(dn3)):
            self.assertExpectedClass(DN, dn3[i], 'RDN')
            for j in range(0, len(dn3[i])):
                self.assertExpectedClass(DN, dn3[i][j], 'AVA')

    def test_find(self):
        #        -10 -9  -8     -7  -6  -5  -4     -3  -2  -1
        dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9')
        pat = DN('cn=bob')

        # forward
        self.assertEqual(dn.find(pat),          2)
        self.assertEqual(dn.find(pat,  1),      2)
        self.assertEqual(dn.find(pat,  1,  3),  2)
        self.assertEqual(dn.find(pat,  2,  3),  2)
        self.assertEqual(dn.find(pat,  6),      6)

        self.assertEqual(dn.find(pat,  7),     -1)
        self.assertEqual(dn.find(pat,  1,  2), -1)

        with self.assertRaises(ValueError):
            self.assertEqual(dn.index(pat,  7),     -1)
        with self.assertRaises(ValueError):
            self.assertEqual(dn.index(pat,  1,  2), -1)

        # reverse
        self.assertEqual(dn.rfind(pat),          6)
        self.assertEqual(dn.rfind(pat, -4),      6)
        self.assertEqual(dn.rfind(pat,  6),      6)
        self.assertEqual(dn.rfind(pat,  6,  8),  6)
        self.assertEqual(dn.rfind(pat,  6,  8),  6)
        self.assertEqual(dn.rfind(pat, -8),      6)
        self.assertEqual(dn.rfind(pat, -8, -4),  6)
        self.assertEqual(dn.rfind(pat, -8, -5),  2)

        self.assertEqual(dn.rfind(pat,  7),     -1)
        self.assertEqual(dn.rfind(pat, -3),     -1)

        with self.assertRaises(ValueError):
            self.assertEqual(dn.rindex(pat,  7),     -1)
        with self.assertRaises(ValueError):
            self.assertEqual(dn.rindex(pat, -3),     -1)

    def test_replace(self):
        # pylint: disable=no-member
        dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9')
        with self.assertRaises(AttributeError):
            dn.replace  # pylint: disable=pointless-statement

    def test_hashing(self):
        # create DN's that are equal but differ in case
        dn1 = DN((self.attr1.lower(), self.value1.upper()))
        dn2 = DN((self.attr1.upper(), self.value1.lower()))

        # DNs that are equal should hash to the same value.
        self.assertEqual(dn1, dn2)

        # Good, everyone's equal, now verify their hash values

        self.assertEqual(hash(dn1), hash(dn2))

        # Different DN objects with the same value should
        # map to 1 common key and 1 member in a set. The key and
        # member are based on the object's value.

        dn1_a = DN(self.dn1)
        dn1_b = DN(self.dn1)

        dn2_a = DN(self.dn2)
        dn2_b = DN(self.dn2)

        dn3_a = DN(self.dn3)
        dn3_b = DN(self.dn3)

        self.assertEqual(dn1_a, dn1_b)
        self.assertEqual(dn2_a, dn2_b)
        self.assertEqual(dn3_a, dn3_b)

        d = dict()
        s = set()

        d[dn1_a] = str(dn1_a)
        d[dn1_b] = str(dn1_b)
        d[dn2_a] = str(dn2_a)
        d[dn2_b] = str(dn2_b)

        s.add(dn1_a)
        s.add(dn1_b)
        s.add(dn2_a)
        s.add(dn2_b)

        self.assertEqual(len(d), 2)
        self.assertEqual(len(s), 2)
        self.assertEqual(sorted(d), sorted([dn1_a, dn2_a]))
        self.assertEqual(sorted(s), sorted([dn1_a, dn2_a]))

        self.assertTrue(dn1_a in d)
        self.assertTrue(dn1_b in d)
        self.assertTrue(dn2_a in d)
        self.assertTrue(dn2_b in d)
        self.assertFalse(dn3_a in d)
        self.assertFalse(dn3_b in d)

        self.assertTrue(dn1_a in s)
        self.assertTrue(dn1_b in s)
        self.assertTrue(dn2_a in s)
        self.assertTrue(dn2_b in s)
        self.assertFalse(dn3_a in s)
        self.assertFalse(dn3_b in s)

    def test_x500_text(self):
        # null DN x500 ordering and LDAP ordering are the same
        nulldn = DN()
        self.assertEqual(nulldn.ldap_text(), nulldn.x500_text())

        # reverse a DN with a single RDN
        self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text())

        # reverse a DN with 2 RDNs
        dn3_x500 = self.dn3.x500_text()
        dn3_rev = DN(self.rdn2, self.rdn1)
        self.assertEqual(dn3_rev.ldap_text(), dn3_x500)

        # reverse a longer DN
        longdn_x500 = self.base_container_dn.x500_text()
        longdn_rev = DN(longdn_x500)
        l = len(self.base_container_dn)
        for i in range(l):
            self.assertEqual(longdn_rev[i], self.base_container_dn[l-1-i])
Example #8
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        # Fill in a default UUID when not specified.
        if entry_attrs.get('ipatokenuniqueid', None) is None:
            entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4())
            dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'], dn)

        if not _check_interval(options.get('ipatokennotbefore', None),
                               options.get('ipatokennotafter', None)):
            raise ValidationError(name='not_after',
                                  error='is before the validity start')

        # Set the object class and defaults for specific token types
        options['type'] = options['type'].lower()
        entry_attrs['objectclass'] = otptoken.object_class + ['ipatoken' + options['type']]
        for ttype, tattrs in TOKEN_TYPES.items():
            if ttype != options['type']:
                for tattr in tattrs:
                    if tattr in entry_attrs:
                        del entry_attrs[tattr]

        # If owner was not specified, default to the person adding this token.
        # If managedby was not specified, attempt a sensible default.
        if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs:
            cur_dn = DN(self.api.Backend.ldap2.conn.whoami_s()[4:])
            if cur_dn:
                cur_uid = cur_dn[0].value
                prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid)
                if cur_uid == prev_uid:
                    entry_attrs.setdefault('managedby', cur_dn.ldap_text())

        # Resolve the owner's dn
        _normalize_owner(self.api.Object.user, entry_attrs)

        # Get the issuer for the URI
        owner = entry_attrs.get('ipatokenowner', None)
        issuer = api.env.realm
        if owner is not None:
            try:
                issuer = ldap.get_entry(owner, ['krbprincipalname'])['krbprincipalname'][0]
            except (NotFound, IndexError):
                pass

        # Check if key is not empty
        if entry_attrs['ipatokenotpkey'] is None:
            raise ValidationError(name='key', error=_(u'cannot be empty'))

        # Build the URI parameters
        args = {}
        args['issuer'] = issuer
        args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey'])
        args['digits'] = entry_attrs['ipatokenotpdigits']
        args['algorithm'] = entry_attrs['ipatokenotpalgorithm'].upper()
        if options['type'] == 'totp':
            args['period'] = entry_attrs['ipatokentotptimestep']
        elif options['type'] == 'hotp':
            args['counter'] = entry_attrs['ipatokenhotpcounter']

        # Build the URI
        label = urllib.parse.quote(entry_attrs['ipatokenuniqueid'])
        parameters = urllib.parse.urlencode(args)
        uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters)
        setattr(context, 'uri', uri)

        attrs_list.append("objectclass")
        return dn