As promised, here's the patch I threw together for the rlm_ldap module
to solve the problem of failed auth when the LDAP server disconnects the
idle connection.
Basically, I took the ldap_connect code out of the perform_search
function into it's own "search_connect" function. Then, if
ldap_search_st returns LDAP_SERVER_DOWN, it sets inst->bound to 0, does
search_connect to try to reconnect to the server, and tries the
ldap_search_st one more time.
Again, my understanding of all this stuff is very limited. For all I
know I created a vast memory leak that will rot your hard drive and
cause your business to go bankrupt.
- Dan
--
- Dan Perik
Computer Services Department
Lapilo Center
New Tribes Mission - PNG
157a158,160
> /* By Dan Perik */
> static int search_connect( void *instance, int res );
>
313a317
> int search_result = 0;
317,323c321
< DEBUG2("rlm_ldap: attempting LDAP reconnection");
< if (inst->ld){
< DEBUG2("rlm_ldap: closing existing LDAP connection");
< ldap_unbind_s(inst->ld);
< }
< if ((inst->ld = ldap_connect(instance, inst->login, inst->password, 0,
&res)) == NULL) {
< radlog(L_ERR, "rlm_ldap: (re)connection attempt failed");
---
> if( !search_connect( inst, res ) ) {
326d323
< inst->bound = 1;
329c326,341
< switch (ldap_search_st(inst->ld, search_basedn, scope, filter, attrs, 0,
&(inst->timeout), result)) {
---
> /* Do LDAP search */
> search_result = ldap_search_st(inst->ld, search_basedn, scope, filter, attrs,
>0, &(inst->timeout), result);
> /* If server is down, it may have disconnected */
> if ( search_result == LDAP_SERVER_DOWN ) {
> DEBUG("rlm_ldap: ldap server connection down, attempting
>reconnection");
> /* So unbind it, and try to reconnect */
> inst->bound = 0;
> if( !search_connect( inst, res ) ) {
> return (RLM_MODULE_FAIL);
> }
>
> /* Now do our search again, if it fails again, then don't try anymore
>*/
> search_result = ldap_search_st(inst->ld, search_basedn, scope, filter,
>attrs, 0, &(inst->timeout), result);
> }
>
> switch ( search_result ) {
335c347
< radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s",
ldap_err2string(ldap_errno));
---
> radlog(L_ERR, "rlm_ldap: ldap_search() failed: %i, %s", ldap_errno,
>ldap_err2string(ldap_errno));
346a359,377
> }
>
> /*
> * search_connect(). Connect to the LDAP server for searches
> * returns true if successful, false if not.
> */
> static int search_connect( void *instance, int res ) {
> ldap_instance *inst = instance;
> DEBUG2("rlm_ldap: attempting LDAP reconnection");
> if (inst->ld){
> DEBUG2("rlm_ldap: closing existing LDAP connection");
> ldap_unbind_s(inst->ld);
> }
> if ((inst->ld = ldap_connect(instance, inst->login, inst->password, 0, &res))
>== NULL) {
> radlog(L_ERR, "rlm_ldap: (re)connection attempt failed");
> return 0; /* false = error */
> }
> inst->bound = 1;
> return -1; /* true = error */