Package: libpam-ldap
Version: 180-1.7
Severity: important
Tags: patch

This is a bug already fixed in the upstream release
http://bugzilla.padl.com/show_bug.cgi?id=312

My patch is just the patch attached here and confirmed in the release.  

Without the patch when the primary closes the connection (for example ssl 
problem):
[EMAIL PROTECTED]:~$ ssh echolalia
Connection closed by 192.168.5.40

With the patch:
[EMAIL PROTECTED]:~$ ssh echolalia
Last login: Fri Apr 20 15:04:43 2007 from 192.168.5.20
[EMAIL PROTECTED]:~$

these are both when the uri line in /etc/pam_ldap.conf reads:
uri ldaps://ldap.controldocs.com ldaps://ldap2.controldocs.com

Essentially, if an ldap servers is in a partial down state and returns a
response which closes the connection, no matter how many failovers you have in
the config, it gives up.  Of course this a a bit inconvenient given depending
upon how you have ldap configured not even root is able to login from the
console so you have to reboot into single user mode and remove the offending
server.

I'd like to see this patch backported to at least stable etch.

-- System Information:
Debian Release: 4.0
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-4-686
Locale: LANG=en_US, LC_CTYPE=en_US (charmap=ISO-8859-1)

Versions of packages libpam-ldap depends on:
ii  debconf [debconf-2.0]       1.5.11       Debian configuration management sy
ii  libc6                       2.3.6.ds1-13 GNU C Library: Shared libraries
ii  libldap2                    2.1.30-13.3  OpenLDAP libraries
ii  libpam0g                    0.79-4       Pluggable Authentication Modules l

libpam-ldap recommends no packages.

-- debconf information excluded
--- libpam-ldap-180.orig/pam_ldap.c	2006-10-19 08:22:27.000000000 -0500
+++ libpam-ldap-180/pam_ldap.c	2007-03-03 01:13:10.000000000 -0600
@@ -1512,7 +1512,18 @@
   int msgid;
   struct timeval timeout;
   LDAPMessage *result;
+  int reconnect = 0;
 
+retry:
+  if (reconnect) 
+    {
+      if (session->ld != NULL)
+        {
+          ldap_unbind (session->ld);
+          session->ld = NULL;
+        }
+      syslog(LOG_ERR, "pam_ldap: reconnecting to LDAP server...");
+    }
   if (session->ld == NULL)
     {
       rc = _open_session (session);
@@ -1534,8 +1545,15 @@
 
   if (msgid == -1)
     {
+      int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
       syslog (LOG_ERR, "pam_ldap: ldap_simple_bind %s",
-	      ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+	      ldap_err2string (ld_errno));
+      if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+        {
+          reconnect = 1;
+          goto retry;
+        }
       return PAM_AUTHINFO_UNAVAIL;
     }
 
@@ -1544,8 +1562,15 @@
   rc = ldap_result (session->ld, msgid, FALSE, &timeout, &result);
   if (rc == -1 || rc == 0)
     {
+      int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
       syslog (LOG_ERR, "pam_ldap: ldap_result %s",
-	      ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+	      ldap_err2string (ld_errno));
+      if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+        {
+          reconnect = 1;
+          goto retry;
+        }
       return PAM_AUTHINFO_UNAVAIL;
     }
 
@@ -1882,6 +1907,7 @@
   LDAPControl passwd_policy_req;
   LDAPControl *srvctrls[2], **psrvctrls = NULL;
   struct berval userpw;
+  int reconnect=0;
 #endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */
 
   /* avoid binding anonymously with a DN but no password */
@@ -1896,6 +1922,18 @@
   if (session->info->bound_as_user)
     return PAM_SUCCESS;
 
+retry:
+  if (reconnect) 
+    {
+      if (session->ld != NULL)
+        {
+          ldap_unbind (session->ld);
+          session->ld = NULL;
+        }
+      session->info->bound_as_user = 0;
+      syslog(LOG_INFO, "pam_ldap: reconnecting to LDAP server...");
+    }
+
   if (session->ld == NULL)
     {
       rc = _open_session (session);
@@ -1952,8 +1990,15 @@
 					 _do_sasl_interact, &args);
       if (rc != LDAP_SUCCESS)
 	{
+          int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
 	  syslog (LOG_ERR, "pam_ldap: ldap_sasl_interactive_bind %s",
-		  ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+		  ldap_err2string (ld_errno));
+          if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+            {
+              reconnect = 1;
+              goto retry;
+            }
 	  _pam_overwrite (session->info->userpw);
 	  _pam_drop (session->info->userpw);
 	  return PAM_AUTHINFO_UNAVAIL;
@@ -1973,8 +2018,15 @@
 			&userpw, psrvctrls, 0, &msgid);
       if (rc != LDAP_SUCCESS || msgid == -1)
 	{
+          int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
 	  syslog (LOG_ERR, "pam_ldap: ldap_sasl_bind %s",
-		  ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+		  ldap_err2string (ld_errno));
+          if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+            {
+              reconnect = 1;
+              goto retry;
+            }
 	  _pam_overwrite (session->info->userpw);
 	  _pam_drop (session->info->userpw);
 	  return PAM_AUTHINFO_UNAVAIL;
@@ -1986,8 +2038,15 @@
 				session->info->userpw);
       if (msgid == -1)
 	{
+          int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
 	  syslog (LOG_ERR, "pam_ldap: ldap_simple_bind %s",
-		  ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+		  ldap_err2string (ld_errno));
+          if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+            {
+              reconnect = 1;
+              goto retry;
+            }
 	  _pam_overwrite (session->info->userpw);
 	  _pam_drop (session->info->userpw);
 	  return PAM_AUTHINFO_UNAVAIL;
@@ -1999,8 +2058,18 @@
 		      session->info->userpw);
   if (msgid == -1)
     {
+      int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
+
+
+
       syslog (LOG_ERR, "pam_ldap: ldap_simple_bind %s",
-	      ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+	      ldap_err2string (ld_errno));
+      if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+        {
+          reconnect = 1;
+          goto retry;
+        }
       _pam_overwrite (session->info->userpw);
       _pam_drop (session->info->userpw);
       return PAM_AUTHINFO_UNAVAIL;
@@ -2012,8 +2081,15 @@
   rc = ldap_result (session->ld, msgid, FALSE, &timeout, &result);
   if (rc == -1 || rc == 0)
     {
+      int ld_errno = ldap_get_lderrno (session->ld, 0, 0);
+
       syslog (LOG_ERR, "pam_ldap: ldap_result %s",
-	      ldap_err2string (ldap_get_lderrno (session->ld, 0, 0)));
+	      ldap_err2string (ld_errno));
+      if (ld_errno == LDAP_SERVER_DOWN && !reconnect) 
+        {
+          reconnect = 1;
+          goto retry;
+        }
       _pam_overwrite (session->info->userpw);
       _pam_drop (session->info->userpw);
       return PAM_AUTHINFO_UNAVAIL;

Reply via email to