def _findOverRide(self, dn, overrides):
     while True:
         for dn_variant in get_strings(dn):
             if dn_variant in overrides:
                 return overrides[dn]
         if dn == '':
             break
         dn = dn.up()
     return None
Example #2
0
 def _findOverRide(self, dn, overrides):
     while True:
         for dn_variant in get_strings(dn):
             if dn_variant in overrides:
                 return overrides[dn]
         if dn == '':
             break
         dn = dn.up()
     return None
Example #3
0
    def add(self, key):
        """
        Adding key to the attributes with checking
        if it exists as byte or unicode string
        """
        for k in get_strings(key):
            if k in self:
                return

        set.add(self, key)
Example #4
0
    def remove(self, key):
        """
        Removing key from the attributes with checking
        if it exists as byte or unicode string
        """
        for k in get_strings(key):
            if k in self:
                set.remove(self, k)
                return

        raise KeyError(key)
Example #5
0
 def has_key(self, key):
     for k in get_strings(key):
         if k in self._attributes:
             return True
     return False
Example #6
0
 def get(self, key, default=None):
     for k in get_strings(key):
         if k in self._attributes:
             return self._attributes[k]
     return default
Example #7
0
 def __getitem__(self, key):
     for k in get_strings(key):
         if k in self._attributes:
             return self._attributes[k]
     raise KeyError(key)
Example #8
0
class BaseLDAPEntry(WireStrAlias):
    dn = None
    _object_class_keys = set(get_strings('objectClass'))
    _object_class_lower_keys = set(get_strings('objectclass'))
    _user_password_keys = set(get_strings('userPassword'))

    def __init__(self, dn, attributes={}):
        """

        Initialize the object.

        @param dn: Distinguished Name of the object, as a string.

        @param attributes: Attributes of the object. A dictionary of
        attribute types to list of attribute values.

        """
        self._attributes = InsensitiveDict()
        self.dn = distinguishedname.DistinguishedName(dn)

        for k, vs in attributes.items():
            if k not in self._attributes:
                self._attributes[k] = []
            self._attributes[k].extend(vs)

        for k, vs in self._attributes.items():
            self._attributes[k] = self.buildAttributeSet(k, vs)

    def buildAttributeSet(self, key, values):
        return attributeset.LDAPAttributeSet(key, values)

    def __getitem__(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        raise KeyError(key)

    def get(self, key, default=None):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        return default

    def has_key(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return True
        return False

    def __contains__(self, key):
        return self.has_key(key)

    def __iter__(self):
        for key in self._attributes.iterkeys():
            yield key

    def keys(self):
        a = []
        for key in self._object_class_keys:
            if key in self._attributes:
                a.append(key)
        l = list(self._attributes.keys())
        l.sort(key=to_bytes)
        for key in l:
            if key.lower() not in self._object_class_lower_keys:
                a.append(key)
        return a

    def items(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            if objectClasses:
                a.append((key, objectClasses))

        l = list(self._attributes.items())
        l.sort(key=lambda x: to_bytes(x[0]))
        for key, values in l:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))

        return a

    def toWire(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            a.append((key, objectClasses))

        items_gen = ((key, self[key]) for key in self)
        items = sorted(items_gen, key=lambda x: to_bytes(x[0]))
        for key, values in items:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))
        return ldif.asLDIF(self.dn.getText(), a)

    def getLDIF(self):
        return self.toWire().decode('utf-8')

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return NotImplemented
        if self.dn != other.dn:
            return 0

        my = sorted((key for key in self), key=to_bytes)
        its = sorted((key for key in other), key=to_bytes)
        if my != its:
            return 0
        for key in my:
            myAttr = self[key]
            itsAttr = other[key]
            if myAttr != itsAttr:
                return 0
        return 1

    def __ne__(self, other):
        return not self == other

    def __len__(self):
        return len(self.keys())

    def __bool__(self):
        return True

    def __nonzero__(self):
        return self.__bool__()

    def __repr__(self):
        keys = sorted((key for key in self), key=to_bytes)
        a = []
        for key in keys:
            a.append('%s: %s' % (repr(key), repr(list(self[key]))))
        attributes = ', '.join(a)
        dn = to_bytes(self.dn.getText()) if six.PY2 else self.dn.getText()
        return '%s(%s, {%s})' % (self.__class__.__name__, repr(dn), attributes)

    def diff(self, other):
        """
        Compute differences between this and another LDAP entry.

        @param other: An LDAPEntry to compare to.

        @return: None if equal, otherwise a ModifyOp that would make
        this entry look like other.
        """
        assert self.dn == other.dn
        if self == other:
            return None

        r = []

        myKeys = set(key for key in self)
        otherKeys = set(key for key in other)

        addedKeys = list(otherKeys - myKeys)
        addedKeys.sort(key=to_bytes)  # for reproducability only
        for added in addedKeys:
            r.append(delta.Add(added, other[added]))

        deletedKeys = list(myKeys - otherKeys)
        deletedKeys.sort(key=to_bytes)  # for reproducability only
        for deleted in deletedKeys:
            r.append(delta.Delete(deleted, self[deleted]))

        sharedKeys = list(myKeys & otherKeys)
        sharedKeys.sort(key=to_bytes)  # for reproducability only
        for shared in sharedKeys:

            addedValues = list(other[shared] - self[shared])
            if addedValues:
                addedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Add(shared, addedValues))

            deletedValues = list(self[shared] - other[shared])
            if deletedValues:
                deletedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Delete(shared, deletedValues))

        return delta.ModifyOp(dn=self.dn, modifications=r)

    def bind(self, password):
        return defer.maybeDeferred(self._bind, password)

    def _bind(self, password):
        password = to_bytes(password)
        for key in self._user_password_keys:
            for digest in self.get(key, ()):
                digest = to_bytes(digest)
                if digest.startswith(b'{SSHA}'):
                    raw = base64.decodestring(digest[len(b'{SSHA}'):])
                    salt = raw[20:]
                    got = sshaDigest(password, salt)
                    if got == digest:
                        return self
                else:
                    # Plaintext
                    if digest == password:
                        return self
        raise ldaperrors.LDAPInvalidCredentials()

    def hasMember(self, dn):
        for memberDN in self.get('member', []):
            if memberDN == dn:
                return True
        return False

    def __hash__(self):
        # FIXME:https://github.com/twisted/ldaptor/issues/101
        # The hash should take into consideration any attribute used to
        # decide the equality.
        return hash(self.dn)
Example #9
0
    def match(self, filter):
        if isinstance(filter, pureldap.LDAPFilter_present):
            for value in get_strings(filter.value):
                if value in self:
                    return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_equalityMatch):
            # TODO case insensitivity depends on different attribute syntaxes
            for value in get_strings(filter.assertionValue.value.lower()):
                if value in [val.lower() for val in self.get(filter.attributeDesc.value, [])]:
                    return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_substrings):
            if filter.type not in self:
                return False
            possibleMatches = self[filter.type]
            substrings = filter.substrings[:]

            if (substrings
                and isinstance(filter.substrings[0],
                               pureldap.LDAPFilter_substrings_initial)):
                possibleMatches = [
                    x[len(filter.substrings[0].value):]
                    for x in possibleMatches
                    if x.lower().startswith(filter.substrings[0].value.lower())
                    ]
                del substrings[0]

            if (substrings
                and isinstance(filter.substrings[-1],
                               pureldap.LDAPFilter_substrings_final)):
                possibleMatches = [
                    x[:-len(filter.substrings[0].value)]
                    for x in possibleMatches
                    if x.lower().endswith(filter.substrings[-1].value.lower())
                    ]
                del substrings[-1]

            while possibleMatches and substrings:
                assert isinstance(substrings[0], pureldap.LDAPFilter_substrings_any)
                r = []
                for possible in possibleMatches:
                    i = possible.lower().find(substrings[0].value.lower())
                    if i >= 0:
                        r.append(possible[i:])
                possibleMatches = r
                del substrings[0]
            if possibleMatches and not substrings:
                return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_greaterOrEqual):
            if filter.attributeDesc.value not in self:
                return False
            for value in self[filter.attributeDesc.value]:
                if value  >= filter.assertionValue.value:
                    return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_lessOrEqual):
            if filter.attributeDesc.value not in self:
                return False
            for value in self[filter.attributeDesc.value]:
                if value <= filter.assertionValue.value:
                    return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_and):
            for filt in filter:
                if not self.match(filt):
                    return False
            return True
        elif isinstance(filter, pureldap.LDAPFilter_or):
            for filt in filter:
                if self.match(filt):
                    return True
            return False
        elif isinstance(filter, pureldap.LDAPFilter_not):
            return not self.match(filter.value)
        elif isinstance(filter, pureldap.LDAPFilter_extensibleMatch):
            if filter.matchingRule is None:
                attrib = filter.type.value
                match_value = filter.matchValue.value
                match_value_lower = safelower(match_value)
                if (match_value_lower in [val.lower() for val in self.get(attrib, [])]):
                    return True
                for rdn in self.dn.listOfRDNs:
                    for av in rdn.attributeTypesAndValues:
                        if attrib is None or attrib == av.attributeType:
                            if match_value_lower == safelower(av.value):
                                return True
                return False
            else:
                raise ldapsyntax.MatchNotImplemented(filter)
        else:
            raise ldapsyntax.MatchNotImplemented(filter)
Example #10
0
 def has_key(self, key):
     for k in get_strings(key):
         if k in self._attributes:
             return True
     return False
Example #11
0
 def get(self, key, default=None):
     for k in get_strings(key):
         if k in self._attributes:
             return self._attributes[k]
     return default
Example #12
0
 def __getitem__(self, key):
     for k in get_strings(key):
         if k in self._attributes:
             return self._attributes[k]
     raise KeyError(key)