Description: Fix memory leak in libnss-ldap
  A memory leak in libnss-ldap over time can cause the nscd process to 
  grow extremely large. 
  .
  The ldap-nss.c do_init() may be called more then once, to initialize an 
  ldap session and save the session in __session.ls_conn and 
  set the __session.ls_stat = LD_INITIALIZED. But it does not check the 
  state to see if has be initialized, and
  at line 1239: __session.ls_conn = NULL;
Bug: http://bugzilla.padl.com/show_bug.cgi?id=418
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libnss-ldap/+bug/292971
Author: Doug Engert <deengert@anl.gov>
Reviewed-by: Mathias Gug <mathiaz@ubuntu.com>
Reviewed-by: Kees Cook <kees@ubuntu.com>

--- a/ldap-nss.c
+++ b/ldap-nss.c
@@ -184,6 +184,7 @@ static void do_atfork_child (void);
 static void do_atfork_setup (void);
 #endif
 
+static void do_atexit (void);  /* allow exit to cleanup to help valgrind */
 /*
  * Close the global session, sending an unbind.
  */
@@ -551,11 +552,25 @@ do_atfork_setup (void)
   (void) __libc_atfork (do_atfork_prepare, do_atfork_parent, do_atfork_child);
 #endif
 
+atexit(do_atexit); /* allow exit to cleanup to help valgrind */
+
   debug ("<== do_atfork_setup");
 }
 #endif
 
 /*
+ * allow exit to cleanup to help valgrind
+ */
+void
+do_atexit (void)
+{
+  debug ("<== do_atexit");
+  _nss_ldap_enter();
+  do_close();
+  debug ("==> do_atexit (should be no more activity)");
+}
+
+/*
  * Acquires global lock, blocks SIGPIPE.
  */
 void
@@ -1234,9 +1249,9 @@ do_init (void)
 	}
     }
 
-  __session.ls_conn = NULL;
+/* LOOKS LIKE A PROBLEM. COULD BE INITIALIZED, BUT NOT CONNECTED */
+  if (__session.ls_state == LS_UNINITIALIZED) {
   __session.ls_timestamp = 0;
-  __session.ls_state = LS_UNINITIALIZED;
 
 #if defined(HAVE_PTHREAD_ONCE) && defined(HAVE_PTHREAD_ATFORK)
   if (pthread_once (&__once, do_atfork_setup) != 0)
@@ -1355,6 +1370,10 @@ do_init (void)
   __session.ls_state = LS_INITIALIZED;
 
   debug ("<== do_init (initialized session)");
+  } /* if already initialized  but not connected */
+  else {
+    debug ("<== do_init (already initialized)");
+  }
 
   return NSS_SUCCESS;
 }
@@ -1575,6 +1594,7 @@ do_open (void)
 	}
       else
 	{
+          syslog(LOG_ERR, "nss-ldap: do_open: do_start_tls failed:stat=%d", stat);
 	  do_close ();
 	  debug ("<== do_open (TLS startup failed)");
 	  return stat;
