From ee16c609497f29731c5a590821d27d0db0ffc91f Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 3 Mar 2021 15:34:49 +0100 Subject: [PATCH] ldap: retry ldap_install_tls() when watchdog interruption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the call to ldap_install_tls() fails because the watchdog interrupted it, retry it. The watchdog interruption is detected by checking the value of the ticks before and after the call to ldap_install_tls(). Resolves: https://github.com/SSSD/sssd/issues/5531 Reviewed-by: Pavel Březina --- src/providers/ldap/sdap_async_connection.c | 27 +++++++++++++++++++++- src/util/sss_ldap.c | 12 ++++++++++ src/util/util.h | 1 + src/util/util_errors.c | 3 +++ src/util/util_errors.h | 3 +++ src/util/util_watchdog.c | 5 ++++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index afa31ea0f..db963044e 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -30,6 +30,8 @@ #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/ldap_common.h" +#define MAX_RETRY_ATTEMPTS 1 + /* ==Connect-to-LDAP-Server=============================================== */ struct sdap_rebind_proc_params { @@ -1447,6 +1449,8 @@ struct sdap_cli_connect_state { enum connect_tls force_tls; bool do_auth; bool use_tls; + + int retry_attempts; }; static int sdap_cli_resolve_next(struct tevent_req *req); @@ -1599,16 +1603,37 @@ static void sdap_cli_connect_done(struct tevent_req *subreq) talloc_zfree(state->sh); ret = sdap_connect_recv(subreq, state, &state->sh); talloc_zfree(subreq); - if (ret) { + if (ret == ERR_TLS_HANDSHAKE_INTERRUPTED && + state->retry_attempts < MAX_RETRY_ATTEMPTS) { + DEBUG(SSSDBG_OP_FAILURE, + "TLS handshake was interruped, provider will retry\n"); + state->retry_attempts++; + subreq = sdap_connect_send(state, state->ev, state->opts, + state->service->uri, + state->service->sockaddr, + state->use_tls); + + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, sdap_cli_connect_done, req); + return; + } else if (ret != EOK) { + state->retry_attempts = 0; /* retry another server */ be_fo_set_port_status(state->be, state->service->name, state->srv, PORT_NOT_WORKING); + ret = sdap_cli_resolve_next(req); if (ret != EOK) { tevent_req_error(req, ret); } + return; } + state->retry_attempts = 0; if (state->use_rootdse) { /* fetch the rootDSE this time */ diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c index 9d1e95217..652b08ea7 100644 --- a/src/util/sss_ldap.c +++ b/src/util/sss_ldap.c @@ -234,6 +234,8 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) int ret; int lret; int optret; + int ticks_before_install; + int ticks_after_install; ret = sssd_async_socket_init_recv(subreq, &state->sd); talloc_zfree(subreq); @@ -261,7 +263,9 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) } if (ldap_is_ldaps_url(state->uri)) { + ticks_before_install = get_watchdog_ticks(); lret = ldap_install_tls(state->ldap); + ticks_after_install = get_watchdog_ticks(); if (lret != LDAP_SUCCESS) { if (lret == LDAP_LOCAL_ERROR) { DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n"); @@ -283,6 +287,14 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) "Check for certificate issues."); } + if (ticks_after_install > ticks_before_install) { + ret = ERR_TLS_HANDSHAKE_INTERRUPTED; + DEBUG(SSSDBG_CRIT_FAILURE, + "Assuming %s\n", + sss_ldap_err2string(ret)); + goto fail; + } + ret = EIO; goto fail; } diff --git a/src/util/util.h b/src/util/util.h index 486394448..94c2e6e3b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -737,6 +737,7 @@ int sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl); /* from util_watchdog.c */ int setup_watchdog(struct tevent_context *ev, int interval); void teardown_watchdog(void); +int get_watchdog_ticks(void); /* from files.c */ int sss_remove_tree(const char *root); diff --git a/src/util/util_errors.c b/src/util/util_errors.c index c35a99a54..0eeaa346c 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -121,6 +121,9 @@ struct err_string error_to_str[] = { { "The last GetAccountDomain() result is still valid" }, /* ERR_GET_ACCT_DOM_CACHED */ { "ID is outside the allowed range" }, /* ERR_ID_OUTSIDE_RANGE */ { "Group ID is duplicated" }, /* ERR_GID_DUPLICATED */ + + { "TLS handshake was interrupted"}, /* ERR_TLS_HANDSHAKE_INTERRUPTED */ + { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index 470f62f9e..366b75650 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -143,6 +143,9 @@ enum sssd_errors { ERR_GET_ACCT_DOM_CACHED, ERR_ID_OUTSIDE_RANGE, ERR_GID_DUPLICATED, + + ERR_TLS_HANDSHAKE_INTERRUPTED, + ERR_LAST /* ALWAYS LAST */ }; diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c index 69160fbdf..7642bfd53 100644 --- a/src/util/util_watchdog.c +++ b/src/util/util_watchdog.c @@ -259,3 +259,8 @@ void teardown_watchdog(void) /* and kill the watchdog event */ talloc_free(watchdog_ctx.te); } + +int get_watchdog_ticks(void) +{ + return __sync_add_and_fetch(&watchdog_ctx.ticks, 0); +} -- 2.26.3