[SSSD] [PATCH] Only detect cycle in the fail over on subsequent resolve requests

Jakub Hrozek jhrozek at redhat.com
Wed Mar 7 17:28:08 UTC 2012


On Wed, Mar 07, 2012 at 05:48:45PM +0100, Jakub Hrozek wrote:
> The yesterday's fail over patch broke the IPA provider.. The IPA provider
> is a special case because it uses fail over port 0 for both LDAP and
> Kerberos. That is done to make sure that we never connect to LDAP port on
> one host and Kerberos port on a different host.
> 
> However, the cycle detection in fail over tripped over this because when
> performing a GSSAPI bind, we first request a server with port 0 to get
> the LDAP server and before we can mark the server status (or go
> offline), we also need to resolve the KDC, which, from fail over point
> of view is also running on port 0...
> 
> The attached patch adds a boolean parameter to be_resolve_server_send()
> and only performs the cycle check if the parameter is false, that is,
> when requesting another server during the same operation.

Jan spotted I was assigning the same callback for a kpasswd resolve
request twice. New patch is attached.

-------------- next part --------------
From 6916c2fe2273823e4f74cc93b5a67a0c2fbb108b Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 7 Mar 2012 17:08:52 +0100
Subject: [PATCH] Detect cycle in the fail over on subsequent resolve requests
 only

---
 src/providers/data_provider_fo.c           |    7 ++++-
 src/providers/dp_backend.h                 |    3 +-
 src/providers/krb5/krb5_auth.c             |   32 +++++++++++++--------------
 src/providers/ldap/ldap_auth.c             |    3 +-
 src/providers/ldap/sdap_async_connection.c |    6 +++-
 5 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index c358e68d12bce0c518d58aaa17b3b3cdb706d180..51d6ae211efc2e4cfb6078e3b558a3623e8c25b1 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -342,6 +342,7 @@ struct be_resolve_server_state {
     int attempts;
 
     struct fo_server *srv;
+    bool first_try;
 };
 
 static void be_resolve_server_done(struct tevent_req *subreq);
@@ -349,7 +350,8 @@ static void be_resolve_server_done(struct tevent_req *subreq);
 struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
                                           struct tevent_context *ev,
                                           struct be_ctx *ctx,
-                                          const char *service_name)
+                                          const char *service_name,
+                                          bool first_try)
 {
     struct tevent_req *req, *subreq;
     struct be_resolve_server_state *state;
@@ -370,6 +372,7 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
 
     state->svc = svc;
     state->attempts = 0;
+    state->first_try = first_try;
 
     subreq = fo_resolve_service_send(state, ev,
                                      ctx->be_fo->resolv,
@@ -443,7 +446,7 @@ static void be_resolve_server_done(struct tevent_req *subreq)
     }
 
     /* all fine we got the server */
-    if (state->svc->first_resolved == NULL) {
+    if (state->svc->first_resolved == NULL || state->first_try == true) {
         DEBUG(SSSDBG_TRACE_LIBS, ("Saving the first resolved server\n"));
         state->svc->first_resolved = state->srv;
     } else if (state->svc->first_resolved == state->srv) {
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 96c774783e6590f86cb4a35fe4d920e792d379ce..6e98e7ef3c9370f0cbf93a8f344641b2642bd9a8 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -207,7 +207,8 @@ int be_fo_add_server(struct be_ctx *ctx, const char *service_name,
 struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
                                           struct tevent_context *ev,
                                           struct be_ctx *ctx,
-                                          const char *service_name);
+                                          const char *service_name,
+                                          bool first_try);
 int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
 
 void be_fo_set_port_status(struct be_ctx *ctx,
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 72992ba752c8d7a0202f4475b4bc0bd3af8f369d..0306426ccac564f77d6f592fee1fe32462ad48dc 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -320,6 +320,9 @@ int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err)
     return EOK;
 }
 
+static struct tevent_req *krb5_next_kdc(struct tevent_req *req);
+static struct tevent_req *krb5_next_kpasswd(struct tevent_req *req);
+
 struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
                                   struct tevent_context *ev,
                                   struct be_ctx *be_ctx,
@@ -507,16 +510,14 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
 
     kr->srv = NULL;
     kr->kpasswd_srv = NULL;
-    subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
-                                    krb5_ctx->service->name);
-    if (subreq == NULL) {
-        DEBUG(1, ("be_resolve_server_send failed.\n"));
-        ret = ENOMEM;
+
+    subreq = krb5_next_kdc(req);
+    if (!subreq) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_next_kdc failed.\n"));
+        ret = EIO;
         goto done;
     }
 
-    tevent_req_set_callback(subreq, krb5_resolve_kdc_done, req);
-
     return req;
 
 done:
@@ -557,16 +558,12 @@ static void krb5_resolve_kdc_done(struct tevent_req *subreq)
         }
     } else {
         if (kr->krb5_ctx->kpasswd_service != NULL) {
-            subreq = be_resolve_server_send(state, state->ev, state->be_ctx,
-                                            kr->krb5_ctx->kpasswd_service->name);
+            subreq = krb5_next_kpasswd(req);
             if (subreq == NULL) {
-                DEBUG(1, ("be_resolve_server_send failed.\n"));
-                ret = ENOMEM;
+                DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_next_kpasswd failed.\n"));
+                ret = EIO;
                 goto failed;
             }
-
-            tevent_req_set_callback(subreq, krb5_resolve_kpasswd_done, req);
-
             return;
         }
     }
@@ -718,7 +715,6 @@ done:
 }
 
 static struct tevent_req *krb5_next_server(struct tevent_req *req);
-static struct tevent_req *krb5_next_kdc(struct tevent_req *req);
 static struct tevent_req *krb5_next_kpasswd(struct tevent_req *req);
 
 static void krb5_child_done(struct tevent_req *subreq)
@@ -1004,7 +1000,8 @@ static struct tevent_req *krb5_next_kdc(struct tevent_req *req)
 
     next_req = be_resolve_server_send(state, state->ev,
                                       state->be_ctx,
-                                      state->krb5_ctx->service->name);
+                                      state->krb5_ctx->service->name,
+                                      state->kr->srv == NULL ? true : false);
     if (next_req == NULL) {
         DEBUG(1, ("be_resolve_server_send failed.\n"));
         return NULL;
@@ -1021,7 +1018,8 @@ static struct tevent_req *krb5_next_kpasswd(struct tevent_req *req)
 
     next_req = be_resolve_server_send(state, state->ev,
                                 state->be_ctx,
-                                state->krb5_ctx->kpasswd_service->name);
+                                state->krb5_ctx->kpasswd_service->name,
+                                state->kr->kpasswd_srv == NULL ? true : false);
     if (next_req == NULL) {
         DEBUG(1, ("be_resolve_server_send failed.\n"));
         return NULL;
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 8b6173e145239a2e604aaa9aea43a632ae8582d9..734249ced33e3b70dcfd452f674a9e3dd5b736da 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -517,7 +517,8 @@ static struct tevent_req *auth_get_server(struct tevent_req *req)
     next_req = be_resolve_server_send(state,
                                       state->ev,
                                       state->ctx->be,
-                                      state->sdap_service->name);
+                                      state->sdap_service->name,
+                                      state->srv == NULL ? true : false);
     if (!next_req) {
         DEBUG(1, ("be_resolve_server_send failed.\n"));
         return NULL;
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 22aa4f91ebb4020efc8b4ac5df210f443010e744..2b7f8c93df55e167ae2f4fb330a47dd600c2974e 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -884,7 +884,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->krb_service_name,
+                                      state->kdc_srv == NULL ? true : false);
     if (next_req == NULL) {
         DEBUG(1, ("be_resolve_server_send failed.\n"));
         return NULL;
@@ -1215,7 +1216,8 @@ static int sdap_cli_resolve_next(struct tevent_req *req)
     /* NOTE: this call may cause service->uri to be refreshed
      * 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->be, state->service->name,
+                                    state->srv == NULL ? true : false);
     if (!subreq) {
         return ENOMEM;
     }
-- 
1.7.7.6



More information about the sssd-devel mailing list