[prev in list] [next in list] [prev in thread] [next in thread]
List: sssd-devel
Subject: =?utf-8?b?W1NTU0Rd?= [sssd PR#5532][synchronized] ldap: retry ldap_install_tls() when watchdog inter
From: ikerexxe <sssd-github-notification () fedorahosted ! org>
Date: 2021-03-31 8:18:21
Message-ID: gh-SSSD/sssd-5532-2021-58aaf2d2-6ecc-442d-a2ef-0627bc6b7969 () sssd-github-notification ! fedorahosted ! org
[Download RAW message or body]
[Attachment #2 (unknown)]
URL: https://github.com/SSSD/sssd/pull/5532
Author: ikerexxe
Title: #5532: ldap: retry ldap_install_tls() when watchdog interruption
Action: synchronized
To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5532/head:pr5532
git checkout pr5532
["sssd-pr-5532.patch" (sssd-pr-5532.patch)]
From 41f59e1b90b331869b56d74414a347a8204c7f2b Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Wed, 3 Mar 2021 15:34:49 +0100
Subject: [PATCH] ldap: retry ldap_install_tls() when watchdog interruption
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
---
src/providers/backend.h | 6 +++-
src/providers/data_provider_fo.c | 32 +++++++++++++++++++++-
src/providers/krb5/krb5_auth.c | 15 ++++++----
src/providers/ldap/sdap_async_connection.c | 32 ++++++++++++++--------
src/util/sss_ldap.c | 12 ++++++++
src/util/util.h | 1 +
src/util/util_errors.c | 2 ++
src/util/util_errors.h | 2 ++
src/util/util_watchdog.c | 5 ++++
9 files changed, 89 insertions(+), 18 deletions(-)
diff --git a/src/providers/backend.h b/src/providers/backend.h
index f8e8af9aa0..c5280c8ffb 100644
--- a/src/providers/backend.h
+++ b/src/providers/backend.h
@@ -60,6 +60,9 @@ struct be_svc_data {
struct be_svc_callback *callbacks;
struct fo_server *first_resolved;
+
+ struct fo_server *current_resolved;
+ int current_resolved_attempts;
};
struct be_failover_ctx {
@@ -189,7 +192,8 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct be_ctx *ctx,
const char *service_name,
- bool first_try);
+ bool first_try,
+ bool retry_same_server);
int be_resolve_server_recv(struct tevent_req *req,
TALLOC_CTX *ref_ctx,
struct fo_server **srv);
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 0dfbb04b0f..91ea7e68c2 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -24,6 +24,8 @@
#include "providers/backend.h"
#include "resolv/async_resolv.h"
+#define MAX_RESOLVED_ATTEMPTS 2
+
struct be_svc_callback {
struct be_svc_callback *prev;
struct be_svc_callback *next;
@@ -506,7 +508,8 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct be_ctx *ctx,
const char *service_name,
- bool first_try)
+ bool first_try,
+ bool retry_same_server)
{
struct tevent_req *req, *subreq;
struct be_resolve_server_state *state;
@@ -529,6 +532,30 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
state->attempts = 0;
state->first_try = first_try;
+ if (retry_same_server &&
+ state->svc->current_resolved_attempts < MAX_RESOLVED_ATTEMPTS) {
+ state->srv = state->svc->current_resolved;
+ state->svc->current_resolved_attempts++;
+ DEBUG(SSSDBG_IMPORTANT_INFO, "Performing retry to %s:%d\n",
+ fo_get_server_str_name(state->srv),
+ fo_get_server_port(state->srv));
+ tevent_req_done(req);
+ tevent_req_post(req, ev);
+ return req;
+ } else if (retry_same_server &&
+ state->svc->current_resolved_attempts >= MAX_RESOLVED_ATTEMPTS) {
+ DEBUG(SSSDBG_IMPORTANT_INFO,
+ "Will not retry %s:%d, maximum number of attempts (%d) reached\n",
+ fo_get_server_str_name(state->svc->current_resolved),
+ fo_get_server_port(state->svc->current_resolved),
+ MAX_RESOLVED_ATTEMPTS);
+ be_fo_set_port_status(state->ctx, state->svc->name,
+ state->svc->current_resolved,
+ PORT_NOT_WORKING);
+ }
+
+ state->svc->current_resolved_attempts = 0;
+
subreq = fo_resolve_service_send(state, ev,
ctx->be_fo->be_res->resolv,
ctx->be_fo->fo_ctx,
@@ -645,6 +672,9 @@ errno_t be_resolve_server_process(struct tevent_req *subreq,
return ENOENT;
}
+ state->svc->current_resolved = state->srv;
+ state->svc->current_resolved_attempts++;
+
if (DEBUG_IS_SET(SSSDBG_FUNC_DATA) && fo_get_server_name(state->srv)) {
struct resolv_hostent *srvaddr;
char ipaddr[128];
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 699c2467b8..95336f68d0 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -688,7 +688,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
state->search_kpasswd = false;
subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
state->krb5_ctx->service->name,
- state->kr->srv == NULL ? true : false);
+ state->kr->srv == NULL ? true : false,
+ false);
if (!subreq) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed resolver request.\n");
ret = EIO;
@@ -759,7 +760,8 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
subreq = be_resolve_server_send(state,
state->ev, state->be_ctx,
state->krb5_ctx->kpasswd_service->name,
- kr->kpasswd_srv == NULL ? true : false);
+ kr->kpasswd_srv == NULL ? true : false,
+ false);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Resolver request failed.\n");
ret = EIO;
@@ -863,7 +865,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
search_srv, PORT_NOT_WORKING);
subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
state->krb5_ctx->service->name,
- search_srv == NULL ? true : false);
+ search_srv == NULL ? true : false,
+ false);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed resolved request.\n");
ret = ENOMEM;
@@ -965,7 +968,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
state->search_kpasswd = true;
subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
state->krb5_ctx->kpasswd_service->name,
- state->kr->kpasswd_srv == NULL ? true : false);
+ state->kr->kpasswd_srv == NULL ? true : false,
+ false);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Resolver request failed.\n");
ret = ENOMEM;
@@ -982,7 +986,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
state->search_kpasswd = false;
subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
state->krb5_ctx->service->name,
- kr->srv == NULL ? true : false);
+ kr->srv == NULL ? true : false,
+ false);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Resolver request failed.\n");
ret = ENOMEM;
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index eead3f119a..5039c4a696 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1172,7 +1172,8 @@ static struct tevent_req *sdap_kinit_next_kdc(struct tevent_req *req)
next_req = be_resolve_server_send(state, state->ev,
state->be,
state->krb_service_name,
- state->kdc_srv == NULL ? true : false);
+ state->kdc_srv == NULL ? true : false,
+ false);
if (next_req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "be_resolve_server_send failed.\n");
return NULL;
@@ -1450,7 +1451,7 @@ struct sdap_cli_connect_state {
bool use_tls;
};
-static int sdap_cli_resolve_next(struct tevent_req *req);
+static int sdap_cli_resolve_next(struct tevent_req *req, bool retry_same_server);
static void sdap_cli_resolve_done(struct tevent_req *subreq);
static void sdap_cli_connect_done(struct tevent_req *subreq);
static void sdap_cli_rootdse_step(struct tevent_req *req);
@@ -1521,7 +1522,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
state->force_tls = force_tls;
state->do_auth = !skip_auth;
- ret = sdap_cli_resolve_next(req);
+ ret = sdap_cli_resolve_next(req, false);
if (ret) {
tevent_req_error(req, ret);
tevent_req_post(req, ev);
@@ -1529,7 +1530,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
return req;
}
-static int sdap_cli_resolve_next(struct tevent_req *req)
+static int sdap_cli_resolve_next(struct tevent_req *req, bool retry_same_server)
{
struct sdap_cli_connect_state *state = tevent_req_data(req,
struct sdap_cli_connect_state);
@@ -1542,7 +1543,8 @@ static int sdap_cli_resolve_next(struct tevent_req *req)
* with a new valid server. Do not use service->uri before */
subreq = be_resolve_server_send(state, state->ev,
state->be, state->service->name,
- state->srv == NULL ? true : false);
+ state->srv == NULL ? true : false,
+ retry_same_server);
if (!subreq) {
return ENOMEM;
}
@@ -1596,15 +1598,23 @@ static void sdap_cli_connect_done(struct tevent_req *subreq)
struct sdap_cli_connect_state);
const char *sasl_mech;
int ret;
+ bool retry_same_server;
talloc_zfree(state->sh);
ret = sdap_connect_recv(subreq, state, &state->sh);
talloc_zfree(subreq);
if (ret) {
- /* 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 == ERR_TLS_HANDSHAKE_INTERRUPTED) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "TLS handshake was interruped, provider may retry\n");
+ retry_same_server = true;
+ } else {
+ retry_same_server = false;
+ /* retry another server */
+ be_fo_set_port_status(state->be, state->service->name,
+ state->srv, PORT_NOT_WORKING);
+ }
+ ret = sdap_cli_resolve_next(req, retry_same_server);
if (ret != EOK) {
tevent_req_error(req, ret);
}
@@ -1678,7 +1688,7 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq)
if (ret == ETIMEDOUT) { /* retry another server */
be_fo_set_port_status(state->be, state->service->name,
state->srv, PORT_NOT_WORKING);
- ret = sdap_cli_resolve_next(req);
+ ret = sdap_cli_resolve_next(req, false);
if (ret != EOK) {
tevent_req_error(req, ret);
}
@@ -2040,7 +2050,7 @@ static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq)
* one */
be_fo_set_port_status(state->be, state->service->name,
state->srv, PORT_NOT_WORKING);
- ret = sdap_cli_resolve_next(req);
+ ret = sdap_cli_resolve_next(req, false);
if (ret != EOK) {
tevent_req_error(req, ret);
}
diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c
index 976d6208ee..3c68b85994 100644
--- a/src/util/sss_ldap.c
+++ b/src/util/sss_ldap.c
@@ -237,6 +237,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);
@@ -279,7 +281,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");
@@ -301,6 +305,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 aec53962b3..4546d8f123 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -750,6 +750,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 b5c7419a94..334fd9d508 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -143,6 +143,8 @@ struct err_string error_to_str[] = {
{ "Error while parsing configuration file" }, /* ERR_INI_PARSE_FAILED */
{ "Failed to add configuration snippets" }, /* ERR_INI_ADD_SNIPPETS_FAILED */
+ { "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 75c46286af..b6b96f3eea 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -164,6 +164,8 @@ enum sssd_errors {
ERR_INI_PARSE_FAILED,
ERR_INI_ADD_SNIPPETS_FAILED,
+ ERR_TLS_HANDSHAKE_INTERRUPTED,
+
ERR_LAST /* ALWAYS LAST */
};
diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c
index 14bf98a9bc..b1534e499c 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);
+}
[Attachment #4 (text/plain)]
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-leave@lists.fedorahosted.org
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic