lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1490 - in nss-pam-ldapd: . nslcd

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd commit: r1490 - in nss-pam-ldapd: . nslcd



Author: arthur
Date: Sun Aug  7 15:10:53 2011
New Revision: 1490
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?view=rev&revision=1490

Log:
set the socket timeout in a connection callback to avoid timeout issues during 
the SSL handshake (based on a patch by Stefan Völke)

Modified:
   nss-pam-ldapd/AUTHORS
   nss-pam-ldapd/nslcd/myldap.c

Modified: nss-pam-ldapd/AUTHORS
==============================================================================
--- nss-pam-ldapd/AUTHORS       Sat Aug  6 22:36:53 2011        (r1489)
+++ nss-pam-ldapd/AUTHORS       Sun Aug  7 15:10:53 2011        (r1490)
@@ -105,3 +105,4 @@
 Alexander V. Chernikov <melifaro@ipfw.ru>
 SATOH Fumiyasu <fumiyas@osstech.co.jp>
 Wesley Mason <wmason@ittc.ku.edu>
+Stefan Völke <stefan.volkel.ext@nsn.com>

Modified: nss-pam-ldapd/nslcd/myldap.c
==============================================================================
--- nss-pam-ldapd/nslcd/myldap.c        Sat Aug  6 22:36:53 2011        (r1489)
+++ nss-pam-ldapd/nslcd/myldap.c        Sun Aug  7 15:10:53 2011        (r1490)
@@ -474,6 +474,61 @@
 }
 #endif /* HAVE_LDAP_SET_REBIND_PROC */
 
+/* set a recieve and send timeout on a socket */
+static int set_socket_timeout(LDAP *ld,time_t sec,suseconds_t usec)
+{
+  struct timeval tv;
+  int rc=LDAP_SUCCESS;
+  int sd;
+  log_log(LOG_DEBUG,"set_socket_timeout(%lu,%lu)",sec,usec);
+  /* get the socket */
+  if ((rc=ldap_get_option(ld,LDAP_OPT_DESC,&sd))!=LDAP_SUCCESS)
+  {
+    log_log(LOG_ERR,"ldap_get_option(LDAP_OPT_DESC) failed: 
%s",ldap_err2string(rc));
+    return rc;
+  }
+  /* ignore invalid (probably closed) file descriptors */
+  if (sd<=0)
+    return LDAP_SUCCESS;
+  /* set timeouts */
+  memset(&tv,0,sizeof(tv));
+  tv.tv_sec=sec;
+  tv.tv_usec=usec;
+  if (setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv)))
+  {
+    log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: 
%s",sd,strerror(errno));
+    rc=LDAP_LOCAL_ERROR;
+  }
+  if (setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv)))
+  {
+    log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: 
%s",sd,strerror(errno));
+    rc=LDAP_LOCAL_ERROR;
+  }
+  return rc;
+}
+
+#ifdef LDAP_OPT_CONNECT_CB
+/* This function is called by the LDAP library once a connection was made to 
the server. We
+   set a timeout on the socket here, to catch netzwork timeouts during the ssl
+   handshake phase. It is configured with LDAP_OPT_CONNECT_CB. */
+static int connect_cb(LDAP *ld,Sockbuf UNUSED(*sb),LDAPURLDesc UNUSED(*srv),
+        struct sockaddr UNUSED(*addr),struct ldap_conncb UNUSED(*ctx))
+{
+  /* set timeout options on socket to avoid hang in some cases (a little
+     more than the normal timeout so this should only be triggered in cases
+     where the library behaves incorrectly) */
+  if (nslcd_cfg->ldc_timelimit)
+    set_socket_timeout(ld,nslcd_cfg->ldc_timelimit,500000);
+  return LDAP_SUCCESS;
+}
+
+/* We have an empty disconnect callback because LDAP_OPT_CONNECT_CB expects
+   both functions to be available. */
+static void disconnect_cb(LDAP UNUSED(*ld),Sockbuf UNUSED(*sb),struct 
ldap_conncb UNUSED(*ctx))
+{
+}
+#endif /* LDAP_OPT_CONNECT_CB */
+
 /* This function sets a number of properties on the connection, based
    what is configured in the configfile. This function returns an
    LDAP status code. */
@@ -482,6 +537,9 @@
   /* FIXME: move this to a global initialisation routine */
   int rc;
   struct timeval tv;
+#ifdef LDAP_OPT_CONNECT_CB
+  struct ldap_conncb cb;
+#endif /* LDAP_OPT_CONNECT_CB */
 #ifdef LDAP_OPT_X_TLS
   int i;
 #endif /* LDAP_OPT_X_TLS */
@@ -528,6 +586,13 @@
   
LDAP_SET_OPTION(session->ld,LDAP_OPT_REFERRALS,nslcd_cfg->ldc_referrals?LDAP_OPT_ON:LDAP_OPT_OFF);
   
log_log(LOG_DEBUG,"ldap_set_option(LDAP_OPT_RESTART,%s)",nslcd_cfg->ldc_restart?"LDAP_OPT_ON":"LDAP_OPT_OFF");
   
LDAP_SET_OPTION(session->ld,LDAP_OPT_RESTART,nslcd_cfg->ldc_restart?LDAP_OPT_ON:LDAP_OPT_OFF);
+#ifdef LDAP_OPT_CONNECT_CB
+  /* register a connection callback */
+  cb.lc_add=connect_cb;
+  cb.lc_del=disconnect_cb;
+  cb.lc_arg=NULL;
+  LDAP_SET_OPTION(session->ld,LDAP_OPT_CONNECT_CB,(void *)&cb);
+#endif /* LDAP_OPT_CONNECT_CB */
 #ifdef LDAP_OPT_X_TLS
   /* if SSL is desired, then enable it */
   if ( (nslcd_cfg->ldc_ssl_on==SSL_LDAPS) ||
@@ -548,23 +613,19 @@
 {
   int i;
   int rc;
-  int sd=-1;
-  struct timeval tv;
-  /* set timeout options on socket to avoid hang in some cases
-     (we set a short timeout because we don't care too much about properly
-     shutting down the connection) */
-  if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
-  {
-    /* ignore errors */
-    tv.tv_sec=nslcd_cfg->ldc_timelimit/2;
-    if (!tv.tv_sec) tv.tv_sec=1;
-    tv.tv_usec=0;
-    (void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
-    (void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
-  }
+  time_t sec;
   /* if we had reachability problems with the server close the connection */
   if (session->ld!=NULL)
   {
+    /* set timeout options on socket to avoid hang in some cases
+       (we set a short timeout because we don't care too much about properly
+       shutting down the connection) */
+    if (nslcd_cfg->ldc_timelimit)
+    {
+      sec=nslcd_cfg->ldc_timelimit/2;
+      if (!sec) sec=1;
+      set_socket_timeout(session->ld,sec,0);
+    }
     /* go over the other searches and partially close them */
     for (i=0;i<MAX_SEARCHES_IN_SESSION;i++)
     {
@@ -634,8 +695,6 @@
 static int do_open(MYLDAP_SESSION *session)
 {
   int rc;
-  int sd=-1;
-  struct timeval tv;
   /* if the connection is still there (ie. ldap_unbind() wasn't
      called) then we can return the cached connection */
   if (session->ld!=NULL)
@@ -684,17 +743,6 @@
     do_close(session);
     return rc;
   }
-  /* set timeout options on socket to avoid hang in some cases
-     (twice the normal timeout so this should only be triggered in cases
-     where the library behaves incorrectly) */
-  if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
-  {
-    /* ignore errors */
-    tv.tv_sec=nslcd_cfg->ldc_timelimit*2;
-    tv.tv_usec=0;
-    (void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
-    (void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
-  }
   /* update last activity and finish off state */
   time(&(session->lastactivity));
   return LDAP_SUCCESS;
-- 
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits