|
From: Steffen R. <ste...@sy...> - 2002-06-29 22:09:21
Attachments:
python-ldap.diff
|
Hi, I recently ran into a problem with a replicated iPlanet directory server. My client was setup to write to the slave directory, which answered with a REFERRAL. The client was trying to follow the referral but could not authenticate with the master directory. After looking into the code I found that the "set_rebind_proc" method has been disabled "until made OpenLDAP2 compatible". Since I need this functionality, I have implemented an openLDAP2 compatible version of set_rebind_proc. The old implementation had an IMHO very bad design flaw: only one rebind_proc was allowed for the whole module. In other words, if you try to open more than one directory connection, the rebind_proc could only be set to one directory, rebinds to the other directory would have fatal consequences (either python-fatal error or a segfault). Since I need to support multiple connections to different directories as well, I implemented a solution for this problem. My solution is not ideal, but I think it is a reasonable compromise. Ideally I would extend the LDAP object and store the rebind callback in the extended version, but LDAP is an opaque object handled by the OpenLDAP library. My alternative is to keep track of the allocated LDAPObjects and map the LDAP object to the corresponding LDAPObject. For this purpose I'm storing the LDAPObjects in a linked list. I don't expect a big number of LDAPObjects to be allocated, so the overhead of doing a linear search should be acceptable. I kept the interface for the callback the same as it was for the old implementation, i.e. the callback has to accept an LDAP object and return a tuple (DN, CRED, METHOD). The second part of the patch is for the python wrapper. I added an automatic rebind_procedure, which is installed when you call a version of "bind()". This way referrals should normally be transparent to the client. I am not sure whether this is a good idea or not (?). /steffen -- ste...@sy... <> Gravity is a myth -- the Earth sucks! |
|
From: <mi...@st...> - 2002-06-30 15:13:10
|
Steffen Ries wrote: > > I recently ran into a problem with a replicated iPlanet directory > server. My client was setup to write to the slave directory, which > answered with a REFERRAL. The client was trying to follow the > referral but could not authenticate with the master directory. Steffen, I can confirm that you already hit many of the issues with following referrals. > After looking into the code I found that the "set_rebind_proc" method > has been disabled "until made OpenLDAP2 compatible". Since I need this > functionality, I have implemented an openLDAP2 compatible version of > set_rebind_proc. AFAIR there was no decision made yet in the OpenLDAP project how to implement set_rebind_proc. But I have to check recent status. > The old implementation had an IMHO very bad design flaw: only one > rebind_proc was allowed for the whole module. Which is not the only design flaw of set_rebind_proc. It's rather flawed by design... > Since I need to support multiple connections to different directories > as well, I implemented a solution for this problem. I have to admit that I'm scared about adding such functionality into the C part of python-ldap. I'd like to encourage you to find a Python-only solution which is easier to maintain. BTW: That's exactly one of the benefits of class ldap.ldapobject.LDAPObject: It can be sub-classed for extending its functionality. > I kept the interface for the callback the same as it was for the old > implementation, i.e. the callback has to accept an LDAP object and > return a tuple (DN, CRED, METHOD). Please check whether this complies to what's done in OpenLDAP 2 today. > The second part of the patch is for the python wrapper. I added an > automatic rebind_procedure, which is installed when you call a version > of "bind()". This way referrals should normally be transparent to the > client. I am not sure whether this is a good idea or not (?). My own investigations of this problem lead to not add any generic referral mechanism to python-ldap because one can't find a generic way without making too many assumptions. Several issues with referrals and - a similar problem - LDAP connection failover. Connection handling: An application has to decide whether it follows the referral for a single operation (e.g. a single write operations) or drop the current LDAP connection completely and switch over to the referred server for all following operations. An interesting question in e.g. a one master, many slaves scenario. Another issue is whether there are more operations involved to properly establish a new LDAP connection, e.g. calling start_tls_s(). Bind sequence: Currently most implementations solely use simple bind. But e.g. SASL BindRequests are rather more complicated (Kerberos via GSS-API, SSL with client certificates). Also the target server mentioned in the referral might have other SASL capabilities. Another issue is setting the right LDAP protocol version (negotiated vs. set by a-priori knowledge). Security issues: I have no clue how to model all the different bind mechanisms securely. Also one would have to store credentials (not only passwords)... I'd rather like to see a framework which helps the application developer to implement generic exception handlers for e.g. ldap.SERVER_DOWN or ldap.REFERRAL and decide what to do in his/her specific environment. We could store the last operation tried in a class attribute by just extending LDAPObject._ldap_call(). Hmm, adding the parameters of the LDAP operation which raised a LDAPError exception to the LDAPError exception instance itself would be really nice... Ciao, Michael. |
|
From: Steffen R. <ste...@sy...> - 2002-06-30 16:37:40
|
Michael Str=F6der <mi...@st...> writes: [...] > > After looking into the code I found that the "set_rebind_proc" method > > has been disabled "until made OpenLDAP2 compatible". Since I need this > > functionality, I have implemented an openLDAP2 compatible version of > > set_rebind_proc. >=20 > AFAIR there was no decision made yet in the OpenLDAP project how to > implement set_rebind_proc. But I have to check recent status. I guess I should have done more research and less reverse engineering... :-) I looked through the OpenLDAP mailing list archives and found only a couple of messages relating to this issue. I can't say whether the mechanism is finalized, but I've seen concerns that it should not be implemented the way it is. [...] > I have to admit that I'm scared about adding such functionality into > the C part of python-ldap. I'd like to encourage you to find a > Python-only solution which is easier to maintain. BTW: That's exactly > one of the benefits of class ldap.ldapobject.LDAPObject: It can be > sub-classed for extending its functionality. Hmm. Implementing a Python-only solution would require to catch the ldap.REFERRAL (or ldap.PARTIAL_RESULT) for each of the operations, decide how to chase the referral and then retry the operation. I can try to come up with a proposal... > > I kept the interface for the callback the same as it was for the old > > implementation, i.e. the callback has to accept an LDAP object and > > return a tuple (DN, CRED, METHOD). >=20 > Please check whether this complies to what's done in OpenLDAP 2 today. It does not. The new API call passes URL, request type and message-id. I ignored these values (mostly because I don't have any particular use for them...). [...] > I'd rather like to see a framework which helps the application > developer to implement generic exception handlers for > e.g. ldap.SERVER_DOWN or ldap.REFERRAL and decide what to do in > his/her specific environment. >=20 > We could store the last operation tried in a class attribute by just > extending LDAPObject._ldap_call(). Hmm, adding the parameters of the > LDAP operation which raised a LDAPError exception to the LDAPError > exception instance itself would be really nice... Are you thinking of registering error specific exception handlers or pushing the functionality to the application? I would like to add some functionality to the library (call it a framework), rather than burden the application to wrap every search/add/modify with an exception handler for chasing referrals. I have this kind of code in some places for fail over, which makes it pretty hard to maintain. /steffen --=20 ste...@sy... <> Gravity is a myth -- the Earth sucks! |
|
From: <mi...@st...> - 2002-06-30 17:09:55
|
Steffen Ries wrote: > >>I have to admit that I'm scared about adding such functionality into >>the C part of python-ldap. I'd like to encourage you to find a >>Python-only solution which is easier to maintain. BTW: That's exactly >>one of the benefits of class ldap.ldapobject.LDAPObject: It can be >>sub-classed for extending its functionality. > > Hmm. Implementing a Python-only solution would require to catch the > ldap.REFERRAL (or ldap.PARTIAL_RESULT) for each of the operations, > decide how to chase the referral and then retry the operation. I can > try to come up with a proposal... > [..] >>I'd rather like to see a framework which helps the application >>developer to implement generic exception handlers for >>e.g. ldap.SERVER_DOWN or ldap.REFERRAL and decide what to do in >>his/her specific environment. > > Are you thinking of registering error specific exception handlers or > pushing the functionality to the application? LDAPObject._ldap_call could be the point from where registered exception handlers are called. E.g. a new method LDAPObject.ErrorHandler(e,func,args,kwargs) could check whether a generic handler method is registered for a specific LDAPError class and call that handler with these parameters. Now the application would sub-class LDAPObject and implement such handlers applying the specific knowledge about the environment. Note that we have the advantage of having OO-oriented API and exceptions. Therefore we aren't limited to such crude mechanisms common in C like call-back functions. IMHO we should think in this direction. > I would like to add some functionality to the library (call it a > framework), rather than burden the application to wrap every > search/add/modify with an exception handler for chasing referrals. I > have this kind of code in some places for fail over, which makes it > pretty hard to maintain. Well, I'd like to have something in the python-ldap library too. But although it sounds pretty easy I guess it's not. There are some caveats I'm sure (e.g. some kind of nested error handling in exception handlers...). Ciao, Michael. |