Index: nslcd/cfg.c
===================================================================
--- nslcd/cfg.c (revision 1483)
+++ nslcd/cfg.c (working copy)
@@ -117,6 +117,7 @@
cfg->ldc_bind_timelimit=10;
cfg->ldc_timelimit=LDAP_NO_LIMIT;
cfg->ldc_idle_timelimit=0;
+ cfg->ldc_sock_timelimit=0;
cfg->ldc_reconnect_sleeptime=1;
cfg->ldc_reconnect_retrytime=10;
#ifdef LDAP_OPT_X_TLS
@@ -981,6 +982,11 @@
get_int(filename,lnr,keyword,&line,&cfg->ldc_idle_timelimit);
get_eol(filename,lnr,keyword,&line);
}
+ else if (strcasecmp(keyword,"sock_timelimit")==0)
+ {
+ get_int(filename,lnr,keyword,&line,&cfg->ldc_sock_timelimit);
+ get_eol(filename,lnr,keyword,&line);
+ }
else if (strcasecmp(keyword,"reconnect_tries")==0)
log_log(LOG_WARNING,"%s:%d: option %s has been removed and will be ignored",filename,lnr,keyword);
else if (!strcasecmp(keyword,"reconnect_sleeptime"))
Index: nslcd/cfg.h
===================================================================
--- nslcd/cfg.h (revision 1483)
+++ nslcd/cfg.h (working copy)
@@ -122,6 +122,8 @@
int ldc_timelimit;
/* idle timeout */
int ldc_idle_timelimit;
+ /* socket timeout */
+ int ldc_sock_timelimit;
/* seconds to sleep; doubled until max */
int ldc_reconnect_sleeptime;
/* maximum seconds to sleep */
Index: nslcd/myldap.c
===================================================================
--- nslcd/myldap.c (revision 1483)
+++ nslcd/myldap.c (working copy)
@@ -474,6 +474,51 @@
}
#endif /* HAVE_LDAP_SET_REBIND_PROC */
+/* set a recieve and send timeout on a socket */
+int set_socket_timeout(int sd, long int sec)
+{
+ struct timeval tv;
+ int ret;
+
+ log_log(LOG_DEBUG, "set_socket_timeout(%d, %li)", sd, sec);
+
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = sec;
+
+ ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));
+ if (ret)
+ {
+ log_log(LOG_ERR, "set_socket_timeout(SO_RCVTIMEO): %s", strerror(errno));
+ return -1;
+ }
+
+ ret = setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv));
+ if (ret)
+ {
+ log_log(LOG_ERR, "set_socket_timeout(SO_SNDTIMEO,): %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* gets called from the ldab lib, once a connec()ion was made to the server. we
+ set a timeout on the socket here, to catch netzwork timeouts during the ssl
+ handshake phase */
+int tls_connect_cb( struct ldap *ld, void *ssl, void *ctx, void *arg )
+{
+ int ret;
+ int sd;
+
+ if (ldap_get_option(ld, LDAP_OPT_DESC, &sd) != LDAP_SUCCESS)
+ {
+ log_log(LOG_ERR,"tls_cb() could not get socket from session");
+ return -1;
+ }
+
+ return set_socket_timeout(sd, nslcd_cfg->ldc_sock_timelimit);
+}
+
/* This function sets a number of properties on the connection, based
what is configured in the configfile. This function returns an
LDAP status code. */
@@ -537,6 +582,9 @@
i=LDAP_OPT_X_TLS_HARD;
log_log(LOG_DEBUG,"ldap_set_option(LDAP_OPT_X_TLS,LDAP_OPT_X_TLS_HARD)");
LDAP_SET_OPTION(session->ld,LDAP_OPT_X_TLS,&i);
+
+ log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CONNECT_CB)");
+ LDAP_SET_OPTION(session->ld, LDAP_OPT_X_TLS_CONNECT_CB, tls_connect_cb);
}
#endif /* LDAP_OPT_X_TLS */
/* if nothing above failed, everything should be fine */
Index: nslcd.conf
===================================================================
--- nslcd.conf (revision 1483)
+++ nslcd.conf (working copy)
@@ -58,6 +58,10 @@
# server has not been contacted for the number of seconds.
#idle_timelimit 3600
+# Socket timelimit. Number of seconds to wait when sending/recieving from a socket.
+# 0 means to wait forever.
+# sock_timelimit 0
+
# Use StartTLS without verifying the server certificate.
#ssl start_tls
#tls_reqcert never
Index: man/nslcd.conf.5.xml
===================================================================
--- man/nslcd.conf.5.xml (revision 1483)
+++ man/nslcd.conf.5.xml (working copy)
@@ -474,6 +474,18 @@
+
+ SECONDS
+
+
+ Number of seconds to wait when sending/receiving on a socket. Zero means
+ to wait forever. This can be used to detect hung SSL handshakes by
+ setting it to something other than zero.
+ Defaults to 0.
+
+
+
+
SECONDS