summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-09-12 19:23:48 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-09-13 16:51:38 +0200
commitd25e7c659361ebd794ef011dc9305543f266e8c4 (patch)
tree7203927b13d500ce1b41c12db712625bfe6f5f15 /src/providers/ldap
parent3c79852d5d5ba4111c0535bafea43450dba8ed12 (diff)
downloadsssd-d25e7c659361ebd794ef011dc9305543f266e8c4.tar.gz
sssd-d25e7c659361ebd794ef011dc9305543f266e8c4.tar.xz
sssd-d25e7c659361ebd794ef011dc9305543f266e8c4.zip
FO: Check server validity before setting status
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.c4
-rw-r--r--src/providers/ldap/sdap_async_connection.c21
2 files changed, 17 insertions, 8 deletions
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index cc5eff1b2..32a2e04ea 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -605,6 +605,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) {
@@ -617,7 +618,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 9fee1a5d4..79ad3b8e4 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1012,7 +1012,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);
@@ -1040,7 +1041,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);
@@ -1371,7 +1373,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);
@@ -1444,7 +1447,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);
@@ -1681,7 +1685,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);
@@ -1729,7 +1734,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;
@@ -1741,7 +1747,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) {