ReconnectLDAPObject doesn't reconnect after main failure
Alain Spineux
aspineux at gmail.com
Sat Jan 27 00:23:00 CET 2007
On 1/26/07, Michael Ströder <michael at stroeder.com> wrote:
> Alain Spineux wrote:
> > When testing ReconnectLDAPObject I found a bug.
> > The object doesn't reconnect after a main failure !
> > [..]
> > I thing the main probleme is here !
> > Look !
>
> Yes, I can reproduce your observation. Thanks for pointing it out.
Don't forget we are on the same boat Captain ! :-)
>
> > l=ldap.ldapobject.ReconnectLDAPObject(ldap_url.initializeUrl())
> > print 'search', l.search_s(ldap_url.dn, ldap.SCOPE_SUBTREE, "(objectClass=*)")
> >
> > this work too ! And don't give any error while their is no bind !
> > work like if l.simple_bind_s('', '') where used just before the search !
>
> Yes, this works as intended in LDAPv3. In opposite to LDAPv2 you MAY
> send a LDAP request without prior bind request.
>
> > I wrote a patch but this is only a workaround that detect the main
> > failure, set a flag and force a reconnect before any request if the
> > flag is set.
>
> Where's the patch?
This is still only a workin "draft" I need to reread it's logic,
anyway I add it at the end
> Can't figure out why it does not send the formerly
> sent bind request. It has all the data around. And if you take the
> server down it will re-send the bind request.
The trick is it doesn't try to reconnect AFTER the main failure (or
BEFORE the next statement) !
Because the first try (of the next ldap statement) doesn't generate
any error, it doesn't try to reconnect and then give the answer as is
! But this is the answer it got like an unauthenticated user !
Look, this is the tcpdump of the last statement !
00:14:21.109514 IP 127.0.0.1.36250 > 127.0.0.1.ldap: S
1795648490:1795648490(0) win 00:14:21.110352 IP 127.0.0.1.ldap >
127.0.0.1.36250: S 1793421325:1793421325(0) ack 1795648491 win 32768
<mss 16396,sackOK,timestamp 516494160 516494159,nop,wscale 7>
00:14:21.110430 IP 127.0.0.1.36250 > 127.0.0.1.ldap: . ack 1 win 257
<nop,nop,timestamp 516494160 516494160>
You can identify the well known 3-way handshaking ! This is a new connection !
I thing libldap open a new connection, but libldap dont store anything
about the credential and then cannot authenticate with the good user !
I will try to reproduce this in C with libc
Here is the patch (including my whoami_s() )
*** ldapobject.py.disconnet Fri Jan 26 22:22:57 2007
--- ldapobject.py.orig Fri Jan 26 13:42:59 2007
***************
*** 678,684 ****
self._retry_delay = retry_delay
self._start_tls = 0
self._reconnects_done = 0L
- self._disconnected=True
def __getstate__(self):
"""return data representation for pickled object"""
--- 678,683 ----
***************
*** 723,730 ****
self.start_tls_s()
# Repeat last simple or SASL bind
self._apply_last_bind()
! except Exception, e:
! self._disconnected=True
if __debug__ and self._trace_level>=1:
self._trace_file.write('*** %d. reconnect to %s failed\n' % (
self._retry_max-reconnect_counter+1,uri
--- 722,728 ----
self.start_tls_s()
# Repeat last simple or SASL bind
self._apply_last_bind()
! except:
if __debug__ and self._trace_level>=1:
self._trace_file.write('*** %d. reconnect to %s failed\n' % (
self._retry_max-reconnect_counter+1,uri
***************
*** 736,742 ****
self._trace_file.write('=> delay %s...\n' % (self._retry_delay))
time.sleep(self._retry_delay)
else:
- self._disconnected=False
if __debug__ and self._trace_level>=1:
self._trace_file.write('*** %d. reconnect to %s
successful, last operation will be repeated\n' % (
self._retry_max-reconnect_counter+1,uri
--- 734,739 ----
***************
*** 745,762 ****
break
def _apply_method_s(self,func,*args,**kwargs):
! if self._disconnected:
self.reconnect(self._uri)
# Re-try last operation
return func(self,*args,**kwargs)
- else:
- try:
- return func(self,*args,**kwargs)
- except ldap.SERVER_DOWN:
- # Reconnect
- self.reconnect(self._uri)
- # Re-try last operation
- return func(self,*args,**kwargs)
def set_option(self,option,invalue):
self._options[option] = invalue
--- 742,754 ----
break
def _apply_method_s(self,func,*args,**kwargs):
! try:
! return func(self,*args,**kwargs)
! except ldap.SERVER_DOWN:
! # Reconnect
self.reconnect(self._uri)
# Re-try last operation
return func(self,*args,**kwargs)
def set_option(self,option,invalue):
self._options[option] = invalue
***************
*** 764,772 ****
def simple_bind_s(self,*args,**kwargs):
self._last_bind = (self.simple_bind_s,args,kwargs)
! result=SimpleLDAPObject.simple_bind_s(self,*args,**kwargs)
! self._disconnected=False
! return result
def start_tls_s(self):
res = SimpleLDAPObject.start_tls_s(self)
--- 756,762 ----
def simple_bind_s(self,*args,**kwargs):
self._last_bind = (self.simple_bind_s,args,kwargs)
! return SimpleLDAPObject.simple_bind_s(self,*args,**kwargs)
def start_tls_s(self):
res = SimpleLDAPObject.start_tls_s(self)
***************
*** 778,786 ****
sasl_interactive_bind_s(who, auth) -> None
"""
self._last_bind = (self.sasl_interactive_bind_s,args,kwargs)
! result=SimpleLDAPObject.sasl_interactive_bind_s(self,*args,**kwargs)
! self._disconnected=False
! return result
def add_ext_s(self,*args,**kwargs):
return self._apply_method_s(SimpleLDAPObject.add_ext_s,*args,**kwargs)
--- 768,774 ----
sasl_interactive_bind_s(who, auth) -> None
"""
self._last_bind = (self.sasl_interactive_bind_s,args,kwargs)
! return SimpleLDAPObject.sasl_interactive_bind_s(self,*args,**kwargs)
def add_ext_s(self,*args,**kwargs):
return self._apply_method_s(SimpleLDAPObject.add_ext_s,*args,**kwargs)
***************
*** 800,808 ****
def search_ext_s(self,*args,**kwargs):
return self._apply_method_s(SimpleLDAPObject.search_ext_s,*args,**kwargs)
- def whoami_s(self,*args,**kwargs):
- return self._apply_method_s(SimpleLDAPObject.whoami_s,*args,**kwargs)
-
class SmartLDAPObject(ReconnectLDAPObject):
"""
--- 788,793 ----
--
Alain Spineux
aspineux gmail com
May the sources be with you
More information about the python-ldap
mailing list