diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py --- a/pykolab/auth/ldap/__init__.py +++ b/pykolab/auth/ldap/__init__.py @@ -116,7 +116,8 @@ pykolab.base.Base.__init__(self, domain=domain) self.ldap = None - self.bind = False + self.bind = None + if domain == None: self.domain = conf.get('kolab', 'primary_domain') else: @@ -230,8 +231,7 @@ # Needs to be synchronous or succeeds and continues setting retval # to True!! - self.ldap.simple_bind_s(entry_dn, login[1]) - retval = True + retval = self._bind(entry_dn, login[1]) try: auth_cache.set_entry(_filter, entry_dn) except Exception, errmsg: @@ -260,13 +260,12 @@ # Needs to be synchronous or succeeds and continues setting retval # to True!! - self.ldap.simple_bind_s(entry_dn, login[1]) + retval = self._bind(entry_dn, login[1]) auth_cache.set_entry(_filter, entry_dn) - retval = True except ldap.NO_SUCH_OBJECT, errmsg: log.debug(_("Error occured, there is no such object: %r") % (errmsg), level=8) - self.bind = False + self.bind = None try: auth_cache.del_entry(_filter) except: @@ -981,8 +980,11 @@ return entry_modifications def reconnect(self): + bind = self.bind self._disconnect() self.connect() + if bind is not None: + self._bind(bind['dn'], bind['pw']) def search_entry_by_attribute(self, attr, value, **kw): self._bind() @@ -1183,27 +1185,36 @@ ### API depth level increasing! ### - def _bind(self): - if self.ldap == None: + def _bind(self, bind_dn=None, bind_pw=None): + if self.ldap is None: self.connect() - if not self.bind: - bind_dn = self.config_get('bind_dn') - bind_pw = self.config_get('bind_pw') + if self.bind is None: + if bind_dn is None: + bind_dn = self.config_get('bind_dn') + if bind_pw is None: + bind_pw = self.config_get('bind_pw') + + if bind_dn is not None and (self.bind is None or bind_dn != self.bind['dn']): + self.bind = None # TODO: Binding errors control try: self.ldap.simple_bind_s(bind_dn, bind_pw) - self.bind = True + self.bind = {'dn': bind_dn, 'pw': bind_pw} except ldap.SERVER_DOWN, errmsg: log.error(_("LDAP server unavailable: %r") % (errmsg)) log.error(_("%s") % (traceback.format_exc())) + return False except ldap.INVALID_CREDENTIALS: log.error(_("Invalid DN, username and/or password.")) + return False else: log.debug(_("_bind called, but already bound"), level=9) + return True + def _change_add_group(self, entry, change): """ An entry of type group was added. @@ -2075,7 +2086,7 @@ self._unbind() del self.ldap self.ldap = None - self.bind = False + self.bind = None def _domain_naming_context(self, domain): self._bind() @@ -2268,11 +2279,7 @@ log.debug(_("Finding domain root dn for domain %s") % (domain), level=8) - bind_dn = conf.get('ldap', 'bind_dn') - bind_pw = conf.get('ldap', 'bind_pw') - domain_base_dn = conf.get('ldap', 'domain_base_dn', quiet=True) - domain_filter = conf.get('ldap', 'domain_filter') if not domain_filter == None: @@ -2353,9 +2360,7 @@ log.debug(_("Listing domains..."), level=8) self.connect() - - bind_dn = conf.get('ldap', 'bind_dn') - bind_pw = conf.get('ldap', 'bind_pw') + self._bind() domain_base_dn = conf.get('ldap', 'domain_base_dn', quiet=True) @@ -2373,12 +2378,6 @@ if domain_base_dn == None or domain_filter == None: return [] - # TODO: this function should be wrapped for error handling - try: - self.ldap.simple_bind_s(bind_dn, bind_pw) - except ldap.SERVER_DOWN, e: - raise AuthBackendError, _("Authentication database DOWN") - dna = self.config_get('domain_name_attribute') if dna == None: dna = 'associateddomain' @@ -2415,13 +2414,6 @@ return domains - def _reconnect(self): - """ - Reconnect to LDAP - """ - self._disconnect() - self.connect() - def _synchronize_callback(self, *args, **kw): """ Determine the characteristics of the callback being placed, and @@ -2542,7 +2534,7 @@ """ self.ldap.unbind() - self.bind = False + self.bind = None ### ### Backend search functions