[SSSD] [PATCH] Check ccache file for renewable TGTs at startup

Sumit Bose sbose at redhat.com
Tue Feb 22 10:41:08 UTC 2011


On Fri, Feb 18, 2011 at 11:29:28AM -0500, Stephen Gallagher wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 02/16/2011 12:12 PM, Sumit Bose wrote:
> > Hi,
> > 
> > with this patch the credential cache files stored in the cache are
> > checked if they contain TGTs which are still renewable.
> > 
> > Should fix #796.
> 
> Nack.
> 
>         if (ccache_file != NULL && upn != NULL && user_name != NULL) {
> 
> The checks for upn and user_name are redundant, as there's no way to
> reach this line without them being non-NULL. A few lines above, you call
> 'continue' to return to the loop if either of these values are NULL.
> 
> Please reduce the debug level of:
> "One of the needed attributes [%s][%s][%s] is missing in [%s]."
> to level six. I think level 9 is too noisy and this is useful information.

I have move the checks and the debug message into check_ccache_file() so
that it can be used safely in other places, too.

> 
> In get_ccache_file_data(), you set kerr = ENOMEM if server_name can't be
> allocated. kerr is a krb5_error_code value, not errno_t. It's probably
> best if you use KRB5_CC_NOMEM here.

done

New patch attached.

bye,
Sumit

> 
> - -- 
> Stephen Gallagher
> RHCE 804006346421761
> 
> Delivering value year after year.
> Red Hat ranks #1 in value among software vendors.
> http://www.redhat.com/promo/vendor/
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (GNU/Linux)
> Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
> 
> iEYEARECAAYFAk1enmcACgkQeiVVYja6o6MAYQCgqllBY5avcJxHyAhTBsMECEx4
> vscAnAxQtWdGfqNxjYDLFpHZSZm+BMt0
> =ATRj
> -----END PGP SIGNATURE-----
> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://fedorahosted.org/mailman/listinfo/sssd-devel
-------------- next part --------------
From e9ff6c447065fa697598a7f6c28d933fad0e2e85 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 16 Feb 2011 14:20:02 +0100
Subject: [PATCH] Check ccache file for renewable TGTs at startup

---
 src/providers/krb5/krb5_renew_tgt.c |  138 +++++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_utils.c     |  100 +++++++++++++++++++++++++
 src/providers/krb5/krb5_utils.h     |    3 +
 3 files changed, 241 insertions(+), 0 deletions(-)

diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
index 915def8..cf50666 100644
--- a/src/providers/krb5/krb5_renew_tgt.c
+++ b/src/providers/krb5/krb5_renew_tgt.c
@@ -26,6 +26,7 @@
 #include "util/util.h"
 #include "providers/krb5/krb5_common.h"
 #include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_utils.h"
 
 #define INITIAL_TGT_TABLE_SIZE 10
 
@@ -299,6 +300,139 @@ static void renew_del_cb(hash_entry_t *entry, hash_destroy_enum type, void *pvt)
     DEBUG(1, ("Unexpected value type [%d].\n", entry->value.type));
 }
 
+static errno_t check_ccache_file(struct renew_tgt_ctx *renew_tgt_ctx,
+                                 const char *ccache_file, const char *upn,
+                                 const char *user_name)
+{
+    int ret;
+    struct stat stat_buf;
+    struct tgt_times tgtt;
+    struct pam_data pd;
+    time_t now;
+    const char *filename;
+
+    if (ccache_file == NULL || upn == NULL || user_name == NULL) {
+        DEBUG(6, ("Missing one of the needed attributes: [%s][%s][%s].\n",
+                  ccache_file == NULL ? "cache file missing" : ccache_file,
+                  upn == NULL ? "principal missing" : upn,
+                  user_name == NULL ? "user name missing" : user_name));
+        return EINVAL;
+    }
+
+    if (strncmp(ccache_file, "FILE:", 5) == 0) {
+        filename = ccache_file + 5;
+    } else {
+        filename = ccache_file;
+    }
+
+    ret = stat(filename, &stat_buf);
+    if (ret != EOK) {
+        if (ret == ENOENT) {
+            return EOK;
+        }
+        return ret;
+    }
+
+    DEBUG(9, ("Found ccache file [%s].\n", ccache_file));
+
+    memset(&tgtt, 0, sizeof(tgtt));
+    ret = get_ccache_file_data(ccache_file, upn, &tgtt);
+    if (ret != EOK) {
+        DEBUG(1, ("get_ccache_file_data failed.\n"));
+        return ret;
+    }
+
+    memset(&pd, 0, sizeof(pd));
+    pd.cmd = SSS_CMD_RENEW;
+    pd.user = discard_const_p(char, user_name);
+    now = time(NULL);
+    if (tgtt.renew_till > tgtt.endtime && tgtt.renew_till > now &&
+        tgtt.endtime > now) {
+        DEBUG(7, ("Adding [%s] for automatic renewal.\n", ccache_file));
+        ret = add_tgt_to_renew_table(renew_tgt_ctx->krb5_ctx, ccache_file,
+                                     &tgtt, &pd, upn);
+        if (ret != EOK) {
+            DEBUG(1, ("add_tgt_to_renew_table failed, "
+                      "automatic renewal not possible.\n"));
+        }
+    } else {
+        DEBUG(9, ("TGT in [%s] for [%s] is too old.\n", ccache_file, upn));
+    }
+
+    return EOK;
+}
+
+static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx)
+{
+    TALLOC_CTX *tmp_ctx;
+    int ret;
+    const char *ccache_filter = "("SYSDB_CCACHE_FILE"=*)";
+    const char *ccache_attrs[] = { SYSDB_CCACHE_FILE, SYSDB_UPN, SYSDB_NAME,
+                                   NULL };
+    size_t msgs_count = 0;
+    struct ldb_message **msgs = NULL;
+    size_t c;
+    const char *ccache_file;
+    const char *upn;
+    const char *user_name;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(1, ("talloc_new failed.\n"));
+        return ENOMEM;
+    }
+
+    ret = sysdb_search_users(tmp_ctx, renew_tgt_ctx->be_ctx->sysdb,
+                             renew_tgt_ctx->be_ctx->domain, ccache_filter,
+                             ccache_attrs, &msgs_count, &msgs);
+    if (ret != EOK) {
+        DEBUG(1, ("sysdb_search_users failed.\n"));
+        goto done;
+    }
+
+    if (msgs_count == 0) {
+        DEBUG(9, ("No entries with ccache file found in cache.\n"));
+        ret = EOK;
+        goto done;
+    }
+    DEBUG(9, ("Found [%d] entries with ccache file in cache.\n", msgs_count));
+
+    for (c = 0; c < msgs_count; c++) {
+        user_name = ldb_msg_find_attr_as_string(msgs[c], SYSDB_NAME, NULL);
+        if (user_name == NULL) {
+            DEBUG(1, ("No user name found, this is a severe error, "
+                      "but we ignore it here.\n"));
+            continue;
+        }
+
+        upn = ldb_msg_find_attr_as_string(msgs[c], SYSDB_UPN, NULL);
+        if (upn == NULL) {
+            ret = krb5_get_simple_upn(tmp_ctx, renew_tgt_ctx->krb5_ctx,
+                                      user_name, &upn);
+            if (ret != EOK) {
+                DEBUG(1, ("krb5_get_simple_upn failed.\n"));
+                continue;
+            }
+            DEBUG(9, ("No upn stored in cache, using [%s].\n", upn));
+        }
+
+        ccache_file = ldb_msg_find_attr_as_string(msgs[c], SYSDB_CCACHE_FILE,
+                                                  NULL);
+
+        ret = check_ccache_file(renew_tgt_ctx, ccache_file, upn, user_name);
+        if (ret != EOK) {
+            DEBUG(5, ("Failed to check ccache file [%s].\n", ccache_file));
+        }
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 errno_t init_renew_tgt(struct krb5_ctx *krb5_ctx, struct be_ctx *be_ctx,
                        struct tevent_context *ev, time_t renew_intv)
 {
@@ -325,6 +459,10 @@ errno_t init_renew_tgt(struct krb5_ctx *krb5_ctx, struct be_ctx *be_ctx,
     krb5_ctx->renew_tgt_ctx->timer_interval = renew_intv;
     krb5_ctx->renew_tgt_ctx->added_to_online_callbacks = false;
 
+    ret = check_ccache_files(krb5_ctx->renew_tgt_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to read ccache files, continuing ...\n"));
+    }
 
     next = tevent_timeval_current_ofs(krb5_ctx->renew_tgt_ctx->timer_interval,
                                       0);
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index d3aa437..adb4822 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -396,3 +396,103 @@ done:
     talloc_free(tmp_ctx);
     return ret;
 }
+
+errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                             struct tgt_times *tgtt)
+{
+    krb5_error_code kerr;
+    krb5_context ctx = NULL;
+    krb5_ccache cc = NULL;
+    krb5_principal client_princ = NULL;
+    krb5_principal server_princ = NULL;
+    char *server_name;
+    krb5_creds mcred;
+    krb5_creds cred;
+
+    kerr = krb5_init_context(&ctx);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_init_context failed.\n"));
+        goto done;
+    }
+
+    kerr = krb5_parse_name(ctx, client_name, &client_princ);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_parse_name failed.\n"));
+        goto done;
+    }
+
+    server_name = talloc_asprintf(NULL, "krbtgt/%.*s@%.*s",
+                                  krb5_princ_realm(ctx, client_princ)->length,
+                                  krb5_princ_realm(ctx, client_princ)->data,
+                                  krb5_princ_realm(ctx, client_princ)->length,
+                                  krb5_princ_realm(ctx, client_princ)->data);
+    if (server_name == NULL) {
+        kerr = KRB5_CC_NOMEM;
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        goto done;
+    }
+
+    kerr = krb5_parse_name(ctx, server_name, &server_princ);
+    talloc_free(server_name);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_parse_name failed.\n"));
+        goto done;
+    }
+
+    kerr = krb5_cc_resolve(ctx, ccache_file, &cc);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_cc_resolve failed.\n"));
+        goto done;
+    }
+
+    memset(&mcred, 0, sizeof(mcred));
+    memset(&cred, 0, sizeof(mcred));
+
+    mcred.server = server_princ;
+    mcred.client = client_princ;
+
+    kerr = krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &cred);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
+        goto done;
+    }
+
+    tgtt->authtime = cred.times.authtime;
+    tgtt->starttime = cred.times.starttime;
+    tgtt->endtime = cred.times.endtime;
+    tgtt->renew_till = cred.times.renew_till;
+
+    krb5_free_cred_contents(ctx, &cred);
+
+    kerr = krb5_cc_close(ctx, cc);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_cc_close failed.\n"));
+        goto done;
+    }
+    cc = NULL;
+
+    kerr = 0;
+
+done:
+    if (cc != NULL) {
+        krb5_cc_close(ctx, cc);
+    }
+
+    if (client_princ != NULL) {
+        krb5_free_principal(ctx, client_princ);
+    }
+
+    if (server_princ != NULL) {
+        krb5_free_principal(ctx, server_princ);
+    }
+
+    if (ctx != NULL) {
+        krb5_free_context(ctx);
+    }
+
+    if (kerr != 0) {
+        return EIO;
+    }
+
+    return EOK;
+}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index be162bc..8977e14 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -40,4 +40,7 @@ errno_t become_user(uid_t uid, gid_t gid);
 errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
                           pcre *illegal_re, uid_t uid, gid_t gid,
                           bool private_path);
+
+errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                             struct tgt_times *tgtt);
 #endif /* __KRB5_UTILS_H__ */
-- 
1.7.4



More information about the sssd-devel mailing list