def ldap_init(ro, ldap_url, bind_dn, bind_pw, user_ou, group_ou, committee_ou): global user_search_ou, group_search_ou, committee_search_ou, ldap_conn, read_only read_only = ro user_search_ou = user_ou group_search_ou = group_ou committee_search_ou = committee_ou ldap_conn = ReconnectLDAPObject(ldap_url) ldap_conn.simple_bind_s(bind_dn, bind_pw)
def ldap_connect(settings, use_cache=True): """Establishes an LDAP connection. Establishes a connection to the LDAP server from the `uri` in the ``settings``. To establish a connection, the settings must be specified: - ``uri``: valid URI which points to a LDAP server, - ``bind_dn``: `dn` used to initially bind every LDAP connection - ``bind_password``" password used for the initial bind - ``tls``: ``True`` if the connection should use TLS encryption - ``starttls``: ``True`` to negotiate TLS with the server `Note`: ``starttls`` is ignored if the URI uses LDAPS and ``tls`` is set to ``True``. This function re-uses an existing LDAP connection if there is one available in the application context, unless caching is disabled. :param settings: dict -- The settings for a LDAP provider. :param use_cache: bool -- If the connection should be cached. :return: The ldap connection. """ if use_cache: cache = _get_ldap_cache() cache_key = frozenset( (k, hash(v)) for k, v in iteritems(settings) if k in conn_keys) conn = cache.get(cache_key) if conn is not None: return conn uri_info = urlparse(settings['uri']) use_ldaps = uri_info.scheme == 'ldaps' credentials = (settings['bind_dn'], settings['bind_password']) ldap_connection = ReconnectLDAPObject(settings['uri']) ldap_connection.protocol_version = ldap.VERSION3 ldap_connection.set_option(ldap.OPT_REFERRALS, 0) ldap_connection.set_option( ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND if use_ldaps else ldap.OPT_X_TLS_NEVER) ldap_connection.set_option( ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND if settings['verify_cert'] else ldap.OPT_X_TLS_ALLOW) # force the creation of a new TLS context. This must be the last TLS option. # see: http://stackoverflow.com/a/27713355/298479 ldap_connection.set_option(ldap.OPT_X_TLS_NEWCTX, 0) if use_ldaps and settings['starttls']: warn( "Unable to start TLS, LDAP connection already secured over SSL (LDAPS)" ) elif settings['starttls']: ldap_connection.start_tls_s() # TODO: allow anonymous bind ldap_connection.simple_bind_s(*credentials) if use_cache: cache[cache_key] = ldap_connection return ldap_connection
class DatabaseWrapper(BaseDatabaseWrapper): def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) self.charset = "utf-8" self.creation = DatabaseCreation(self) self.features = DatabaseFeatures(self) if django.VERSION > (1, 4): self.ops = DatabaseOperations(self) else: self.ops = DatabaseOperations() self.settings_dict['SUPPORTS_TRANSACTIONS'] = False def close(self): pass def _commit(self): pass def _cursor(self): if self.connection is None: # self.connection = ldap.initialize(self.settings_dict['NAME']) self.connection = ReconnectLDAPObject(self.settings_dict['NAME']) self.connection.simple_bind_s( self.settings_dict['USER'], self.settings_dict['PASSWORD']) return DatabaseCursor(self.connection) def _rollback(self): pass def add_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.add_s(dn.encode(self.charset), modlist) def delete_s(self, dn): cursor = self._cursor() return cursor.connection.delete_s(dn.encode(self.charset)) def modify_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.modify_s(dn.encode(self.charset), modlist) def rename_s(self, dn, newrdn): cursor = self._cursor() return cursor.connection.rename_s(dn.encode(self.charset), newrdn.encode(self.charset)) def search_s(self, base, scope, filterstr='(objectClass=*)',attrlist=None): logger.debug("base: %s; scope: %s; filter: %s, attrs: %s" % (base, scope, filterstr, attrlist)) cursor = self._cursor() results = cursor.connection.search_s(base, scope, filterstr.encode(self.charset), attrlist) output = [] for dn, attrs in results: output.append((dn.decode(self.charset), attrs)) return output
def ldap_connect(settings, use_cache=True): """Establishes an LDAP connection. Establishes a connection to the LDAP server from the `uri` in the ``settings``. To establish a connection, the settings must be specified: - ``uri``: valid URI which points to a LDAP server, - ``bind_dn``: `dn` used to initially bind every LDAP connection - ``bind_password``" password used for the initial bind - ``tls``: ``True`` if the connection should use TLS encryption - ``starttls``: ``True`` to negotiate TLS with the server `Note`: ``starttls`` is ignored if the URI uses LDAPS and ``tls`` is set to ``True``. This function re-uses an existing LDAP connection if there is one available in the application context, unless caching is disabled. :param settings: dict -- The settings for a LDAP provider. :param use_cache: bool -- If the connection should be cached. :return: The ldap connection. """ if use_cache: cache = _get_ldap_cache() cache_key = frozenset((k, hash(v)) for k, v in iteritems(settings) if k in conn_keys) conn = cache.get(cache_key) if conn is not None: return conn uri_info = urlparse(settings['uri']) use_ldaps = uri_info.scheme == 'ldaps' credentials = (settings['bind_dn'], settings['bind_password']) ldap_connection = ReconnectLDAPObject(settings['uri']) ldap_connection.protocol_version = ldap.VERSION3 ldap_connection.set_option(ldap.OPT_REFERRALS, 0) ldap_connection.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND if use_ldaps else ldap.OPT_X_TLS_NEVER) if settings['cert_file']: ldap_connection.set_option(ldap.OPT_X_TLS_CACERTFILE, settings['cert_file']) ldap_connection.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND if settings['verify_cert'] else ldap.OPT_X_TLS_ALLOW) # force the creation of a new TLS context. This must be the last TLS option. # see: http://stackoverflow.com/a/27713355/298479 ldap_connection.set_option(ldap.OPT_X_TLS_NEWCTX, 0) if use_ldaps and settings['starttls']: warn("Unable to start TLS, LDAP connection already secured over SSL (LDAPS)") elif settings['starttls']: ldap_connection.start_tls_s() # TODO: allow anonymous bind ldap_connection.simple_bind_s(*credentials) if use_cache: cache[cache_key] = ldap_connection return ldap_connection
def simple_bind_s(self, who='', cred='', serverctrls=None, clientctrls=None): res = ReconnectLDAPObject.simple_bind_s(self, who, cred, serverctrls, clientctrls) self.connected = True self.who = who self.cred = cred return res
def simple_bind_s(self, who='', cred='', serverctrls=None, clientctrls=None): res = ReconnectLDAPObject.simple_bind_s(self, who, cred, serverctrls, clientctrls) self.connected = True self.who = who self.cred = cred if self._connection_time is None: self._connection_time = time.time() return res
def simple_bind_s(self, who='', cred='', serverctrls=None, clientctrls=None): res = ReconnectLDAPObject.simple_bind_s(self, who, cred, serverctrls, clientctrls) self.connected = True self.who = who self.cred = cred if self._connection_time is None: self._connection_time = time.time() return res
class LdapLookup(object): connection = None uri = None user = None password = None user_searchbase = '' group_searchbase = '' user_searchfilter = {'objectClass': 'user'} group_searchfilter = {'objectClass': 'group'} def __init__(self, **kw): for key, item in kw.items(): if hasattr(self, key) and not key.startswith('_'): setattr(self, key, item) def connect(self): try: self.connection = ReconnectLDAPObject(self.uri) if self.user is not None: self.connection.simple_bind_s(self.user, self.password) except: logger.exception("LDAP connection failed") return False return True def get_safe(self, basedn, **kw): return self.get( basedn, **dict([(ldap_escape(k), ldap_escape(v)) for k, v in kw.iteritems()])) def get(self, basedn, **kw): search = '(&%s)' % ''.join( ['(%s=%s)' % item for item in kw.iteritems()]) result = self.connection.search_s(basedn, ldap.SCOPE_SUBTREE, search) return result def get_dn(self, dn): res = self.connection.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)') if len(res) == 0: return None else: return res[0] def get_users(self): return self.get(self.user_searchbase, **self.user_searchfilter) def get_user(self, username): search = self.user_searchfilter.copy() if '@' in username: search['userPrincipalName'] = username else: search['sAMAccountName'] = username res = self.get_safe(self.user_searchbase, **search) if len(res) == 0: return None else: return res[0] def get_groups(self): return self.get(self.group_searchbase, **self.group_searchfilter) def get_group(self, groupname): search = self.group_searchfilter.copy() search['name'] = groupname res = self.get_safe(self.group_searchbase, **search) if len(res) == 0: return None else: return res[0]
class LdapLookup(object): connection = None uri = None user = None password = None user_searchbase = '' group_searchbase = '' user_searchfilter = {'objectClass': 'user'} group_searchfilter = {'objectClass': 'group'} def __init__(self, **kw): for key, item in kw.items(): if hasattr(self, key) and not key.startswith('_'): setattr(self, key, item) def connect(self): try: self.connection = ReconnectLDAPObject(self.uri) if self.user is not None: self.connection.simple_bind_s(self.user, self.password) except: logger.exception("LDAP connection failed") return False return True def get_safe(self, basedn, **kw): return self.get(basedn, **dict([(ldap_escape(k), ldap_escape(v)) for k, v in kw.iteritems()])) def get(self, basedn, **kw): search = '(&%s)' % ''.join(['(%s=%s)' % item for item in kw.iteritems()]) result = self.connection.search_s(basedn, ldap.SCOPE_SUBTREE, search) return result def get_dn(self, dn): res = self.connection.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)') if len(res) == 0: return None else: return res[0] def get_users(self): return self.get(self.user_searchbase, **self.user_searchfilter) def get_user(self, username): search = self.user_searchfilter.copy() if '@' in username: search['userPrincipalName'] = username else: search['sAMAccountName'] = username res = self.get_safe(self.user_searchbase, **search) if len(res) == 0: return None else: return res[0] def get_groups(self): return self.get(self.group_searchbase, **self.group_searchfilter) def get_group(self, groupname): search = self.group_searchfilter.copy() search['name'] = groupname res = self.get_safe(self.group_searchbase, **search) if len(res) == 0: return None else: return res[0]
class CSHLDAP: __domain__ = "csh.rit.edu" def __init__(self, bind_dn, bind_pw, batch_mods=False, sasl=False, ro=False): """Handler for bindings to CSH LDAP. Keyword arguments: batch_mods -- whether or not to batch LDAP writes (default False) sasl -- whether or not to bypass bind_dn and bind_pw and use SASL bind ro -- whether or not CSH LDAP is in read only mode (default False) """ if ro: print("########################################\n" "# #\n" "# CSH LDAP IS IN READ ONLY MODE #\n" "# #\n" "########################################") ldap_srvs = srvlookup.lookup("ldap", "tcp", self.__domain__) ldap_uris = "" for uri in ldap_srvs: ldap_uris += "ldaps://"+uri.hostname+"," self.__con__ = ReconnectLDAPObject(ldap_uris) # Allow connections with self-signed certs self.__con__.set_option(self.__con__.OPT_X_TLS_REQUIRE_CERT, self.__con__.OPT_X_TLS_ALLOW) if sasl: self.__con__.sasl_non_interactive_bind_s('') else: self.__con__.simple_bind_s(bind_dn, bind_pw) self.__mod_queue__ = {} self.__pending_mod_dn__ = [] self.__batch_mods__ = batch_mods self.__ro__ = ro def get_member(self, val, uid=False): """Get a CSHMember object. Arguments: val -- the uuid (or uid) of the member Keyword arguments: uid -- whether or not val is a uid (default False) """ return CSHMember(self, val, uid) def get_member_ibutton(self, val): """Get a CSHMember object. Arguments: val -- the iButton ID of the member Returns: None if the iButton supplied does not correspond to a CSH Member """ members = self.__con__.search_s( CSHMember.__ldap_user_ou__, ldap.SCOPE_SUBTREE, "(ibutton=%s)" % val, ['ipaUniqueID']) if members: return CSHMember( self, members[0][1]['ipaUniqueID'][0].decode('utf-8'), False) return None def get_member_slackuid(self, slack): """Get a CSHMember object. Arguments: slack -- the Slack UID of the member Returns: None if the Slack UID provided does not correspond to a CSH Member """ members = self.__con__.search_s( CSHMember.__ldap_user_ou__, ldap.SCOPE_SUBTREE, "(slackuid=%s)" % slack, ['ipaUniqueID']) if members: return CSHMember( self, members[0][1]['ipaUniqueID'][0].decode('utf-8'), False) return None def get_group(self, val): """Get a CSHGroup object. Arguments: val -- the cn of the group """ return CSHGroup(self, val) def get_con(self): """Get the PyLDAP Connection""" return self.__con__ def get_directorship_heads(self, val): """Get the head of a directorship Arguments: val -- the cn of the directorship """ __ldap_group_ou__ = "cn=groups,cn=accounts,dc=csh,dc=rit,dc=edu" res = self.__con__.search_s( __ldap_group_ou__, ldap.SCOPE_SUBTREE, "(cn=eboard-%s)" % val, ['member']) ret = [] for member in res[0][1]['member']: try: ret.append(member.decode('utf-8')) except UnicodeDecodeError: ret.append(member) except KeyError: continue return [CSHMember(self, dn.split('=')[1].split(',')[0], True) for dn in ret] def enqueue_mod(self, dn, mod): """Enqueue a LDAP modification. Arguments: dn -- the distinguished name of the object to modify mod -- an ldap modfication entry to enqueue """ # mark for update if dn not in self.__pending_mod_dn__: self.__pending_mod_dn__.append(dn) self.__mod_queue__[dn] = [] self.__mod_queue__[dn].append(mod) def flush_mod(self): """Flush all pending LDAP modifications.""" for dn in self.__pending_mod_dn__: try: if self.__ro__: for mod in self.__mod_queue__[dn]: if mod[0] == ldap.MOD_DELETE: mod_str = "DELETE" elif mod[0] == ldap.MOD_ADD: mod_str = "ADD" else: mod_str = "REPLACE" print("{} VALUE {} = {} FOR {}".format(mod_str, mod[1], mod[2], dn)) else: self.__con__.modify_s(dn, self.__mod_queue__[dn]) except ldap.TYPE_OR_VALUE_EXISTS: print("Error! Conflicting Batch Modification: %s" % str(self.__mod_queue__[dn])) continue except ldap.NO_SUCH_ATTRIBUTE: print("Error! Conflicting Batch Modification: %s" % str(self.__mod_queue__[dn])) continue self.__mod_queue__[dn] = None self.__pending_mod_dn__ = []
class DatabaseWrapper(BaseDatabaseWrapper): def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) self.charset = "utf-8" self.creation = DatabaseCreation(self) self.features = DatabaseFeatures(self) if django.VERSION > (1, 4): self.ops = DatabaseOperations(self) else: self.ops = DatabaseOperations() self.settings_dict['SUPPORTS_TRANSACTIONS'] = False def close(self): if hasattr(self, 'validate_thread_sharing'): # django >= 1.4 self.validate_thread_sharing() if self.connection is not None: self.connection.unbind_s() self.connection = None def _commit(self): pass def _cursor(self): if self.connection is None: # self.connection = ldap.initialize(self.settings_dict['NAME']) self.connection = ReconnectLDAPObject(self.settings_dict['NAME']) self.connection.simple_bind_s( self.settings_dict['USER'], self.settings_dict['PASSWORD']) return DatabaseCursor(self.connection) def _rollback(self): pass def add_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.add_s(dn.encode(self.charset), modlist) def delete_s(self, dn): cursor = self._cursor() return cursor.connection.delete_s(dn.encode(self.charset)) def modify_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.modify_s(dn.encode(self.charset), modlist) def rename_s(self, dn, newrdn): cursor = self._cursor() return cursor.connection.rename_s(dn.encode(self.charset), newrdn.encode(self.charset)) def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None): logger.debug("base: %s; scope: %s; filter: %s, attrs: %s" % (base, scope, filterstr, attrlist)) cursor = self._cursor() results = cursor.connection.search_s(base, scope, filterstr.encode(self.charset), attrlist) output = [] for dn, attrs in results: output.append((dn.decode(self.charset), attrs)) return output
class DatabaseWrapper(BaseDatabaseWrapper): vendor = 'ldap' # NOTE: These are copied from the mysql DatabaseWrapper operators = { 'exact': '= %s', 'iexact': 'LIKE %s', 'contains': 'LIKE BINARY %s', 'icontains': 'LIKE %s', 'regex': 'REGEXP BINARY %s', 'iregex': 'REGEXP %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': 'LIKE BINARY %s', 'endswith': 'LIKE BINARY %s', 'istartswith': 'LIKE %s', 'iendswith': 'LIKE %s', } def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) self.charset = "utf-8" self.creation = DatabaseCreation(self) self.features = DatabaseFeatures(self) if django.VERSION > (1, 4): self.ops = DatabaseOperations(self) else: self.ops = DatabaseOperations() self.settings_dict['SUPPORTS_TRANSACTIONS'] = True self.autocommit = True def close(self): if hasattr(self, 'validate_thread_sharing'): # django >= 1.4 self.validate_thread_sharing() if self.connection is not None: self.connection.unbind_s() self.connection = None def ensure_connection(self): if self.connection is None: #self.connection = ldap.initialize(self.settings_dict['NAME']) self.connection = ReconnectLDAPObject(self.settings_dict['NAME']) options = self.settings_dict.get('CONNECTION_OPTIONS', {}) for opt, value in options.items(): self.connection.set_option(opt, value) if self.settings_dict.get('TLS', False): self.connection.start_tls_s() self.connection.simple_bind_s( self.settings_dict['USER'], self.settings_dict['PASSWORD']) def _commit(self): pass def _cursor(self): self.ensure_connection() return DatabaseCursor(self.connection) def _rollback(self): pass def _set_autocommit(self, autocommit): pass def add_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.add_s(dn.encode(self.charset), modlist) def delete_s(self, dn): cursor = self._cursor() return cursor.connection.delete_s(dn.encode(self.charset)) def modify_s(self, dn, modlist): cursor = self._cursor() return cursor.connection.modify_s(dn.encode(self.charset), modlist) def rename_s(self, dn, newrdn): cursor = self._cursor() return cursor.connection.rename_s(dn.encode(self.charset), newrdn.encode(self.charset)) def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None): cursor = self._cursor() results = cursor.connection.search_s(base, scope, filterstr.encode(self.charset), attrlist) output = [] for dn, attrs in results: # skip referrals if dn is not None: output.append((dn.decode(self.charset), attrs)) return output
class LDAPUser(object): EPOCH_DATE = datetime.datetime.fromtimestamp(0) LOGIN_SHELL = "/bin/bash" HOME_BASE_DIRECTORY = "/home" GROUP_ID_NUMBER = None CREATOR = None VERIFY_CREATOR = True password_compile = re.compile("^{(%s)}(\S+)$" % "|".join(SUPPORT_METHOD)) def __init__(self, ldap_uri, base_dn, admin_user, admin_password, home_base_directory=None, group_id=None): self.ldap_uri = ldap_uri self.ldap_com = ReconnectLDAPObject(ldap_uri, retry_max=10, retry_delay=3) # self.ldap_com = ldap.initialize(ldap_uri) self.ldap_base_dn = base_dn if home_base_directory is not None: self.HOME_BASE_DIRECTORY = home_base_directory if group_id is not None: self.GROUP_ID_NUMBER = "%s" % group_id self.ldap_admin = "cn=%s,%s" % (admin_user, self.ldap_base_dn) self.people_base_cn = "ou=People,%s" % self.ldap_base_dn self.ldap_com.bind_s(self.ldap_admin, admin_password) def __get_next_uid_number(self): filter_str = "uid=*" attributes = ["uidNumber", "gidNumber"] items = self.ldap_com.search_s(self.people_base_cn, LDAP_SCOPE_SUBTREE, filter_str, attributes) max_number = 1000 for item in items: if "uidNumber" in item[1]: u_number = int(item[1]["uidNumber"][0]) if max_number < u_number: max_number = u_number return max_number + 1 def delete_user(self, user_name): if self.exist(user_name) is None: return True dn = "uid=%s,%s" % (user_name, self.people_base_cn) return self.ldap_com.delete_s(dn) def add_user(self, user_name, uid_number=None, gid_number=None, home_directory=None): dn = "uid=%s,%s" % (user_name, self.people_base_cn) attributes = dict() for key in ("uid", "cn", "sn"): attributes[key] = encode(user_name) attributes["objectClass"] = [ "top", "person", "inetOrgPerson", "posixAccount", "organizationalPerson", "shadowAccount" ] if uid_number is None: attributes["uidNumber"] = encode(self.__get_next_uid_number()) else: attributes["uidNumber"] = encode(uid_number) if gid_number is None: attributes["gidNumber"] = encode(self.GROUP_ID_NUMBER) else: attributes["gidNumber"] = encode(gid_number) if attributes["gidNumber"] is None: raise LDAPError("please set gidNumber") if home_directory is None: home_directory = os.path.join(self.HOME_BASE_DIRECTORY, user_name) attributes["homeDirectory"] = encode(home_directory) attributes["loginShell"] = encode(self.LOGIN_SHELL) if self.CREATOR is not None: attributes["givenName"] = encode(self.CREATOR) mod_list = ldap.modlist.addModlist(attributes) self.ldap_com.add_s(dn, mod_list) def expire_user(self, user_name, shadow_expire=None): user_entry = self.exist(user_name) if user_entry is None: return False old_attributes = user_entry[1] attributes = dict(**old_attributes) if shadow_expire is None: attributes["shadowExpire"] = [ "%s" % (datetime.datetime.now() - self.EPOCH_DATE).days ] else: attributes["shadowExpire"] = "" mod_list = ldap.modlist.modifyModlist(old_attributes, attributes) return self.ldap_com.modify_s(user_entry[0], mod_list) def block_user(self, user_name): return self.expire_user(user_name) def unlock_user(self, user_name): user_entry = self.exist(user_name, "pwdAccountLockedTime", "shadowExpire") if user_entry is None: return False old_attributes = user_entry[1] attributes = dict(**old_attributes) if "pwdAccountLockedTime" in attributes: attributes["pwdAccountLockedTime"] = "" if "shadowExpire" in attributes: attributes["shadowExpire"] = "" mod_list = ldap.modlist.modifyModlist(old_attributes, attributes) return self.ldap_com.modify_s(user_entry[0], mod_list) def _verify_creator(self, user_entry): if self.CREATOR is None or self.VERIFY_CREATOR is False: return True if "givenName" not in user_entry: return False return self.CREATOR in user_entry["givenName"] def exist(self, user_name, *attributes): l_attributes = set(attributes) sr = self.ldap_com.search_s(self.ldap_base_dn, LDAP_SCOPE_SUBTREE, "uid=%s" % user_name, l_attributes) if len(sr) <= 0: return None return sr[0] def verify_password(self, password, ldap_password): match_r = self.password_compile.match(ldap_password) if match_r is not None: method = match_r.groups()[0] cipher_text = match_r.groups()[1] return verify(method, password, cipher_text) return password == ldap_password def login(self, user_name, password): user_entry = self.exist(user_name) if user_entry is None: return False attr = user_entry[1] if "userPassword" not in attr: return False ldap_password = attr["userPassword"][0] return self.verify_password(password, ldap_password) def login2(self, user_name, password): user_entry = self.exist(user_name) if user_entry is None: return False attr = user_entry[1] if "userPassword" not in attr: return False try: self.ldap_com.simple_bind_s(user_entry[0], password) return True except ldap.INVALID_CREDENTIALS: return False def set_password(self, user_name, new_password): user_entry = self.exist(user_name) if user_entry is None: return False if self._verify_creator(user_entry) is False: return False pr = self.ldap_com.passwd_s(user_entry[0], None, new_password) if pr[0] is None and pr[1] is None: return True return False