Example #1
0
    def update(self, uuid, data, params):

        # Assemble a proper modlist
        dn = self.uuid2dn(uuid)

        mod_attrs = []
        self.log.debug("gathering modifications for entry '%s'" % dn)
        for attr, entry in data.iteritems():

            # Value removed?
            if entry['orig'] and not entry['value']:
                self.log.debug(" * remove attribute '%s'" % attr)
                mod_attrs.append((ldap.MOD_DELETE, attr, None))
                continue

            cnv = getattr(self, "_convert_to_%s" % entry['type'].lower())
            items = []
            for lvalue in entry['value']:
                items.append(cnv(lvalue))

            # New value?
            if not entry['orig'] and entry['value']:
                self.log.debug(" * add attribute '%s' with value %s" % (attr, items))
                mod_attrs.append((ldap.MOD_ADD, attr, items))
                continue

            # Ok, modified...
            self.log.debug(" * replace attribute '%s' with value %s" % (attr, items))
            mod_attrs.append((ldap.MOD_REPLACE, attr, items))

        # Did we change one of the RDN attributes?
        new_rdn_parts = []
        rdns = ldap.dn.str2dn(dn.encode('utf-8'), flags=ldap.DN_FORMAT_LDAPV3)
        rdn_parts = rdns[0]

        for attr, value, idx in rdn_parts:
            if attr in data:
                cnv = getattr(self, "_convert_to_%s" % data[attr]['type'].lower())
                new_rdn_parts.append((attr, cnv(data[attr]['value'][0]), 4))
            else:
                new_rdn_parts.append((attr, value, idx))

        # Build new target DN and check if it has changed...
        tdn = ldap.dn.dn2str([new_rdn_parts] + rdns[1:]).decode('utf-8')

        if tdn != dn:
            self.log.debug("entry needs a rename from '%s' to '%s'" % (dn, tdn))
            self.con.rename_s(dn.encode('utf-8'), ldap.dn.dn2str([new_rdn_parts]))

        # Write back...
        self.log.debug("saving entry '%s'" % tdn)
        return self.con.modify_s(tdn.encode('utf-8'), mod_attrs)
Example #2
0
    def get_timestamps(self, dn):
        res = self.con.search_s(dn.encode('utf-8'), ldap.SCOPE_BASE,
                '(objectClass=*)', [self.create_ts_entry, self.modify_ts_entry])
        cts = self._convert_from_timestamp(res[0][1][self.create_ts_entry][0])
        mts = self._convert_from_timestamp(res[0][1][self.modify_ts_entry][0])

        return cts, mts
Example #3
0
    def identify(self, dn, params):
        ocs = ["(objectClass=%s)" % o.strip() for o in params['objectClasses'].split(",")]
        fltr = "(&" + "".join(ocs) + ")"
        res = self.con.search_s(dn.encode('utf-8'), ldap.SCOPE_BASE, fltr,
                [self.uuid_entry])

        return len(res) == 1
Example #4
0
    def dn2uuid(self, dn):
        res = self.con.search_s(dn.encode('utf-8'), ldap.SCOPE_BASE, '(objectClass=*)',
                [self.uuid_entry])

        # Check if res is valid
        self.__check_res(dn, res)

        return res[0][1][self.uuid_entry][0]
Example #5
0
    def get_uniq_dn(self, rdns, base, data):
        try:
            for dn in self.build_dn_list(rdns, base, data):
                res = self.con.search_s(dn.encode('utf-8'), ldap.SCOPE_BASE, '(objectClass=*)',
                    [self.uuid_entry])

        except ldap.NO_SUCH_OBJECT:
            return dn

        return None
Example #6
0
def explode_dn(dn):
    if isinstance(dn, six.text_type):
        # DNs are expected to be UTF-8-encoded
        dn = dn.encode('UTF-8')

    parts = []
    raw_parts = ldap.dn.explode_dn(dn)
    for part in raw_parts:
        if isinstance(part, six.text_type):
            part = part.encode('UTF-8')
        parts.append(part)

    return parts
Example #7
0
    def retract(self, uuid, data, params):
        # Remove defined data from the specified object
        dn = self.uuid2dn(uuid)
        mod_attrs = []

        # We know about object classes - remove them
        if 'objectClasses' in params:
            ocs = [o.strip() for o in params['objectClasses'].split(",")]
            mod_attrs.append((ldap.MOD_DELETE, 'objectClass', ocs))

        # Remove all other keys related to this object
        for key in data.keys():
            mod_attrs.append((ldap.MOD_DELETE, key, None))

        self.con.modify_s(dn.encode('utf-8'), mod_attrs)

        # Clear identify cache, else we will receive old values from self.identifyObject
        if dn in self.__i_cache_ttl:
            del self.__i_cache[dn]
            del self.__i_cache_ttl[dn]
Example #8
0
    def identify(self, dn, params, fixed_rdn=None):

        # Check for special RDN attribute
        if 'RDN' in params:
            rdns = [o.strip() for o in params['RDN'].split(",")]
            rdn_parts = ldap.dn.str2dn(dn.encode('utf-8'), flags=ldap.DN_FORMAT_LDAPV3)[0]

            found = False
            for rdn_a, rdn_v, dummy in rdn_parts: #@UnusedVariable
                if rdn_a in rdns:
                    found = True

            if not found:
                return False

        custom_filter = ""
        if 'filter' in params:
            custom_filter = params['filter']

        ocs = [o.strip() for o in params['objectClasses'].split(",")]

        # Remove cache if too old
        if dn in self.__i_cache_ttl and self.__i_cache_ttl[dn] - time.time() > 60:
            del self.__i_cache[dn]
            del self.__i_cache_ttl[dn]

        # Split for fixed attrs
        fixed_rdn_filter = ""
        attr = None
        if fixed_rdn:
            attr, value, _ = ldap.dn.str2dn(fixed_rdn.encode('utf-8'), flags=ldap.DN_FORMAT_LDAPV3)[0][0]
            fixed_rdn_filter = ldap.filter.filter_format("(%s=*)", [attr])

        # If we just query for an objectClass, try to get the
        # answer from the cache.
        if not 'filter' in params and dn in self.__i_cache:

            if fixed_rdn:
                if dn in self.__i_cache and attr in self.__i_cache[dn]:
                    self.__i_cache_ttl[dn] = time.time()
                    #noinspection PyUnboundLocalVariable
                    return len(set(ocs) - set(self.__i_cache[dn]['objectClass'])) == 0 and len({value} - set(self.__i_cache[dn][attr])) == 0

            else:
                self.__i_cache_ttl[dn] = time.time()
                return len(set(ocs) - set(self.__i_cache[dn]['objectClass'])) == 0

        fltr = "(&(objectClass=*)" + fixed_rdn_filter + custom_filter + ")"
        try:
            res = self.con.search_s(dn.encode('utf-8'), ldap.SCOPE_BASE, fltr,
                    [self.uuid_entry, 'objectClass'] + ([attr] if attr else []))
        except ldap.NO_SUCH_OBJECT:
            return False

        if len(res) == 1:
            if not dn in self.__i_cache:
                self.__i_cache[dn] = {}

            self.__i_cache[dn]['objectClass'] = res[0][1]['objectClass']
            self.__i_cache_ttl[dn] = time.time()

            if fixed_rdn:
                if attr in res[0][1]:
                    self.__i_cache[dn][attr] = [x.decode('utf-8') for x in res[0][1][attr]]
                else:
                    self.__i_cache[dn][attr] = []

                #noinspection PyUnboundLocalVariable
                return len(set(ocs) - set(self.__i_cache[dn]['objectClass'])) == 0 and len({value} - set(self.__i_cache[dn][attr])) == 0
            else:
                return len(set(ocs) - set(self.__i_cache[dn]['objectClass'])) == 0

        return False
Example #9
0
    def create(self, base, data, params, foreign_keys=None):
        mod_attrs = []
        self.log.debug("gathering modifications for entry on base '%s'" % base)
        for attr, entry in data.iteritems():

            # Skip foreign keys
            if foreign_keys and attr in foreign_keys:
                continue

            cnv = getattr(self, "_convert_to_%s" % entry['type'].lower())
            items = []
            for lvalue in entry['value']:
                items.append(cnv(lvalue))

            self.log.debug(" * add attribute '%s' with value %s" % (attr, items))
            if foreign_keys is None:
                mod_attrs.append((attr, items))
            else:
                mod_attrs.append((ldap.MOD_ADD, attr, items))

        # We know about object classes - add them if possible
        if 'objectClasses' in params:
            ocs = [o.strip() for o in params['objectClasses'].split(",")]
            if foreign_keys is None:
                mod_attrs.append(('objectClass', ocs))
            else:
                mod_attrs.append((ldap.MOD_ADD, 'objectClass', ocs))

        if foreign_keys is None:
            # Check if obligatory information for assembling the DN are
            # provided
            if not 'RDN' in params:
                raise RDNNotSpecified(C.make_error("RDN_NOT_SPECIFIED"))

            # Build unique DN using maybe optional RDN parameters
            rdns = [d.strip() for d in params['RDN'].split(",")]

            FixedRDN = params['FixedRDN'] if 'FixedRDN' in params else None
            dn = self.get_uniq_dn(rdns, base, data, FixedRDN)
            if not dn:
                raise DNGeneratorError(C.make_error("NO_UNIQUE_DN", base=base, rdns=", ".join(rdns)))
            dn = dn.encode('utf-8')

        else:
            dn = base

        self.log.debug("evaluated new entry DN to '%s'" % dn)

        # Write...
        self.log.debug("saving entry '%s'" % dn)

        if foreign_keys is None:
            self.con.add_s(dn, mod_attrs)
        else:
            self.con.modify_s(dn, mod_attrs)

        # Clear identify cache, else we will receive old values from self.identifyObject
        if dn in self.__i_cache_ttl:
            del self.__i_cache[dn]
            del self.__i_cache_ttl[dn]

        # Return automatic uuid
        return self.dn2uuid(dn)
Example #10
0
    def remove(self, uuid, data, params):
        dn = self.uuid2dn(uuid)

        self.log.debug("removing entry '%s'" % dn)
        return self.con.delete_s(dn.encode('utf-8'))
Example #11
0
File: dn.py Project: gonicus/clacks
# -*- coding: utf-8 -*-
import ldap.dn

# Some bits to shredd...
dn = u"cn=Alfred Schröder+uid=fred,ou=Kommunalpolitik\, Geschäftsführung,dc=gonicus,dc=de"

# Remove unicode, because the ldap module does not like it
dn = dn.encode('utf-8')

print "Process:", dn

# Example splitting
print "Split:"
print ldap.dn.str2dn(dn, flags=ldap.DN_FORMAT_LDAPV3)

print "Explode:"
print ldap.dn.explode_dn(dn, flags=ldap.DN_FORMAT_LDAPV3)
print ldap.dn.explode_dn(dn, notypes=True, flags=ldap.DN_FORMAT_LDAPV3)

print "Explode RDN:"
print ldap.dn.explode_rdn("cn=Cajus Pollmeier+uid=cajus")

print "Build DN:"
#print ldap.AVA_BINARY
#print ldap.AVA_STRING
#print ldap.AVA_NULL
#print ldap.AVA_NONPRINTABLE
s = ldap.dn.dn2str([[("cn", "Alfred Schröder", 4), ("uid", "fred", 4)], [('dc', 'gonicus', 4)], [('dc', 'de', 4)]])
print s
print ldap.dn.str2dn(s, flags=ldap.DN_FORMAT_LDAPV3)