diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2012-09-12 19:23:48 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2012-10-03 13:44:13 +0200 |
commit | 052684f1ab1c8a4fcfb2c9057c33273acbaf660e (patch) | |
tree | 9cbb6c5004e16f90188b5495204b2ce0773453ab /src/providers/ldap | |
parent | b196e1e91ec04ca5af93bfd2dcfc5225f4858a54 (diff) | |
download | sssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.tar.gz sssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.tar.xz sssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.zip |
FO: Check server validity before setting statussssd-1_8_5
The list of resolved servers is allocated on the back end context and
kept in the fo_service structure. However, a single request often
resolves a server and keeps a pointer until the end of a request and
only then gives feedback about the server based on the request result.
This presents a big race condition in case the SRV resolution is used.
When there are requests coming in in parallel, it is possible that an
incoming request will invalidate a server until another request that
holds a pointer to the original server is able to give a feedback.
This patch simply checks if a server is in the list of servers
maintained by a service before reading its status.
https://fedorahosted.org/sssd/ticket/1364
Diffstat (limited to 'src/providers/ldap')
-rw-r--r-- | src/providers/ldap/ldap_auth.c | 4 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_connection.c | 21 |
2 files changed, 17 insertions, 8 deletions
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index 734249ced..08502c147 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -590,6 +590,7 @@ static void auth_connect_done(struct tevent_req *subreq) if (state->srv) { /* mark this server as bad if connection failed */ be_fo_set_port_status(state->ctx->be, + state->sdap_service->name, state->srv, PORT_NOT_WORKING); } if (ret == ETIMEDOUT) { @@ -602,7 +603,8 @@ static void auth_connect_done(struct tevent_req *subreq) tevent_req_error(req, ret); return; } else if (state->srv) { - be_fo_set_port_status(state->ctx->be, state->srv, PORT_WORKING); + be_fo_set_port_status(state->ctx->be, state->sdap_service->name, + state->srv, PORT_WORKING); } ret = get_user_dn(state, state->ctx->be->sysdb, state->ctx->opts, diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index 9713fbe37..d8f5b1437 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -947,7 +947,8 @@ static void sdap_kinit_done(struct tevent_req *subreq) * retry with another KDC */ DEBUG(SSSDBG_MINOR_FAILURE, ("Communication with KDC timed out, trying the next one\n")); - be_fo_set_port_status(state->be, state->kdc_srv, PORT_NOT_WORKING); + be_fo_set_port_status(state->be, state->krb_service_name, + state->kdc_srv, PORT_NOT_WORKING); nextreq = sdap_kinit_next_kdc(req); if (!nextreq) { tevent_req_error(req, ENOMEM); @@ -975,7 +976,8 @@ static void sdap_kinit_done(struct tevent_req *subreq) return; } else { if (kerr == KRB5_KDC_UNREACH) { - be_fo_set_port_status(state->be, state->kdc_srv, PORT_NOT_WORKING); + be_fo_set_port_status(state->be, state->krb_service_name, + state->kdc_srv, PORT_NOT_WORKING); nextreq = sdap_kinit_next_kdc(req); if (!nextreq) { tevent_req_error(req, ENOMEM); @@ -1306,7 +1308,8 @@ static void sdap_cli_connect_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret) { /* retry another server */ - be_fo_set_port_status(state->be, state->srv, PORT_NOT_WORKING); + 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); @@ -1379,7 +1382,8 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret) { if (ret == ETIMEDOUT) { /* retry another server */ - be_fo_set_port_status(state->be, state->srv, PORT_NOT_WORKING); + 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); @@ -1612,7 +1616,8 @@ static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq) if (ret == ETIMEDOUT) { /* The server we authenticated against went down. Retry another * one */ - be_fo_set_port_status(state->be, state->srv, PORT_NOT_WORKING); + 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); @@ -1660,7 +1665,8 @@ int sdap_cli_connect_recv(struct tevent_req *req, if (tevent_req_is_error(req, &tstate, &err)) { /* mark the server as bad if connection failed */ if (state->srv) { - be_fo_set_port_status(state->be, state->srv, PORT_NOT_WORKING); + be_fo_set_port_status(state->be, state->service->name, + state->srv, PORT_NOT_WORKING); } else { if (can_retry) { *can_retry = false; @@ -1672,7 +1678,8 @@ int sdap_cli_connect_recv(struct tevent_req *req, } return EIO; } else if (state->srv) { - be_fo_set_port_status(state->be, state->srv, PORT_WORKING); + be_fo_set_port_status(state->be, state->service->name, + state->srv, PORT_WORKING); } if (gsh) { |