Blob Blame History Raw
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