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)
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
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
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]
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
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
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]
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
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)
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'))
# -*- 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)