def modify(self, dn, mod_type=None, attrs=None): """ Modify a record """ if self.read_only: msg = 'Running in read-only mode, modification is disabled' logger.info(msg) return msg utf8_dn = self._clean_dn(to_utf8(dn)) res = self.search(base=utf8_dn, scope=self.BASE) attrs = attrs and attrs or {} if res['exception']: return res['exception'] if res['size'] == 0: return 'LDAPDelegate.modify: Cannot find dn "%s"' % dn cur_rec = res['results'][0] mod_list = [] msg = '' for key, values in attrs.items(): if key.endswith(';binary'): key = key[:-7] else: values = map(to_utf8, values) if mod_type is None: if cur_rec.get(key, ['']) != values and values != ['']: mod_list.append((self.REPLACE, key, values)) elif cur_rec.has_key(key) and values == ['']: mod_list.append((self.DELETE, key, None)) else: mod_list.append((mod_type, key, values)) try: connection = self.connect() new_rdn = attrs.get(self.rdn_attr, [''])[0] if new_rdn and new_rdn != cur_rec.get(self.rdn_attr)[0]: raw_utf8_rdn = to_utf8('%s=%s' % (self.rdn_attr, new_rdn)) new_utf8_rdn = self._clean_rdn(raw_utf8_rdn) connection.modrdn_s(utf8_dn, new_utf8_rdn) old_dn_exploded = self.explode_dn(utf8_dn) old_dn_exploded[0] = new_utf8_rdn utf8_dn = ','.join(old_dn_exploded) if mod_list: connection.modify_s(utf8_dn, mod_list) else: debug_msg = 'Nothing to modify: %s' % utf8_dn logger.debug('LDAPDelegate.modify: %s' % debug_msg) except ldap.INVALID_CREDENTIALS, e: e_name = e.__class__.__name__ msg = '%s No permission to modify "%s"' % (e_name, dn)
def delete(self, dn): """ Delete a record """ if self.read_only: msg = 'Running in read-only mode, deletion is disabled' logger.info(msg) return msg msg = '' utf8_dn = self._clean_dn(to_utf8(dn)) try: connection = self.connect() connection.delete_s(utf8_dn) except ldap.INVALID_CREDENTIALS: msg = 'No permission to delete "%s"' % dn except ldap.REFERRAL as e: try: connection = self.handle_referral(e) connection.delete_s(utf8_dn) except ldap.INVALID_CREDENTIALS: msg = 'No permission to delete "%s"' % dn except Exception as e: msg = 'LDAPDelegate.delete: %s' % str(e) except Exception as e: msg = 'LDAPDelegate.delete: %s' % str(e) if msg != '': logger.info(msg, exc_info=1) return msg
def insert(self, base, rdn, attrs=None): """ Insert a new record """ if self.read_only: msg = 'Running in read-only mode, insertion is disabled' logger.info(msg) return msg msg = '' dn = self._clean_dn(to_utf8('%s,%s' % (rdn, base))) attribute_list = [] attrs = attrs and attrs or {} for attr_key, attr_val in attrs.items(): if attr_key.endswith(';binary'): is_binary = True attr_key = attr_key[:-7] else: is_binary = False if isinstance(attr_val, (str, unicode)) and not is_binary: attr_val = [x.strip() for x in attr_val.split(';')] if attr_val != ['']: if not is_binary: attr_val = map(to_utf8, attr_val) attribute_list.append((attr_key, attr_val)) try: connection = self.connect() connection.add_s(dn, attribute_list) except ldap.INVALID_CREDENTIALS, e: e_name = e.__class__.__name__ msg = '%s No permission to insert "%s"' % (e_name, dn)
def search(self, base, scope, filter='(objectClass=*)', attrs=[], bind_dn='', bind_pwd='', convert_filter=True): """ The main search engine """ result = {'exception': '', 'size': 0, 'results': []} if convert_filter: filter = to_utf8(filter) base = self._clean_dn(base) try: connection = self.connect(bind_dn=bind_dn, bind_pwd=bind_pwd) if connection is None: result['exception'] = 'Cannot connect to LDAP server' return result try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) except ldap.REFERRAL, e: connection = self.handle_referral(e) try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) for rec_dn, rec_dict in res: # When used against Active Directory, "rec_dict" may not be # be a dictionary in some cases (instead, it can be a list) # An example of a useless "res" entry that can be ignored # from AD is # (None, ['ldap://ForestDnsZones.PORTAL.LOCAL/DC=ForestDnsZones,DC=PORTAL,DC=LOCAL']) # This appears to be some sort of internal referral, but # we can't handle it, so we need to skip over it. try: items = rec_dict.items() except AttributeError: # 'items' not found on rec_dict continue for key, value in items: if (not isinstance(value, str) and key.lower() not in BINARY_ATTRIBUTES): try: for i in range(len(value)): value[i] = from_utf8(value[i]) except: pass rec_dict['dn'] = from_utf8(rec_dn) result['results'].append(rec_dict) result['size'] += 1
def insert(self, base, rdn, attrs=None): """ Insert a new record """ if self.read_only: msg = 'Running in read-only mode, insertion is disabled' logger.info(msg) return msg msg = '' dn = self._clean_dn(to_utf8('%s,%s' % (rdn, base))) attribute_list = [] attrs = attrs and attrs or {} for attr_key, attr_val in attrs.items(): if attr_key.endswith(';binary'): is_binary = True attr_key = attr_key[:-7] else: is_binary = False if isinstance(attr_val, (str, unicode)) and not is_binary: attr_val = [x.strip() for x in attr_val.split(';')] if attr_val != ['']: if not is_binary: attr_val = list(map(to_utf8, attr_val)) attribute_list.append((attr_key, attr_val)) try: connection = self.connect() connection.add_s(dn, attribute_list) except ldap.INVALID_CREDENTIALS as e: e_name = e.__class__.__name__ msg = '%s No permission to insert "%s"' % (e_name, dn) except ldap.ALREADY_EXISTS as e: e_name = e.__class__.__name__ msg = '%s Record with dn "%s" already exists' % (e_name, dn) except ldap.REFERRAL as e: try: connection = self.handle_referral(e) connection.add_s(dn, attribute_list) except ldap.INVALID_CREDENTIALS: e_name = e.__class__.__name__ msg = '%s No permission to insert "%s"' % (e_name, dn) except Exception as e: e_name = e.__class__.__name__ msg = '%s LDAPDelegate.insert: %s' % (e_name, str(e)) except Exception as e: e_name = e.__class__.__name__ msg = '%s LDAPDelegate.insert: %s' % (e_name, str(e)) if msg != '': logger.info(msg, exc_info=1) return msg
def _get_logged_in_user(self): uid = self.get_current_user() if uid is None: raise Unauthorized() # force logout ldapuserfolder = self._get_ldapuserfolder() user = ldapuserfolder.getUserByDN(ldap_utils.to_utf8(self._build_dn(uid))) if user == None: raise ValueError('User with uid "%s" does not exist' % uid) return user
def search(self, base, scope, filter="(objectClass=*)", attrs=[], bind_dn="", bind_pwd="", convert_filter=True): """ The main search engine """ result = {"exception": "", "size": 0, "results": []} if convert_filter: filter = to_utf8(filter) base = self._clean_dn(base) try: connection = self.connect(bind_dn=bind_dn, bind_pwd=bind_pwd) if connection is None: result["exception"] = "Cannot connect to LDAP server" return result try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) except ldap.REFERRAL, e: connection = self.handle_referral(e) try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) for rec_dn, rec_dict in res: # When used against Active Directory, "rec_dict" may not be # be a dictionary in some cases (instead, it can be a list) # An example of a useless "res" entry that can be ignored # from AD is # (None, ['ldap://ForestDnsZones.PORTAL.LOCAL/DC=ForestDnsZones,DC=PORTAL,DC=LOCAL']) # This appears to be some sort of internal referral, but # we can't handle it, so we need to skip over it. try: items = rec_dict.items() except AttributeError: # 'items' not found on rec_dict continue for key, value in items: if not isinstance(value, str) and key.lower() not in BINARY_ATTRIBUTES: try: for i in range(len(value)): value[i] = from_utf8(value[i]) except: pass rec_dict["dn"] = from_utf8(rec_dn) result["results"].append(rec_dict) result["size"] += 1
def _change_account_password(self, uid, new_password): dn=self._build_dn(uid) # the following code is taken from LDAPUserFolder, because # LDAPUserFolder.manage_editUserPassword does not return error messages ldapuserfolder = self._get_ldapuserfolder() ldap_pw = ldap_utils._createLDAPPassword(new_password, ldapuserfolder._pwd_encryption) err_msg = ldapuserfolder._delegate.modify(dn=dn, attrs={'userPassword':[ldap_pw]}) if err_msg: return err_msg ldapuserfolder._expireUser(ldapuserfolder.getUserByDN(ldap_utils.to_utf8(dn))) return None # no error
def delete(self, dn): """ Delete a record """ if self.read_only: msg = 'Running in read-only mode, deletion is disabled' logger.info(msg) return msg msg = '' utf8_dn = self._clean_dn(to_utf8(dn)) try: connection = self.connect() connection.delete_s(utf8_dn) except ldap.INVALID_CREDENTIALS: msg = 'No permission to delete "%s"' % dn except ldap.REFERRAL, e: try: connection = self.handle_referral(e) connection.delete_s(utf8_dn) except ldap.INVALID_CREDENTIALS: msg = 'No permission to delete "%s"' % dn except Exception, e: msg = 'LDAPDelegate.delete: %s' % str(e)
def search( self , base , scope , filter='(objectClass=*)' , attrs=[] , bind_dn='' , bind_pwd='' , convert_filter=True ): """ The main search engine """ result = { 'exception' : '' , 'size' : 0 , 'results' : [] } if convert_filter: filter = to_utf8(filter) try: base = self._clean_dn(base) except ldap.DECODING_ERROR: msg = 'Invalid base DN' logger.debug(msg, exc_info=1) result['exception'] = msg return result # no need to go further - nothing will work try: connection = self.connect(bind_dn=bind_dn, bind_pwd=bind_pwd) if connection is None: result['exception'] = 'Cannot connect to LDAP server' return result try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) except ldap.REFERRAL, e: connection = self.handle_referral(e) try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) for rec_dn, rec_dict in res: # When used against Active Directory, "rec_dict" may not be # be a dictionary in some cases (instead, it can be a list) # An example of a useless "res" entry that can be ignored # from AD is # (None, ['ldap://ForestDnsZones.PORTAL.LOCAL/DC=ForestDnsZones,DC=PORTAL,DC=LOCAL']) # This appears to be some sort of internal referral, but # we can't handle it, so we need to skip over it. try: items = rec_dict.items() except AttributeError: # 'items' not found on rec_dict continue for key, value in items: if ( not isinstance(value, str) and key.lower() not in BINARY_ATTRIBUTES ): try: for i in range(len(value)): value[i] = from_utf8(value[i]) except: pass rec_dict['dn'] = from_utf8(rec_dn) result['results'].append(rec_dict) result['size'] += 1
def search(self, base, scope, filter='(objectClass=*)', attrs=[], bind_dn='', bind_pwd='', convert_filter=True): """ The main search engine """ result = {'exception': '', 'size': 0, 'results': []} if convert_filter: filter = to_utf8(filter) base = self._clean_dn(base) try: connection = self.connect(bind_dn=bind_dn, bind_pwd=bind_pwd) if connection is None: result['exception'] = 'Cannot connect to LDAP server' return result try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) except ldap.REFERRAL as e: connection = self.handle_referral(e) try: res = connection.search_s(base, scope, filter, attrs) except ldap.PARTIAL_RESULTS: res_type, res = connection.result(all=0) for rec_dn, rec_dict in res: # When used against Active Directory, "rec_dict" may not be # be a dictionary in some cases (instead, it can be a list) # An example of a useless "res" entry that can be ignored # from AD is # (None, ['ldap://ForestDnsZones.PORTAL.LOCAL/\ # DC=ForestDnsZones,DC=PORTAL,DC=LOCAL']) # This appears to be some sort of internal referral, but # we can't handle it, so we need to skip over it. try: items = rec_dict.items() except AttributeError: # 'items' not found on rec_dict continue for key, value in items: if not isinstance(value, str) and \ key.lower() not in BINARY_ATTRIBUTES: try: for i in range(len(value)): value[i] = from_utf8(value[i]) except Exception as e: pass rec_dict['dn'] = from_utf8(rec_dn) result['results'].append(rec_dict) result['size'] += 1 except ldap.INVALID_CREDENTIALS: msg = 'Invalid authentication credentials' logger.debug(msg, exc_info=1) result['exception'] = msg except ldap.NO_SUCH_OBJECT: msg = 'Cannot find %s under %s' % (filter, base) logger.debug(msg, exc_info=1) result['exception'] = msg except (ldap.SIZELIMIT_EXCEEDED, ldap.ADMINLIMIT_EXCEEDED): msg = 'Too many results for this query' logger.warning(msg, exc_info=1) result['exception'] = msg except (KeyboardInterrupt, SystemExit): raise except Exception as e: msg = str(e) logger.error(msg, exc_info=1) result['exception'] = msg return result