From 442cd658329251d8390dd5bd790d86c78ead88ab Mon Sep 17 00:00:00 2001 From: Tomas Halman Date: Mon, 24 Jun 2019 15:58:09 +0200 Subject: [PATCH] LDAP: failover does not work on non-responsive ldaps In case ldaps:// is used, then establishing the secure socket is a sychronous operation. If there's nothing on the other end, then the process would be stuck waiting in for the crypto library to finish. Here we set socket read/write timeout so the operation can finish in reasonable time with an error. The ldap_network_timeout option is used for this timeout. Resolves: https://pagure.io/SSSD/sssd/issue/2878 Reviewed-by: Alexey Tikhonov Reviewed-by: Jakub Hrozek (cherry picked from commit 2d657dffb419640860e46ed417137b0e2cc7d9af) --- src/util/sss_sockets.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/util/sss_sockets.c b/src/util/sss_sockets.c index 5e9be9ebd..0e4d8df8a 100644 --- a/src/util/sss_sockets.c +++ b/src/util/sss_sockets.c @@ -74,10 +74,11 @@ static errno_t set_fcntl_flags(int fd, int fd_flags, int fl_flags) return EOK; } -static errno_t set_fd_common_opts(int fd) +static errno_t set_fd_common_opts(int fd, int timeout) { int dummy = 1; int ret; + struct timeval tv; /* SO_KEEPALIVE and TCP_NODELAY are set by OpenLDAP client libraries but * failures are ignored.*/ @@ -97,6 +98,27 @@ static errno_t set_fd_common_opts(int fd) strerror(ret)); } + if (timeout > 0) { + /* Set socket read & write timeout */ + tv = tevent_timeval_set(timeout, 0); + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_FUNC_DATA, + "setsockopt SO_RCVTIMEO failed.[%d][%s].\n", ret, + strerror(ret)); + } + + ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_FUNC_DATA, + "setsockopt SO_SNDTIMEO failed.[%d][%s].\n", ret, + strerror(ret)); + } + } + return EOK; } @@ -264,7 +286,7 @@ struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx, goto fail; } - ret = set_fd_common_opts(state->sd); + ret = set_fd_common_opts(state->sd, timeout); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_common_opts failed.\n"); goto fail; -- 2.20.1