From 442cd658329251d8390dd5bd790d86c78ead88ab Mon Sep 17 00:00:00 2001
From: Tomas Halman <thalman@redhat.com>
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 <atikhono@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(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