[SSSD] [PATCH] Add offline callback and fix info file handling

Sumit Bose sbose at redhat.com
Tue May 18 10:47:50 UTC 2010


On Mon, May 17, 2010 at 07:55:47AM -0400, Stephen Gallagher wrote:
> I don't think it makes sense to do it in be_mark_offline. I'd prefer
> that for other servers like LDAP we'd maintain affinity for the server
> we currently know works.
> 
> But I might be convinced. What are everyone else's thoughts?
> 

ok, resetting all the resolver data is not a good idea. Please find
attached a new series of patches which tries to only do what is really
needed:

0001-Revert-Create-kdcinfo-and-kpasswdinfo-file-at-startu.patch
0002-Refactor-data-provider-callbacks.patch
0003-Add-offline-callbacks.patch
0004-Refactor-krb5_finalize.patch

0005-Add-run_callbacks-flag.patch
     This new patch adds a flag and a function to set it to request that
     the callbacks are run the next time the resolver is called.

0006-Add-callback-to-remove-krb5-info-files-when-going-of.patch
     This patch new set the run_callbacks flag only for the KDC and if
     available for the kpasswd service.

0007-Krb5-locator-plugin-returns-KRB5_PLUGIN_NO_HANDLE.patch
0008-Refactor-krb5-SIGTERM-handler-installation.patch
0009-Add-krb5-SIGTERM-handler-to-ipa-auth-provider.patch

0010-Add-offline-callback-to-disconnect-global-SDAP-handl.patch
     This new patch adds an offline callback to the LDAP/IPA id provider
     which set the connected flag of the global SDAP handle to false.
     Otherwise this connection will still be used if the transition to
     the offline state was triggered by SIGUSR1 or an other provider.

bye,
Sumit
-------------- next part --------------
From 45628a73641b66bf95c53ce1bf2d772a4c19a4c3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 11:39:35 +0200
Subject: [PATCH 01/10] Revert "Create kdcinfo and kpasswdinfo file at startup"

This reverts commit 4f5664a2ec401f43c090e6170ed9c78390c35272.
---
 src/providers/ipa/ipa_common.c   |    9 --------
 src/providers/krb5/krb5_common.c |   41 +-------------------------------------
 src/providers/krb5/krb5_common.h |    1 -
 3 files changed, 1 insertions(+), 50 deletions(-)

diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 568b10a..0624b79 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -489,7 +489,6 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     char *realm;
     int ret;
     int i;
-    struct tevent_req *req;
 
     tmp_ctx = talloc_new(memctx);
     if (!tmp_ctx) {
@@ -584,14 +583,6 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
         goto done;
     }
 
-    req = be_resolve_server_send(memctx, ctx->ev, ctx, "IPA");
-    if (req == NULL) {
-        DEBUG(1, ("be_resolve_server_send failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-    tevent_req_set_callback(req, krb5_init_resolve_done, service->krb5_service);
-
     ret = EOK;
 
 done:
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index da7627c..f038557 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -31,8 +31,6 @@
 #include "providers/dp_backend.h"
 #include "providers/krb5/krb5_common.h"
 
-#define DUMMY_ADDRESS "255.255.255.255"
-
 struct dp_option default_krb5_opts[] = {
     { "krb5_kdcip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
@@ -290,6 +288,7 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server)
     return;
 }
 
+
 int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
                       const char *service_name, const char *servers,
                       const char *realm, struct krb5_service **_service)
@@ -304,7 +303,6 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     char *server_spec;
     char *endptr;
     struct servent *servent;
-    struct tevent_req *req;
 
     tmp_ctx = talloc_new(memctx);
     if (!tmp_ctx) {
@@ -427,14 +425,6 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
         goto done;
     }
 
-    req = be_resolve_server_send(memctx, ctx->ev, ctx, service_name);
-    if (req == NULL) {
-        DEBUG(1, ("be_resolve_server_send failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-    tevent_req_set_callback(req, krb5_init_resolve_done, service);
-
     ret = EOK;
 
 done:
@@ -485,32 +475,3 @@ void krb5_finalize(struct tevent_context *ev,
 
     sig_term(signum);
 }
-
-void krb5_init_resolve_done(struct tevent_req *req)
-{
-    struct krb5_service *krb5_service  = tevent_req_callback_data(req,
-                                                           struct krb5_service);
-    int ret;
-    struct fo_server *srv;
-    const char *service_name;
-
-    ret = be_resolve_server_recv(req, &srv);
-    talloc_zfree(req);
-    if (ret) {
-        DEBUG(1, ("be_resolve_server request failed [%d][%s]. "
-                  "Creating dummy info file.\n", ret, strerror(ret)));
-
-        service_name = krb5_service->name;
-        if (strcmp(service_name, "IPA") == 0) {
-            service_name = SSS_KRB5KDC_FO_SRV;
-        }
-        ret = write_krb5info_file(krb5_service->realm, DUMMY_ADDRESS,
-                                  service_name);
-        if (ret != EOK) {
-            DEBUG(2, ("write_krb5info_file failed, "
-                      "authentication might fail.\n"));
-        }
-    }
-
-    return;
-}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index dd7fdf2..87d6168 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -83,5 +83,4 @@ void krb5_finalize(struct tevent_context *ev,
                    int count,
                    void *siginfo,
                    void *private_data);
-void krb5_init_resolve_done(struct tevent_req *req);
 #endif /* __KRB5_COMMON_H__ */
-- 
1.6.6.1

-------------- next part --------------
From 5fa0c57c3868014f0f230d5980a079cc515f6ad8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 10:18:33 +0200
Subject: [PATCH 02/10] Refactor data provider callbacks

---
 src/Makefile.am                         |    1 +
 src/providers/data_provider_be.c        |  137 -----------------------
 src/providers/data_provider_callbacks.c |  182 +++++++++++++++++++++++++++++++
 src/providers/dp_backend.h              |   10 +-
 4 files changed, 188 insertions(+), 142 deletions(-)
 create mode 100644 src/providers/data_provider_callbacks.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 86c497e..c7a10e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -399,6 +399,7 @@ sssd_be_SOURCES = \
     providers/data_provider_be.c \
     providers/data_provider_fo.c \
     providers/data_provider_opts.c \
+    providers/data_provider_callbacks.c \
     $(SSSD_FAILOVER_OBJ) \
     $(SSSD_UTIL_OBJ)
 sssd_be_LDADD = $(SSSD_LIBS) $(CARES_LIBS)
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 9ef436e..9a7f8cf 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -169,143 +169,6 @@ void be_mark_offline(struct be_ctx *ctx)
     ctx->run_online_cb = true;
 }
 
-
-struct be_conn_online_cb {
-    struct be_conn_online_cb *prev;
-    struct be_conn_online_cb *next;
-
-    be_conn_online_callback_t cb;
-    void *pvt;
-
-    struct be_ctx *be;
-};
-
-static int online_cb_destructor(TALLOC_CTX *ptr);
-int be_add_online_cb(TALLOC_CTX *mem_ctx,
-                     struct be_ctx *ctx,
-                     be_conn_online_callback_t cb,
-                     void *pvt,
-                     struct be_conn_online_cb **online_cb)
-{
-    struct be_conn_online_cb *on_cb;
-
-    if (!ctx || !cb) {
-        return EINVAL;
-    }
-
-    on_cb = talloc(mem_ctx, struct be_conn_online_cb);
-    if (!on_cb) {
-        return ENOMEM;
-    }
-
-    on_cb->cb = cb;
-    on_cb->pvt = pvt;
-    on_cb->be = ctx;
-
-    DLIST_ADD(ctx->online_cb_list, on_cb);
-
-    talloc_set_destructor((TALLOC_CTX *)on_cb, online_cb_destructor);
-
-    /* Make sure we run the callback for the first
-     * connection after startup.
-     */
-    ctx->run_online_cb = true;
-
-    if (online_cb) {
-        *online_cb = on_cb;
-    }
-
-    return EOK;
-}
-
-static int online_cb_destructor(TALLOC_CTX *ptr)
-{
-    struct be_conn_online_cb *cb =
-            talloc_get_type(ptr, struct be_conn_online_cb);
-    DLIST_REMOVE(cb->be->online_cb_list, cb);
-    return 0;
-}
-
-
-struct be_online_cb_ctx {
-    struct be_ctx *be;
-    struct be_conn_online_cb *callback;
-};
-
-static void be_run_online_cb_step(struct tevent_context *ev,
-                                  struct tevent_timer *te,
-                                  struct timeval current_time,
-                                  void *pvt);
-void be_run_online_cb(struct be_ctx *be) {
-    struct timeval soon;
-    struct tevent_timer *te;
-    struct be_online_cb_ctx *cb_ctx;
-
-    if (be->run_online_cb && be->online_cb_list) {
-        /* Reset the flag. We only want to run these
-         * callbacks when transitioning to online
-         */
-        be->run_online_cb = false;
-
-        DEBUG(3, ("Going online. Running callbacks.\n"));
-
-        cb_ctx = talloc(be, struct be_online_cb_ctx);
-        if (!cb_ctx) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            return;
-        }
-        cb_ctx->be = be;
-        cb_ctx->callback = be->online_cb_list;
-
-        /* Delay 30ms so we don't block any other events */
-        soon = tevent_timeval_current_ofs(0, 30000);
-        te = tevent_add_timer(be->ev, cb_ctx, soon,
-                              be_run_online_cb_step,
-                              cb_ctx);
-        if (!te) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            talloc_free(cb_ctx);
-        }
-    }
-}
-
-static void be_run_online_cb_step(struct tevent_context *ev,
-                                  struct tevent_timer *te,
-                                  struct timeval current_time,
-                                  void *pvt)
-{
-    struct be_online_cb_ctx *cb_ctx =
-            talloc_get_type(pvt, struct be_online_cb_ctx);
-    struct tevent_timer *tev;
-    struct timeval soon;
-
-    /* Call the callback */
-    cb_ctx->callback->cb(cb_ctx->callback->pvt);
-
-    if (cb_ctx->callback->next) {
-        cb_ctx->callback = cb_ctx->callback->next;
-
-        /* Delay 30ms so we don't block any other events */
-        soon = tevent_timeval_current_ofs(0, 30000);
-        tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
-                               be_run_online_cb_step,
-                               cb_ctx);
-        if (!te) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            goto final;
-        }
-        return;
-    }
-
-final:
-    /* Steal the timer event onto the be_ctx so it doesn't
-     * get freed with the cb_ctx
-     */
-    talloc_steal(cb_ctx->be, te);
-    talloc_free(cb_ctx);
-}
-
-
 static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
 {
     struct be_client *becli;
diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
new file mode 100644
index 0000000..00bc8fd
--- /dev/null
+++ b/src/providers/data_provider_callbacks.c
@@ -0,0 +1,182 @@
+/*
+    SSSD
+
+    Data Provider Process - Callback
+
+    Authors:
+
+        Stephen Gallagher <sgallagh at redhat.com>
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2010 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "providers/dp_backend.h"
+
+struct be_cb {
+    struct be_cb *prev;
+    struct be_cb *next;
+
+    be_callback_t cb;
+    void *pvt;
+
+    struct be_cb *list;
+    struct be_ctx *be;
+};
+
+struct be_cb_ctx {
+    struct be_ctx *be;
+    struct be_cb *callback;
+};
+
+static int cb_destructor(TALLOC_CTX *ptr)
+{
+    struct be_cb *cb = talloc_get_type(ptr, struct be_cb);
+    DLIST_REMOVE(cb->list, cb);
+    return 0;
+}
+
+static int be_add_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
+                     be_callback_t cb, void *pvt, struct be_cb **cb_list,
+                     struct be_cb **return_cb)
+{
+    struct be_cb *new_cb;
+
+    if (!ctx || !cb) {
+        return EINVAL;
+    }
+
+    new_cb = talloc(mem_ctx, struct be_cb);
+    if (!new_cb) {
+        return ENOMEM;
+    }
+
+    new_cb->cb = cb;
+    new_cb->pvt = pvt;
+    new_cb->list = *cb_list;
+    new_cb->be = ctx;
+
+    DLIST_ADD(*cb_list, new_cb);
+
+    talloc_set_destructor((TALLOC_CTX *) new_cb, cb_destructor);
+
+    if (return_cb) {
+        *return_cb = new_cb;
+    }
+
+    return EOK;
+}
+
+static void be_run_cb_step(struct tevent_context *ev, struct tevent_timer *te,
+                           struct timeval current_time, void *pvt)
+{
+    struct be_cb_ctx *cb_ctx = talloc_get_type(pvt, struct be_cb_ctx);
+    struct tevent_timer *tev;
+    struct timeval soon;
+
+    /* Call the callback */
+    cb_ctx->callback->cb(cb_ctx->callback->pvt);
+
+    if (cb_ctx->callback->next) {
+        cb_ctx->callback = cb_ctx->callback->next;
+
+        /* Delay 30ms so we don't block any other events */
+        soon = tevent_timeval_current_ofs(0, 30000);
+        tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
+                               be_run_cb_step,
+                               cb_ctx);
+        if (!te) {
+            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+            goto final;
+        }
+        return;
+    }
+
+final:
+    /* Steal the timer event onto the be_ctx so it doesn't
+     * get freed with the cb_ctx
+     */
+    talloc_steal(cb_ctx->be, te);
+    talloc_free(cb_ctx);
+}
+
+static errno_t be_run_cb(struct be_ctx *be, struct be_cb *cb_list) {
+    struct timeval soon;
+    struct tevent_timer *te;
+    struct be_cb_ctx *cb_ctx;
+
+    cb_ctx = talloc(be, struct be_cb_ctx);
+    if (!cb_ctx) {
+        DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+        return ENOMEM;
+    }
+    cb_ctx->be = be;
+    cb_ctx->callback = cb_list;
+
+    /* Delay 30ms so we don't block any other events */
+    soon = tevent_timeval_current_ofs(0, 30000);
+    te = tevent_add_timer(be->ev, cb_ctx, soon,
+                          be_run_cb_step,
+                          cb_ctx);
+    if (!te) {
+        DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+        talloc_free(cb_ctx);
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
+int be_add_online_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
+                     void *pvt, struct be_cb **online_cb)
+{
+    int ret;
+
+    ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->online_cb_list, online_cb);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_cb failed.\n"));
+        return ret;
+    }
+
+    /* Make sure we run the callback for the first
+     * connection after startup.
+     */
+    ctx->run_online_cb = true;
+
+    return EOK;
+}
+
+void be_run_online_cb(struct be_ctx *be) {
+    int ret;
+
+    if (be->run_online_cb && be->online_cb_list) {
+        /* Reset the flag. We only want to run these
+         * callbacks when transitioning to online
+         */
+        be->run_online_cb = false;
+
+        DEBUG(3, ("Going online. Running callbacks.\n"));
+
+        ret = be_run_cb(be, be->online_cb_list);
+        if (ret != EOK) {
+            DEBUG(1, ("be_run_cb failed.\n"));
+        }
+
+    } else {
+        DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
+    }
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index ec0510e..43d79ba 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -40,7 +40,7 @@ typedef void (*be_shutdown_fn)(void *);
 typedef void (*be_req_fn_t)(struct be_req *);
 typedef void (*be_async_callback_t)(struct be_req *, int, int, const char *);
 
-typedef void (*be_conn_online_callback_t)(void *);
+typedef void (*be_callback_t)(void *);
 
 enum bet_type {
     BET_NULL = 0,
@@ -83,7 +83,7 @@ struct be_client {
 
 struct be_failover_ctx;
 
-struct be_conn_online_cb;
+struct be_cb;
 
 struct be_ctx {
     struct tevent_context *ev;
@@ -97,7 +97,7 @@ struct be_ctx {
     /* Functions to be invoked when the
      * backend goes online
      */
-    struct be_conn_online_cb *online_cb_list;
+    struct be_cb *online_cb_list;
     bool run_online_cb;
 
     struct be_offline_status offstat;
@@ -143,9 +143,9 @@ void be_mark_offline(struct be_ctx *ctx);
 
 int be_add_online_cb(TALLOC_CTX *mem_ctx,
                      struct be_ctx *ctx,
-                     be_conn_online_callback_t cb,
+                     be_callback_t cb,
                      void *pvt,
-                     struct be_conn_online_cb **online_cb);
+                     struct be_cb **online_cb);
 void be_run_online_cb(struct be_ctx *be);
 
 /* from data_provider_fo.c */
-- 
1.6.6.1

-------------- next part --------------
From ad2149eb67dc53e11087da7979aaf8167ca5b94a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 10:57:19 +0200
Subject: [PATCH 03/10] Add offline callbacks

---
 src/providers/data_provider_be.c        |    1 +
 src/providers/data_provider_callbacks.c |   22 ++++++++++++++++++++++
 src/providers/dp_backend.h              |   10 +++++++++-
 3 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 9a7f8cf..4ece1b6 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -167,6 +167,7 @@ void be_mark_offline(struct be_ctx *ctx)
     ctx->offstat.went_offline = time(NULL);
     ctx->offstat.offline = true;
     ctx->run_online_cb = true;
+    be_run_offline_cb(ctx);
 }
 
 static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
index 00bc8fd..5552713 100644
--- a/src/providers/data_provider_callbacks.c
+++ b/src/providers/data_provider_callbacks.c
@@ -180,3 +180,25 @@ void be_run_online_cb(struct be_ctx *be) {
         DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
     }
 }
+
+int be_add_offline_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
+                      void *pvt, struct be_cb **offline_cb)
+{
+    return be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
+}
+
+void be_run_offline_cb(struct be_ctx *be) {
+    int ret;
+
+    if (be->offline_cb_list) {
+        DEBUG(3, ("Going offline. Running callbacks.\n"));
+
+        ret = be_run_cb(be, be->offline_cb_list);
+        if (ret != EOK) {
+            DEBUG(1, ("be_run_cb failed.\n"));
+        }
+
+    } else {
+        DEBUG(9, ("Offline call back list is empty, nothing to do.\n"));
+    }
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 43d79ba..fc5e558 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -95,10 +95,11 @@ struct be_ctx {
     struct be_failover_ctx *be_fo;
 
     /* Functions to be invoked when the
-     * backend goes online
+     * backend goes online or offline
      */
     struct be_cb *online_cb_list;
     bool run_online_cb;
+    struct be_cb *offline_cb_list;
 
     struct be_offline_status offstat;
 
@@ -148,6 +149,13 @@ int be_add_online_cb(TALLOC_CTX *mem_ctx,
                      struct be_cb **online_cb);
 void be_run_online_cb(struct be_ctx *be);
 
+int be_add_offline_cb(TALLOC_CTX *mem_ctx,
+                     struct be_ctx *ctx,
+                     be_callback_t cb,
+                     void *pvt,
+                     struct be_cb **online_cb);
+void be_run_offline_cb(struct be_ctx *be);
+
 /* from data_provider_fo.c */
 typedef void (be_svc_callback_fn_t)(void *, struct fo_server *);
 
-- 
1.6.6.1

-------------- next part --------------
From 7da25d91af8649fcbb16e3aa1fcffec2bb057237 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 11:35:11 +0200
Subject: [PATCH 04/10] Refactor krb5_finalize()

---
 src/providers/krb5/krb5_common.c |   39 ++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index f038557..dfcb502 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -435,22 +435,19 @@ done:
     return ret;
 }
 
-void krb5_finalize(struct tevent_context *ev,
-                   struct tevent_signal *se,
-                   int signum,
-                   int count,
-                   void *siginfo,
-                   void *private_data)
+
+static errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm)
 {
-    char *realm = (char *)private_data;
     int ret;
     errno_t err;
     char *file;
 
-    file = talloc_asprintf(se, KDCINFO_TMPL, realm);
+    file = talloc_asprintf(mem_ctx, KDCINFO_TMPL, realm);
     if(file == NULL) {
-        sig_term(signum);
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        return ENOMEM;
     }
+
     errno = 0;
     ret = unlink(file);
     if (ret == -1) {
@@ -459,10 +456,10 @@ void krb5_finalize(struct tevent_context *ev,
                   err, strerror(err)));
     }
 
-    errno = 0;
-    file = talloc_asprintf(se, KPASSWDINFO_TMPL, realm);
+    file = talloc_asprintf(mem_ctx, KPASSWDINFO_TMPL, realm);
     if(file == NULL) {
-        sig_term(signum);
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        return ENOMEM;
     }
 
     errno = 0;
@@ -473,5 +470,23 @@ void krb5_finalize(struct tevent_context *ev,
                   err, strerror(err)));
     }
 
+    return EOK;
+}
+
+void krb5_finalize(struct tevent_context *ev,
+                   struct tevent_signal *se,
+                   int signum,
+                   int count,
+                   void *siginfo,
+                   void *private_data)
+{
+    char *realm = (char *)private_data;
+    int ret;
+
+    ret = remove_krb5_info_files(se, realm);
+    if (ret != EOK) {
+        DEBUG(1, ("remove_krb5_info_files failed.\n"));
+    }
+
     sig_term(signum);
 }
-- 
1.6.6.1

-------------- next part --------------
From 47165cdd46e9f23280498c03966f4d23896c5d1a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 18 May 2010 11:11:52 +0200
Subject: [PATCH 05/10] Add run_callbacks flag

---
 src/providers/data_provider_fo.c |   25 +++++++++++++++++++++++--
 src/providers/dp_backend.h       |    2 ++
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 14ebbdb..56a072a 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -42,6 +42,7 @@ struct be_svc_data {
     struct fo_service *fo_service;
 
     struct fo_server *last_good_srv;
+    bool run_callbacks;
 
     struct be_svc_callback *callbacks;
 };
@@ -414,9 +415,11 @@ static void be_resolve_server_done(struct tevent_req *subreq)
                   fo_get_server_name(state->srv), ipaddr));
     }
 
-    /* now call all svc callbacks if server changed */
-    if (state->srv != state->svc->last_good_srv) {
+    /* now call all svc callbacks if server changed or if it is explicitly
+     * requested */
+    if (state->srv != state->svc->last_good_srv || state->svc->run_callbacks) {
         state->svc->last_good_srv = state->srv;
+        state->svc->run_callbacks = false;
 
         DLIST_FOR_EACH(callback, state->svc->callbacks) {
             callback->fn(callback->private_data, state->srv);
@@ -440,3 +443,21 @@ int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv)
     return EOK;
 }
 
+int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
+                                        const char *service_name)
+{
+    struct be_svc_data *svc;
+
+    DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
+        if (strcmp(svc->name, service_name) == 0) {
+            break;
+        }
+    }
+    if (NULL == svc) {
+        return ENOENT;
+    }
+
+    svc->run_callbacks = true;
+
+    return EOK;
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index fc5e558..0668859 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -177,4 +177,6 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
                                           const char *service_name);
 int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
 
+int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
+                                        const char *service_name);
 #endif /* __DP_BACKEND_H___ */
-- 
1.6.6.1

-------------- next part --------------
From 8f958f58c913bfcc7903a4381707cb4634175299 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 12:04:36 +0200
Subject: [PATCH 06/10] Add callback to remove krb5 info files when going offline

---
 src/Makefile.am                  |    1 +
 src/providers/ipa/ipa_init.c     |    6 ++
 src/providers/krb5/krb5_auth.h   |   40 ----------------
 src/providers/krb5/krb5_common.c |   97 ++++++++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |   52 ++++++++++++++++++++
 src/providers/krb5/krb5_init.c   |    7 ++-
 6 files changed, 162 insertions(+), 41 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index c7a10e7..cb0685c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -515,6 +515,7 @@ krb5_utils_tests_SOURCES = \
     providers/krb5/krb5_common.c \
     providers/data_provider_fo.c \
     providers/data_provider_opts.c \
+    providers/data_provider_callbacks.c \
     $(SSSD_FAILOVER_OBJ) \
     $(SSSD_UTIL_OBJ)
 krb5_utils_tests_CFLAGS = \
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 0e72b1f..60501ce 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -287,6 +287,12 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = krb5_install_offline_callback(bectx, krb5_auth_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_offline_callback failed.\n"));
+        goto done;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index 61b8071..7a4cb77 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -37,8 +37,6 @@
 
 #define ILLEGAL_PATH_PATTERN "//|/\\./|/\\.\\./"
 
-typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
-
 struct krb5child_req {
     pid_t child_pid;
     int read_from_child_fd;
@@ -61,44 +59,6 @@ struct krb5child_req {
     bool valid_tgt_present;
 };
 
-struct fo_service;
-struct deferred_auth_ctx;
-
-struct krb5_ctx {
-    /* opts taken from kinit */
-    /* in seconds */
-    krb5_deltat starttime;
-    krb5_deltat lifetime;
-    krb5_deltat rlife;
-
-    int forwardable;
-    int proxiable;
-    int addresses;
-
-    int not_forwardable;
-    int not_proxiable;
-    int no_addresses;
-
-    int verbose;
-
-    char* principal_name;
-    char* service_name;
-    char* keytab_name;
-    char* k5_cache_name;
-    char* k4_cache_name;
-
-    action_type action;
-
-    struct dp_option *opts;
-    struct krb5_service *service;
-    struct krb5_service *kpasswd_service;
-    int child_debug_fd;
-
-    pcre *illegal_path_re;
-
-    struct deferred_auth_ctx *deferred_auth_ctx;
-};
-
 void krb5_pam_handler(struct be_req *be_req);
 
 struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index dfcb502..f63f516 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -473,6 +473,46 @@ static errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm)
     return EOK;
 }
 
+void remove_krb5_info_files_callback(void *pvt)
+{
+    int ret;
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
+                                                  struct remove_info_files_ctx);
+
+    ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
+                                              ctx->kdc_service_name);
+    if (ret != EOK) {
+        DEBUG(1, ("be_fo_run_callbacks_at_next_request failed, "
+                  "krb5 info files will not be removed, because "
+                  "it is unclear if they will be recreated properly.\n"));
+        return;
+    }
+    if (ctx->kpasswd_service_name != NULL) {
+        ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
+                                            ctx->kpasswd_service_name);
+        if (ret != EOK) {
+            DEBUG(1, ("be_fo_run_callbacks_at_next_request failed, "
+                      "krb5 info files will not be removed, because "
+                      "it is unclear if they will be recreated properly.\n"));
+            return;
+        }
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(1, ("talloc_new failed, cannot remove krb5 info files.\n"));
+        return;
+    }
+
+    ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
+    if (ret != EOK) {
+        DEBUG(1, ("remove_krb5_info_files failed.\n"));
+    }
+
+    talloc_zfree(tmp_ctx);
+}
+
 void krb5_finalize(struct tevent_context *ev,
                    struct tevent_signal *se,
                    int signum,
@@ -490,3 +530,60 @@ void krb5_finalize(struct tevent_context *ev,
 
     sig_term(signum);
 }
+
+errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
+                                      struct krb5_ctx *krb5_ctx)
+{
+    int ret;
+    struct remove_info_files_ctx *ctx;
+    const char *krb5_realm;
+
+    if (krb5_ctx->service == NULL || krb5_ctx->service->name == NULL) {
+        DEBUG(1, ("Missing KDC service name!\n"));
+        return EINVAL;
+    }
+
+    ctx = talloc_zero(krb5_ctx, struct remove_info_files_ctx);
+    if (ctx == NULL) {
+        DEBUG(1, ("talloc_zfree failed.\n"));
+        return ENOMEM;
+    }
+
+    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
+    if (krb5_realm == NULL) {
+        DEBUG(1, ("Missing krb5_realm option!\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    ctx->realm = talloc_strdup(ctx, krb5_realm);
+    if (ctx->realm == NULL) {
+        DEBUG(1, ("talloc_strdup failed!\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ctx->be_ctx = be_ctx;
+    ctx->kdc_service_name = krb5_ctx->service->name;
+    if (krb5_ctx->kpasswd_service == NULL) {
+        ctx->kpasswd_service_name =NULL;
+    } else {
+        ctx->kpasswd_service_name = krb5_ctx->kpasswd_service->name;
+    }
+
+    ret = be_add_offline_cb(ctx, be_ctx, remove_krb5_info_files_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        talloc_zfree(ctx);
+    }
+
+    return ret;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 87d6168..f9b6195 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -58,12 +58,59 @@ enum krb5_opts {
     KRB5_OPTS
 };
 
+typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+
 struct krb5_service {
     char *name;
     char *address;
     char *realm;
 };
 
+struct fo_service;
+struct deferred_auth_ctx;
+
+struct krb5_ctx {
+    /* opts taken from kinit */
+    /* in seconds */
+    krb5_deltat starttime;
+    krb5_deltat lifetime;
+    krb5_deltat rlife;
+
+    int forwardable;
+    int proxiable;
+    int addresses;
+
+    int not_forwardable;
+    int not_proxiable;
+    int no_addresses;
+
+    int verbose;
+
+    char* principal_name;
+    char* service_name;
+    char* keytab_name;
+    char* k5_cache_name;
+    char* k4_cache_name;
+
+    action_type action;
+
+    struct dp_option *opts;
+    struct krb5_service *service;
+    struct krb5_service *kpasswd_service;
+    int child_debug_fd;
+
+    pcre *illegal_path_re;
+
+    struct deferred_auth_ctx *deferred_auth_ctx;
+};
+
+struct remove_info_files_ctx {
+    char *realm;
+    struct be_ctx *be_ctx;
+    const char *kdc_service_name;
+    const char *kpasswd_service_name;
+};
+
 errno_t check_and_export_options(struct dp_option *opts,
                                  struct sss_domain_info *dom);
 
@@ -77,10 +124,15 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
                       const char *service_name, const char *servers,
                       const char *realm, struct krb5_service **_service);
 
+void remove_krb5_info_files_callback(void *pvt);
+
 void krb5_finalize(struct tevent_context *ev,
                    struct tevent_signal *se,
                    int signum,
                    int count,
                    void *siginfo,
                    void *private_data);
+
+errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
+                                      struct krb5_ctx *krb_ctx);
 #endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 4a02b05..481b088 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -135,7 +135,6 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         goto fail;
     }
 
-
     BlockSignals(false, SIGTERM);
     sig_realm = talloc_strdup(ctx, krb5_realm);
     if (sig_realm == NULL) {
@@ -151,6 +150,12 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     }
     talloc_steal(sige, sig_realm);
 
+    ret = krb5_install_offline_callback(bectx, ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_offline_callback failed.\n"));
+        goto fail;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From 9bc8252972a5fcdf62b91a1b1c7770cc749edbdd Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 12:16:59 +0200
Subject: [PATCH 07/10] Krb5 locator plugin returns KRB5_PLUGIN_NO_HANDLE

To allow a fallback to the setting in krb5.conf the locator plugin
returns KRB5_PLUGIN_NO_HANDLE in nearly all error conditions. Only if the
call back fails the error code of the callback is returned.
---
 src/krb5_plugin/sssd_krb5_locator_plugin.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
index 153145b..dfc9c19 100644
--- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
@@ -223,7 +223,7 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context,
     const char *dummy;
 
     ctx = calloc(1,sizeof(struct sssd_ctx));
-    if (ctx == NULL) return ENOMEM;
+    if (ctx == NULL) return KRB5_PLUGIN_NO_HANDLE;
 
     dummy = getenv(SSSD_KRB5_LOCATOR_DEBUG);
     if (dummy == NULL) {
@@ -280,7 +280,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         ctx->sssd_realm = strdup(realm);
         if (ctx->sssd_realm == NULL) {
             PLUGIN_DEBUG(("strdup failed.\n"));
-            return ENOMEM;
+            return KRB5_PLUGIN_NO_HANDLE;
         }
 
         ret = get_krb5info(realm, ctx, locate_service_kdc);
@@ -326,7 +326,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         case locate_service_krb524:
             return KRB5_PLUGIN_NO_HANDLE;
         default:
-            return EINVAL;
+            return KRB5_PLUGIN_NO_HANDLE;
     }
 
     switch (family) {
@@ -343,7 +343,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         case SOCK_DGRAM:
             break;
         default:
-            return EINVAL;
+            return KRB5_PLUGIN_NO_HANDLE;
     }
 
     if (strcmp(realm, ctx->sssd_realm) != 0)
@@ -353,7 +353,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
     ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port);
     if (ret < 0 || ret >= (PORT_STR_SIZE-1)) {
         PLUGIN_DEBUG(("snprintf failed.\n"));
-        return EFAULT;
+        return KRB5_PLUGIN_NO_HANDLE;
     }
 
     memset(&ai_hints, 0, sizeof(struct addrinfo));
@@ -368,7 +368,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
             PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", errno,
                                                             strerror(errno)));
         }
-        return EFAULT;
+        return KRB5_PLUGIN_NO_HANDLE;
     }
 
     PLUGIN_DEBUG(("addr[%s:%s] family[%d] socktype[%d]\n", addr, port_str,
-- 
1.6.6.1

-------------- next part --------------
From e7ff5201b98d3fc407099f1b71e8a594fc4aff5e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 17 May 2010 13:23:32 +0200
Subject: [PATCH 08/10] Refactor krb5 SIGTERM handler installation

---
 src/providers/krb5/krb5_common.c |   33 +++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |    3 +++
 src/providers/krb5/krb5_init.c   |   17 +++--------------
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index f63f516..c78f0e6 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -587,3 +587,36 @@ done:
 
     return ret;
 }
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx)
+{
+    const char *krb5_realm;
+    char *sig_realm;
+    struct tevent_signal *sige;
+
+    BlockSignals(false, SIGTERM);
+
+    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
+    if (krb5_realm == NULL) {
+        DEBUG(1, ("Missing krb5_realm option!\n"));
+        return EINVAL;
+    }
+
+    sig_realm = talloc_strdup(krb5_ctx, krb5_realm);
+    if (sig_realm == NULL) {
+        DEBUG(1, ("talloc_strdup failed!\n"));
+        return ENOMEM;
+    }
+
+    sige = tevent_add_signal(ev, krb5_ctx, SIGTERM, SA_SIGINFO, krb5_finalize,
+                             sig_realm);
+    if (sige == NULL) {
+        DEBUG(1, ("tevent_add_signal failed.\n"));
+        talloc_free(sig_realm);
+        return ENOMEM;
+    }
+    talloc_steal(sige, sig_realm);
+
+    return EOK;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index f9b6195..342481e 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -135,4 +135,7 @@ void krb5_finalize(struct tevent_context *ev,
 
 errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
                                       struct krb5_ctx *krb_ctx);
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx);
 #endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 481b088..c457dc5 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -48,14 +48,12 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
 {
     struct krb5_ctx *ctx = NULL;
     int ret;
-    struct tevent_signal *sige;
     unsigned v;
     FILE *debug_filep;
     const char *krb5_servers;
     const char *krb5_kpasswd_servers;
     const char *krb5_realm;
     const char *errstr;
-    char *sig_realm;
     int errval;
     int errpos;
 
@@ -135,20 +133,11 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         goto fail;
     }
 
-    BlockSignals(false, SIGTERM);
-    sig_realm = talloc_strdup(ctx, krb5_realm);
-    if (sig_realm == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-    sige = tevent_add_signal(bectx->ev, ctx, SIGTERM, SA_SIGINFO,
-                             krb5_finalize, sig_realm);
-    if (sige == NULL) {
-        DEBUG(1, ("tevent_add_signal failed.\n"));
-        ret = ENOMEM;
+    ret = krb5_install_sigterm_handler(bectx->ev, ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
         goto fail;
     }
-    talloc_steal(sige, sig_realm);
 
     ret = krb5_install_offline_callback(bectx, ctx);
     if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From e7ff5201b98d3fc407099f1b71e8a594fc4aff5e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 17 May 2010 13:23:32 +0200
Subject: [PATCH 08/10] Refactor krb5 SIGTERM handler installation

---
 src/providers/krb5/krb5_common.c |   33 +++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |    3 +++
 src/providers/krb5/krb5_init.c   |   17 +++--------------
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index f63f516..c78f0e6 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -587,3 +587,36 @@ done:
 
     return ret;
 }
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx)
+{
+    const char *krb5_realm;
+    char *sig_realm;
+    struct tevent_signal *sige;
+
+    BlockSignals(false, SIGTERM);
+
+    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
+    if (krb5_realm == NULL) {
+        DEBUG(1, ("Missing krb5_realm option!\n"));
+        return EINVAL;
+    }
+
+    sig_realm = talloc_strdup(krb5_ctx, krb5_realm);
+    if (sig_realm == NULL) {
+        DEBUG(1, ("talloc_strdup failed!\n"));
+        return ENOMEM;
+    }
+
+    sige = tevent_add_signal(ev, krb5_ctx, SIGTERM, SA_SIGINFO, krb5_finalize,
+                             sig_realm);
+    if (sige == NULL) {
+        DEBUG(1, ("tevent_add_signal failed.\n"));
+        talloc_free(sig_realm);
+        return ENOMEM;
+    }
+    talloc_steal(sige, sig_realm);
+
+    return EOK;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index f9b6195..342481e 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -135,4 +135,7 @@ void krb5_finalize(struct tevent_context *ev,
 
 errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
                                       struct krb5_ctx *krb_ctx);
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx);
 #endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 481b088..c457dc5 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -48,14 +48,12 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
 {
     struct krb5_ctx *ctx = NULL;
     int ret;
-    struct tevent_signal *sige;
     unsigned v;
     FILE *debug_filep;
     const char *krb5_servers;
     const char *krb5_kpasswd_servers;
     const char *krb5_realm;
     const char *errstr;
-    char *sig_realm;
     int errval;
     int errpos;
 
@@ -135,20 +133,11 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         goto fail;
     }
 
-    BlockSignals(false, SIGTERM);
-    sig_realm = talloc_strdup(ctx, krb5_realm);
-    if (sig_realm == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-    sige = tevent_add_signal(bectx->ev, ctx, SIGTERM, SA_SIGINFO,
-                             krb5_finalize, sig_realm);
-    if (sige == NULL) {
-        DEBUG(1, ("tevent_add_signal failed.\n"));
-        ret = ENOMEM;
+    ret = krb5_install_sigterm_handler(bectx->ev, ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
         goto fail;
     }
-    talloc_steal(sige, sig_realm);
 
     ret = krb5_install_offline_callback(bectx, ctx);
     if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From 1b419e75d2ca088fc9669ac45cc97d4204b4fc32 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 17 May 2010 10:00:32 +0200
Subject: [PATCH 09/10] Add krb5 SIGTERM handler to ipa auth provider

---
 src/providers/ipa/ipa_init.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 60501ce..59e479e 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -293,6 +293,12 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
+        goto done;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From 78e4441f0f8692bfb7e460de90f65f3f143835c9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 18 May 2010 12:18:13 +0200
Subject: [PATCH 10/10] Add offline callback to disconnect global SDAP handle

---
 src/providers/ipa/ipa_init.c     |    7 +++++++
 src/providers/ldap/ldap_common.c |   10 +++++++++-
 src/providers/ldap/ldap_common.h |    1 +
 src/providers/ldap/ldap_init.c   |    7 +++++++
 4 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 59e479e..f3fa610 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -175,6 +175,13 @@ int sssm_ipa_id_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = be_add_offline_cb(ctx, bectx, sdap_gsh_disconnect_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
     ret = sdap_id_setup_tasks(ctx);
     if (ret != EOK) {
         goto done;
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 697971d..5beb2e6 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -6,7 +6,7 @@
     Authors:
         Simo Sorce <ssorce at redhat.com>
 
-    Copyright (C) 2008-2009 Red Hat
+    Copyright (C) 2008-2010 Red Hat
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -675,3 +675,11 @@ done:
     return ret;
 }
 
+void sdap_gsh_disconnect_callback(void *pvt)
+{
+    struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx);
+
+    if (ctx->gsh) {
+        ctx->gsh->connected = false;
+    }
+}
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 2fec7e2..1ee7378 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -117,4 +117,5 @@ int groups_get_recv(struct tevent_req *req);
 /* setup child logging */
 int setup_child(struct sdap_id_ctx *ctx);
 
+void sdap_gsh_disconnect_callback(void *pvt);
 #endif /* _LDAP_COMMON_H_ */
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 396dbfd..5c6f4b7 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -105,6 +105,13 @@ int sssm_ldap_id_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = be_add_offline_cb(ctx, bectx, sdap_gsh_disconnect_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
     ret = sdap_id_setup_tasks(ctx);
     if (ret != EOK) {
         goto done;
-- 
1.6.6.1



More information about the sssd-devel mailing list