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