Backport simplification of ccache management from 1.11.1

- Resolves: rhbz#1010553 - sssd setting KRB5CCNAME=(null) on login
This commit is contained in:
Jakub Hrozek 2013-09-23 12:23:42 +02:00
parent c5481c88cf
commit 8d72fcd900
15 changed files with 3686 additions and 1 deletions

View File

@ -0,0 +1,168 @@
From 0371fbcf60d4dd8e25b9bb0a83029c812b66f3d6 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Wed, 28 Aug 2013 21:19:32 -0400
Subject: [PATCH 01/14] krb5: Add calls to change and restore credentials
In some cases we want to temporarily assume user credentials but allow the
process to regain back the original credentials (normally regaining uid 0).
Related:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_become_user.c | 125 ++++++++++++++++++++++++++++++++++
src/providers/krb5/krb5_utils.h | 6 ++
2 files changed, 131 insertions(+)
diff --git a/src/providers/krb5/krb5_become_user.c b/src/providers/krb5/krb5_become_user.c
index 70bc5630ece21505b58bd1a8795d7ab4b7864460..567cf237569f70a6b0fd500327438f2dbb08d24d 100644
--- a/src/providers/krb5/krb5_become_user.c
+++ b/src/providers/krb5/krb5_become_user.c
@@ -70,3 +70,128 @@ errno_t become_user(uid_t uid, gid_t gid)
return EOK;
}
+struct sss_creds {
+ uid_t uid;
+ gid_t gid;
+ int num_gids;
+ gid_t gids[];
+};
+
+errno_t restore_creds(struct sss_creds *saved_creds);
+
+/* This is a reversible version of become_user, and returns the saved
+ * credentials so that creds can be switched back calling restore_creds */
+errno_t switch_creds(TALLOC_CTX *mem_ctx,
+ uid_t uid, gid_t gid,
+ int num_gids, gid_t *gids,
+ struct sss_creds **saved_creds)
+{
+ struct sss_creds *ssc = NULL;
+ int size;
+ int ret;
+
+ DEBUG(SSSDBG_FUNC_DATA, ("Switch user to [%d][%d].\n", uid, gid));
+
+ if (saved_creds) {
+ /* save current user credentials */
+ size = getgroups(0, NULL);
+ if (size == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Getgroups failed! (%d, %s)\n",
+ ret, strerror(ret)));
+ goto done;
+ }
+
+ ssc = talloc_size(mem_ctx,
+ (sizeof(struct sss_creds) + size * sizeof(gid_t)));
+ if (!ssc) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation failed!\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ ssc->num_gids = size;
+
+ size = getgroups(ssc->num_gids, ssc->gids);
+ if (size == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Getgroups failed! (%d, %s)\n",
+ ret, strerror(ret)));
+ /* free ssc immediately otherwise the code will try to restore
+ * wrong creds */
+ talloc_zfree(ssc);
+ goto done;
+ }
+
+ /* we care only about effective ids */
+ ssc->uid = geteuid();
+ ssc->gid = getegid();
+ }
+
+ /* if we are regaining root set euid first so that we have CAP_SETUID back,
+ * ane the other calls work too, otherwise call it last so that we can
+ * change groups before we loose CAP_SETUID */
+ if (uid == 0) {
+ ret = setresuid(0, 0, 0);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("setresuid failed [%d][%s].\n", ret, strerror(ret)));
+ goto done;
+ }
+ }
+
+ /* TODO: use prctl to get/set capabilities too ? */
+
+ /* try to setgroups first should always work if CAP_SETUID is set,
+ * otherwise it will always fail, failure is not critical though as
+ * generally we only really care about uid and at mot primary gid */
+ ret = setgroups(num_gids, gids);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("setgroups failed [%d][%s].\n", ret, strerror(ret)));
+ }
+
+ /* change gid now, (leaves saved gid to current, so we can restore) */
+ ret = setresgid(-1, gid, -1);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("setresgid failed [%d][%s].\n", ret, strerror(ret)));
+ goto done;
+ }
+
+ if (uid != 0) {
+ /* change uid, (leaves saved uid to current, so we can restore) */
+ ret = setresuid(-1, uid, -1);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("setresuid failed [%d][%s].\n", ret, strerror(ret)));
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (ret) {
+ if (ssc) {
+ /* attempt to restore creds first */
+ restore_creds(ssc);
+ talloc_free(ssc);
+ }
+ } else if (saved_creds) {
+ *saved_creds = ssc;
+ }
+ return ret;
+}
+
+errno_t restore_creds(struct sss_creds *saved_creds)
+{
+ return switch_creds(saved_creds,
+ saved_creds->uid,
+ saved_creds->gid,
+ saved_creds->num_gids,
+ saved_creds->gids, NULL);
+}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index cdc9f23641905cff300077f708087e98ba683e0d..aac3ec72ec7e1664ae96cc4e53d368e22448f5f1 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -80,6 +80,12 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
bool case_sensitive, bool *private_path);
errno_t become_user(uid_t uid, gid_t gid);
+struct sss_creds;
+errno_t switch_creds(TALLOC_CTX *mem_ctx,
+ uid_t uid, gid_t gid,
+ int num_gids, gid_t *gids,
+ struct sss_creds **saved_creds);
+errno_t restore_creds(struct sss_creds *saved_creds);
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
--
1.8.3.1

View File

@ -0,0 +1,154 @@
From 04c49a183f49c28f9ef900bdbc4eb30f23278e17 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Wed, 28 Aug 2013 22:12:07 -0400
Subject: [PATCH 02/14] krb5: Add helper to destroy ccache as user
This function safely destroy a ccache given a cache name and user crdentials.
It becomes the user so no possible races can compromise the system, then
uses libkrb5 functions to properly destroy a ccache, independently of the
cache type.
Finally restores the original credentials after closing the ccache handlers.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_utils.c | 109 ++++++++++++++++++++++++++++++++++++++++
src/providers/krb5/krb5_utils.h | 2 +
2 files changed, 111 insertions(+)
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 6bf1cf610dd20afc7a600e9505c4bae2ff675fcc..1141f3fc839a78927dab5f50267c52d5b44b46ba 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -818,6 +818,115 @@ done:
}
+struct sss_krb5_ccache {
+ struct sss_creds *creds;
+ krb5_context context;
+ krb5_ccache ccache;
+};
+
+static int sss_free_krb5_ccache(void *mem)
+{
+ struct sss_krb5_ccache *cc = talloc_get_type(mem, struct sss_krb5_ccache);
+
+ if (cc->ccache) {
+ krb5_cc_close(cc->context, cc->ccache);
+ }
+ krb5_free_context(cc->context);
+ restore_creds(cc->creds);
+ return 0;
+}
+
+static errno_t sss_open_ccache_as_user(TALLOC_CTX *mem_ctx,
+ const char *ccname,
+ uid_t uid, gid_t gid,
+ struct sss_krb5_ccache **ccache)
+{
+ struct sss_krb5_ccache *cc;
+ krb5_error_code kerr;
+ errno_t ret;
+
+ cc = talloc_zero(mem_ctx, struct sss_krb5_ccache);
+ if (!cc) {
+ return ENOMEM;
+ }
+ talloc_set_destructor((TALLOC_CTX *)cc, sss_free_krb5_ccache);
+
+ ret = switch_creds(cc, uid, gid, 0, NULL, &cc->creds);
+ if (ret) {
+ goto done;
+ }
+
+ kerr = krb5_init_context(&cc->context);
+ if (kerr) {
+ ret = EIO;
+ goto done;
+ }
+
+ kerr = krb5_cc_resolve(cc->context, ccname, &cc->ccache);
+ if (kerr == KRB5_FCC_NOFILE || cc->ccache == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("ccache %s is missing or empty\n", ccname));
+ ret = ERR_NOT_FOUND;
+ goto done;
+ } else if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
+ ret = ERR_INTERNAL;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret) {
+ talloc_free(cc);
+ } else {
+ *ccache = cc;
+ }
+ return ret;
+}
+
+static errno_t sss_destroy_ccache(struct sss_krb5_ccache *cc)
+{
+ krb5_error_code kerr;
+ errno_t ret;
+
+ kerr = krb5_cc_destroy(cc->context, cc->ccache);
+ if (kerr) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_destroy failed.\n"));
+ ret = EIO;
+ }
+
+ /* krb5_cc_destroy frees cc->ccache in all events */
+ cc->ccache = NULL;
+
+ return ret;
+}
+
+errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid)
+{
+ struct sss_krb5_ccache *cc = NULL;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+ return ENOMEM;
+ }
+
+ ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
+ if (ret) {
+ goto done;
+ }
+
+ ret = sss_destroy_ccache(cc);
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
/*======== ccache back end utilities ========*/
struct sss_krb5_cc_be *
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index aac3ec72ec7e1664ae96cc4e53d368e22448f5f1..ebcfe938af913f107b8816c3209b690ac90e797e 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -87,6 +87,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
struct sss_creds **saved_creds);
errno_t restore_creds(struct sss_creds *saved_creds);
+errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
+
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
--
1.8.3.1

View File

@ -0,0 +1,279 @@
From a70e88f62e8ba48c5042b881f20ed6586cb135a8 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Wed, 28 Aug 2013 23:18:37 -0400
Subject: [PATCH 03/14] krb5: Use krb5_cc_destroy to remove old ccaches
This completely replaces the per-ccache-type custom code to remove old cacches
and instead uses libkrb5 base doperations (krb5_cc_destroy) and operating as
the user owner.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
Makefile.am | 2 ++
src/providers/krb5/krb5_auth.c | 63 +++++++++++-------------------------
src/providers/krb5/krb5_utils.c | 71 -----------------------------------------
src/providers/krb5/krb5_utils.h | 2 --
src/tests/krb5_child-test.c | 2 +-
5 files changed, 21 insertions(+), 119 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 150f53e72cfa68dc5d32aa90ad475a72000ba3fb..25a4cbf83c790b85fab9ccccd611f59704a5b301 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -962,6 +962,7 @@ strtonum_tests_LDADD = \
krb5_utils_tests_SOURCES = \
src/tests/krb5_utils-tests.c \
src/providers/krb5/krb5_utils.c \
+ src/providers/krb5/krb5_become_user.c \
src/providers/krb5/krb5_common.c \
src/util/sss_krb5.c \
src/util/find_uid.c \
@@ -1532,6 +1533,7 @@ libsss_ldap_la_SOURCES = \
src/providers/ldap/ldap_access.c \
src/providers/krb5/krb5_common.c \
src/providers/krb5/krb5_utils.c \
+ src/providers/krb5/krb5_become_user.c \
src/util/user_info_msg.c \
src/util/sss_ldap.c \
src/util/sss_krb5.c
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index db0aa936ff5577afedf72cb43f1c71485e16505c..5d33dddb6d3bf28c7021580a3859a257b1507210 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -40,48 +40,19 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
-static errno_t safe_remove_old_ccache_file(struct sss_krb5_cc_be *cc_be,
- const char *princ,
- const char *old_ccache,
- const char *new_ccache)
+static errno_t safe_remove_old_ccache_file(const char *old_ccache,
+ const char *new_ccache,
+ uid_t uid, gid_t gid)
{
- int ret;
- enum sss_krb5_cc_type old_type;
- struct sss_krb5_cc_be *old_cc_ops;
-
- if (old_ccache == NULL) {
- DEBUG(SSSDBG_FUNC_DATA, ("No old ccache, nothing to do\n"));
- return EOK;
- }
-
- if (new_ccache == NULL) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Missing new ccache file, old ccache file is not deleted.\n"));
- return EINVAL;
- }
-
- old_type = sss_krb5_get_type(old_ccache);
- old_cc_ops = get_cc_be_ops(old_type);
- if (!old_cc_ops) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccache operations\n"));
- return EINVAL;
- }
-
- if (cc_be->type == old_type &&
- strcmp(old_ccache, new_ccache) == 0) {
+ if ((old_ccache == new_ccache)
+ || (old_ccache && new_ccache
+ && (strcmp(old_ccache, new_ccache) == 0))) {
DEBUG(SSSDBG_TRACE_FUNC, ("New and old ccache file are the same, "
- "no one will be deleted.\n"));
+ "none will be deleted.\n"));
return EOK;
}
- ret = old_cc_ops->remove(old_ccache);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Cannot remove ccache [%s]\n", old_ccache));
- return EIO;
- }
-
- return EOK;
+ return sss_krb5_cc_destroy(old_ccache, uid, gid);
}
static errno_t
@@ -1037,8 +1008,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
* used. */
if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache) {
if (kr->old_ccname != NULL) {
- ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
- kr->old_ccname, "dummy");
+ ret = safe_remove_old_ccache_file(kr->old_ccname, NULL,
+ kr->uid, kr->gid);
if (ret != EOK) {
DEBUG(1, ("Failed to remove old ccache file [%s], "
"please remove it manually.\n", kr->old_ccname));
@@ -1114,12 +1085,14 @@ static void krb5_auth_done(struct tevent_req *subreq)
goto done;
}
- ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
- kr->old_ccname, store_ccname);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE,
- ("Failed to remove old ccache file [%s], "
- "please remove it manually.\n", kr->old_ccname));
+ if (kr->old_ccname) {
+ ret = safe_remove_old_ccache_file(kr->old_ccname, store_ccname,
+ kr->uid, kr->gid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Failed to remove old ccache file [%s], "
+ "please remove it manually.\n", kr->old_ccname));
+ }
}
ret = krb5_save_ccname(state, state->sysdb, state->domain,
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 1141f3fc839a78927dab5f50267c52d5b44b46ba..0245cc9d008f64e00717dc3e878357ddf2fae9fa 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1120,42 +1120,11 @@ cc_file_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
return talloc_strdup(mem_ctx, location);
}
-errno_t
-cc_file_remove(const char *location)
-{
- errno_t ret;
- const char *filename;
-
- filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
- if (!filename) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n", location));
- return EINVAL;
- }
-
- if (filename[0] != '/') {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Ccache file name [%s] is not an absolute path.\n", filename));
- return EINVAL;
- }
-
- errno = 0;
- ret = unlink(filename);
- if (ret == -1 && errno != ENOENT) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("unlink [%s] failed [%d][%s].\n", filename, ret,
- strerror(ret)));
- return ret;
- }
- return EOK;
-}
-
struct sss_krb5_cc_be file_cc = {
.type = SSS_KRB5_TYPE_FILE,
.create = cc_file_create,
.check_existing = cc_file_check_existing,
.ccache_for_princ = cc_file_cache_for_princ,
- .remove = cc_file_remove,
};
#ifdef HAVE_KRB5_CC_COLLECTION
@@ -1333,32 +1302,11 @@ done:
return name;
}
-errno_t
-cc_dir_remove(const char *location)
-{
- const char *subsidiary;
-
- if (sss_krb5_get_type(location) != SSS_KRB5_TYPE_DIR) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR\n", location));
- return EINVAL;
- }
-
- subsidiary = sss_krb5_cc_file_path(location);
- if (!subsidiary) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get subsidiary cache from %s\n",
- location));
- return EINVAL;
- }
-
- return cc_file_remove(subsidiary);
-}
-
struct sss_krb5_cc_be dir_cc = {
.type = SSS_KRB5_TYPE_DIR,
.create = cc_dir_create,
.check_existing = cc_dir_check_existing,
.ccache_for_princ = cc_dir_cache_for_princ,
- .remove = cc_dir_remove
};
@@ -1485,30 +1433,11 @@ done:
return name;
}
-errno_t
-cc_keyring_remove(const char *location)
-{
- const char *residual;
-
- residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
- if (!residual) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("%s is not of type KEYRING:\n", location));
- return EINVAL;
- }
-
- /* No special steps are needed to create a kernel keyring.
- * Everything is handled in libkrb5.
- */
- return EOK;
-}
-
struct sss_krb5_cc_be keyring_cc = {
.type = SSS_KRB5_TYPE_KEYRING,
.create = cc_keyring_create,
.check_existing = cc_keyring_check_existing,
.ccache_for_princ = cc_keyring_cache_for_princ,
- .remove = cc_keyring_remove
};
#endif /* HAVE_KRB5_CC_COLLECTION */
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index ebcfe938af913f107b8816c3209b690ac90e797e..ac29d61e9e4efe963c835e8646ce540e09dc8dd7 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -52,7 +52,6 @@ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
typedef const char * (*cc_be_ccache_for_princ)(TALLOC_CTX *mem_ctx,
const char *location,
const char *princ);
-typedef errno_t (*cc_be_remove)(const char *location);
/* A ccache back end */
struct sss_krb5_cc_be {
@@ -61,7 +60,6 @@ struct sss_krb5_cc_be {
cc_be_create_fn create;
cc_be_check_existing check_existing;
cc_be_ccache_for_princ ccache_for_princ;
- cc_be_remove remove;
};
extern struct sss_krb5_cc_be file_cc;
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 24d077289d64d52488a3419ffc4494f59d6bc5df..dff62ab64dd1948d20da6b640a0570ee8ea6b11d 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -561,7 +561,7 @@ done:
if (rm_ccache && ctx->res
&& ctx->res->ccname
&& ctx->kr) {
- ctx->kr->krb5_ctx->cc_be->remove(ctx->res->ccname);
+ sss_krb5_cc_destroy(ctx->res->ccname, ctx->kr->uid, ctx->kr->gid);
}
free(password);
talloc_free(ctx);
--
1.8.3.1

View File

@ -0,0 +1,357 @@
From 1536e39c191a013bc50bb6fd4b8eaef11cf0d436 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 00:58:24 -0400
Subject: [PATCH 04/14] krb5: Replace type-specific ccache/principal check
Instead of having duplicate functions that are type custom use a signle common
function that also performs access to the cache as the user owner, implicitly
validating correctness of ownership.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 11 +-
src/providers/krb5/krb5_utils.c | 220 +++++++++++++++-------------------------
src/providers/krb5/krb5_utils.h | 6 +-
3 files changed, 89 insertions(+), 148 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 5d33dddb6d3bf28c7021580a3859a257b1507210..976fdec097a06ae5b211a5a93dcb13b9548031ef 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -837,7 +837,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
uint8_t *buf = NULL;
ssize_t len = -1;
struct krb5_child_response *res;
- const char *store_ccname;
struct fo_server *search_srv;
krb5_deltat renew_interval_delta;
char *renew_interval_str;
@@ -1076,17 +1075,15 @@ static void krb5_auth_done(struct tevent_req *subreq)
goto done;
}
- store_ccname = kr->cc_be->ccache_for_princ(kr, kr->ccname,
- kr->upn);
- if (store_ccname == NULL) {
+ ret = sss_krb5_check_ccache_princ(kr->uid, kr->gid, kr->ccname, kr->upn);
+ if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE,
("No ccache for %s in %s?\n", kr->upn, kr->ccname));
- ret = EIO;
goto done;
}
if (kr->old_ccname) {
- ret = safe_remove_old_ccache_file(kr->old_ccname, store_ccname,
+ ret = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname,
kr->uid, kr->gid);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
@@ -1096,7 +1093,7 @@ static void krb5_auth_done(struct tevent_req *subreq)
}
ret = krb5_save_ccname(state, state->sysdb, state->domain,
- pd->user, store_ccname);
+ pd->user, kr->ccname);
if (ret) {
DEBUG(1, ("krb5_save_ccname failed.\n"));
goto done;
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 0245cc9d008f64e00717dc3e878357ddf2fae9fa..ce3cab60d71a8b3329eeedbd82bec6ecb750948c 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -928,6 +928,89 @@ done:
}
+/* This function is called only as a way to validate that we have the
+ * right cache */
+errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
+ const char *ccname, const char *principal)
+{
+ struct sss_krb5_ccache *cc = NULL;
+ krb5_principal ccprinc = NULL;
+ krb5_principal kprinc = NULL;
+ krb5_error_code kerr;
+ const char *cc_type;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+ return ENOMEM;
+ }
+
+ ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
+ if (ret) {
+ goto done;
+ }
+
+ cc_type = krb5_cc_get_type(cc->context, cc->ccache);
+
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ ("Searching for [%s] in cache of type [%s]\n", principal, cc_type));
+
+ kerr = krb5_parse_name(cc->context, principal, &kprinc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
+ ret = ERR_INTERNAL;
+ goto done;
+ }
+
+ kerr = krb5_cc_get_principal(cc->context, cc->ccache, &ccprinc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_get_principal failed.\n"));
+ }
+
+ if (ccprinc) {
+ if (krb5_principal_compare(cc->context, kprinc, ccprinc) == TRUE) {
+ /* found in the primary ccache */
+ ret = EOK;
+ goto done;
+ }
+ }
+
+#ifdef HAVE_KRB5_CC_COLLECTION
+
+ if (krb5_cc_support_switch(cc->context, cc_type)) {
+
+ krb5_cc_close(cc->context, cc->ccache);
+ cc->ccache = NULL;
+
+ kerr = krb5_cc_set_default_name(cc->context, ccname);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_MINOR_FAILURE, cc->context, kerr);
+ /* try to continue despite failure */
+ }
+
+ kerr = krb5_cc_cache_match(cc->context, kprinc, &cc->ccache);
+ if (kerr == 0) {
+ ret = EOK;
+ goto done;
+ }
+ KRB5_DEBUG(SSSDBG_TRACE_INTERNAL, cc->context, kerr);
+ }
+
+#endif /* HAVE_KRB5_CC_COLLECTION */
+
+ ret = ERR_NOT_FOUND;
+
+done:
+ krb5_free_principal(cc->context, ccprinc);
+ krb5_free_principal(cc->context, kprinc);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
/*======== ccache back end utilities ========*/
struct sss_krb5_cc_be *
get_cc_be_ops(enum sss_krb5_cc_type type)
@@ -1113,18 +1196,10 @@ cc_file_check_existing(const char *location, uid_t uid,
return EOK;
}
-const char *
-cc_file_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
- const char *princ)
-{
- return talloc_strdup(mem_ctx, location);
-}
-
struct sss_krb5_cc_be file_cc = {
.type = SSS_KRB5_TYPE_FILE,
.create = cc_file_create,
.check_existing = cc_file_check_existing,
- .ccache_for_princ = cc_file_cache_for_princ,
};
#ifdef HAVE_KRB5_CC_COLLECTION
@@ -1246,67 +1321,10 @@ done:
return ret;
}
-const char *
-cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
- const char *princ)
-{
- krb5_context context = NULL;
- krb5_error_code krberr;
- char *name = NULL;
- const char *ccname;
- krb5_principal client_principal = NULL;
-
- ccname = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
- if (!ccname) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccname file from %s\n",
- location));
- return NULL;
- }
-
- /* ccname already points to a subsidiary cache */
- if (ccname[0] == ':' && ccname[1] && ccname[1] == '/') {
- return talloc_strdup(mem_ctx, location);
- }
-
- krberr = krb5_init_context(&context);
- if (krberr) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
- return NULL;
- }
-
- krberr = krb5_parse_name(context, princ, &client_principal);
- if (krberr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
- DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- /* This function is called only as a way to validate that,
- * we have the right cache
- */
- name = sss_get_ccache_name_for_principal(mem_ctx, context,
- client_principal, location);
- if (name == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get full name of ccache\n"));
- goto done;
- }
-
- talloc_zfree(name);
- /* everytime return location for dir_cache */
- name = talloc_strdup(mem_ctx, location);
-
-done:
- krb5_free_principal(context, client_principal);
- krb5_free_context(context);
-
- return name;
-}
-
struct sss_krb5_cc_be dir_cc = {
.type = SSS_KRB5_TYPE_DIR,
.create = cc_dir_create,
.check_existing = cc_dir_check_existing,
- .ccache_for_princ = cc_dir_cache_for_princ,
};
@@ -1362,82 +1380,10 @@ cc_keyring_check_existing(const char *location, uid_t uid,
return EOK;
}
-const char *
-cc_keyring_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
- const char *princ)
-{
- krb5_context context = NULL;
- krb5_error_code krberr;
- char *name = NULL;
- const char *residual;
- size_t i;
- size_t count;
- krb5_principal client_principal = NULL;
-
- residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
- if (!residual) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get residual from %s\n",
- location));
- return NULL;
- }
-
- /* residual already points to a subsidiary cache if it of the
- * form "KEYRING:<type>:<UID>:krb5_cc_XXXXXXX"
- * For simplicity, we'll count the colons, up to three.
- */
- i = count = 0;
- while (residual[i] && count < 3) {
- if (residual[i] == ':') {
- count ++;
- }
- i++;
- }
-
- if (count >= 3) {
- return talloc_strdup(mem_ctx, location);
- }
-
- krberr = krb5_init_context(&context);
- if (krberr) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
- return NULL;
- }
-
- krberr = krb5_parse_name(context, princ, &client_principal);
- if (krberr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
- DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- name = sss_get_ccache_name_for_principal(mem_ctx, context,
- client_principal, location);
- if (name == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get full name of ccache\n"));
- goto done;
- }
-
- talloc_zfree(name);
-
- /* Always return the master name here.
- * We do the above only to ensure that the
- * principal-specific name exists and can
- * be found.
- */
- name = talloc_strdup(mem_ctx, location);
-
-done:
- krb5_free_principal(context, client_principal);
- krb5_free_context(context);
-
- return name;
-}
-
struct sss_krb5_cc_be keyring_cc = {
.type = SSS_KRB5_TYPE_KEYRING,
.create = cc_keyring_create,
.check_existing = cc_keyring_check_existing,
- .ccache_for_princ = cc_keyring_cache_for_princ,
};
#endif /* HAVE_KRB5_CC_COLLECTION */
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index ac29d61e9e4efe963c835e8646ce540e09dc8dd7..a73098d4090199c5a49bdf0adf5115e9120eeb5b 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -49,9 +49,6 @@ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
const char *realm, const char *princ,
const char *cc_template, bool *active,
bool *valid);
-typedef const char * (*cc_be_ccache_for_princ)(TALLOC_CTX *mem_ctx,
- const char *location,
- const char *princ);
/* A ccache back end */
struct sss_krb5_cc_be {
@@ -59,7 +56,6 @@ struct sss_krb5_cc_be {
cc_be_create_fn create;
cc_be_check_existing check_existing;
- cc_be_ccache_for_princ ccache_for_princ;
};
extern struct sss_krb5_cc_be file_cc;
@@ -86,6 +82,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
errno_t restore_creds(struct sss_creds *saved_creds);
errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
+errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
+ const char *ccname, const char *principal);
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
--
1.8.3.1

View File

@ -0,0 +1,220 @@
From bfd32c9e8f302d7722838a68572c6801f5640657 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 11:31:23 -0400
Subject: [PATCH 05/14] krb5: Move determination of user being active
The way a user is checked for being active does not depend on the ccache
type so move that check out of the ccache specific functions.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 10 +++++++--
src/providers/krb5/krb5_utils.c | 47 +++++++----------------------------------
src/providers/krb5/krb5_utils.h | 3 +--
3 files changed, 17 insertions(+), 43 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 976fdec097a06ae5b211a5a93dcb13b9548031ef..178f18a3c5dec4772a59c6d6cfbcdc419c20d48c 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -76,7 +76,7 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
cc_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
- cc_template, active, valid);
+ cc_template, valid);
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_FUNC,
("Saved ccache %s doesn't exist.\n", old_ccache));
@@ -84,11 +84,17 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
}
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
- ("Cannot check if saved ccache %s is active and valid\n",
+ ("Cannot check if saved ccache %s is valid\n",
old_ccache));
return ret;
}
+ ret = check_if_uid_is_active(kr->uid, active);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("check_if_uid_is_active failed.\n"));
+ return ret;
+ }
+
return EOK;
}
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index ce3cab60d71a8b3329eeedbd82bec6ecb750948c..7f2ca2d5ba570e3467ec7dc4060f58f38b1f3428 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1066,14 +1066,11 @@ cc_file_create(const char *location, pcre *illegal_re,
}
static errno_t
-cc_residual_is_used(uid_t uid, const char *ccname,
- enum sss_krb5_cc_type type, bool *result)
+cc_residual_exists(uid_t uid, const char *ccname,
+ enum sss_krb5_cc_type type)
{
int ret;
struct stat stat_buf;
- bool active;
-
- *result = false;
if (ccname == NULL || *ccname == '\0') {
return EINVAL;
@@ -1086,7 +1083,6 @@ cc_residual_is_used(uid_t uid, const char *ccname,
if (ret == ENOENT) {
DEBUG(SSSDBG_FUNC_DATA, ("Cache file [%s] does not exist, "
"it will be recreated\n", ccname));
- *result = false;
return ENOENT;
}
@@ -1123,20 +1119,6 @@ cc_residual_is_used(uid_t uid, const char *ccname,
return EINVAL;
}
- ret = check_if_uid_is_active(uid, &active);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("check_if_uid_is_active failed.\n"));
- return ret;
- }
-
- if (!active) {
- DEBUG(SSSDBG_TRACE_FUNC, ("User [%d] is not active\n", uid));
- } else {
- DEBUG(SSSDBG_TRACE_LIBS,
- ("User [%d] is still active, reusing ccache [%s].\n",
- uid, ccname));
- *result = true;
- }
return EOK;
}
@@ -1157,10 +1139,9 @@ cc_check_template(const char *cc_template)
errno_t
cc_file_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_active, bool *_valid)
+ const char *cc_template, bool *_valid)
{
errno_t ret;
- bool active;
bool valid;
const char *filename;
@@ -1175,14 +1156,13 @@ cc_file_check_existing(const char *location, uid_t uid,
return EINVAL;
}
- ret = cc_residual_is_used(uid, filename, SSS_KRB5_TYPE_FILE, &active);
+ ret = cc_residual_exists(uid, filename, SSS_KRB5_TYPE_FILE);
if (ret != EOK) {
if (ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
("Could not check if ccache is active.\n"));
}
cc_check_template(cc_template);
- active = false;
return ret;
}
@@ -1191,7 +1171,6 @@ cc_file_check_existing(const char *location, uid_t uid,
return ret;
}
- *_active = active;
*_valid = valid;
return EOK;
}
@@ -1222,10 +1201,8 @@ cc_dir_create(const char *location, pcre *illegal_re,
errno_t
cc_dir_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_active, bool *_valid)
+ const char *cc_template, bool *_valid)
{
- bool active;
- bool active_primary = false;
bool valid;
enum sss_krb5_cc_type type;
const char *filename;
@@ -1279,7 +1256,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
dir = tmp;
}
- ret = cc_residual_is_used(uid, dir, SSS_KRB5_TYPE_DIR, &active);
+ ret = cc_residual_exists(uid, dir, SSS_KRB5_TYPE_DIR);
if (ret != EOK) {
if (ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
@@ -1298,8 +1275,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
ret = ENOMEM;
goto done;
}
- ret = cc_residual_is_used(uid, primary_file, SSS_KRB5_TYPE_FILE,
- &active_primary);
+ ret = cc_residual_exists(uid, primary_file, SSS_KRB5_TYPE_FILE);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
("Could not check if file 'primary' [%s] in dir ccache"
@@ -1312,7 +1288,6 @@ cc_dir_check_existing(const char *location, uid_t uid,
goto done;
}
- *_active = active;
*_valid = valid;
ret = EOK;
@@ -1351,11 +1326,9 @@ cc_keyring_create(const char *location, pcre *illegal_re,
errno_t
cc_keyring_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_active,
- bool *_valid)
+ const char *cc_template, bool *_valid)
{
errno_t ret;
- bool active;
bool valid;
const char *residual;
@@ -1366,16 +1339,12 @@ cc_keyring_check_existing(const char *location, uid_t uid,
return EINVAL;
}
- /* The keyring cache is always active */
- active = true;
-
/* Check if any user is actively using this cache */
ret = check_cc_validity(location, realm, princ, &valid);
if (ret != EOK) {
return ret;
}
- *_active = active;
*_valid = valid;
return EOK;
}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index a73098d4090199c5a49bdf0adf5115e9120eeb5b..ca33205817cbb726a75b809f71d1fb1589744e15 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -47,8 +47,7 @@ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *active,
- bool *valid);
+ const char *cc_template, bool *valid);
/* A ccache back end */
struct sss_krb5_cc_be {
--
1.8.3.1

View File

@ -0,0 +1,160 @@
From 5dc3b01fd9b2fa244e7c2820ce04602c9f059370 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 12:21:39 -0400
Subject: [PATCH 06/14] krb5: move template check to initializzation
The randomized template check realy only makes sense for the FILE ccache
which is the only one that normally needs to use randomizing chars.
Also it is better to warn the admin early rather than to warn 'when it
is too late'.
So move the check at initialization time when we determine what the
template actually is.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 5 +----
src/providers/krb5/krb5_common.c | 17 +++++++++++++++++
src/providers/krb5/krb5_utils.c | 22 +++-------------------
src/providers/krb5/krb5_utils.h | 2 +-
4 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 178f18a3c5dec4772a59c6d6cfbcdc419c20d48c..ca00ce7a3aefa6dae3116f57c994d1f5cd1f50ea 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -60,7 +60,6 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
const char *realm, bool *active, bool *valid)
{
struct sss_krb5_cc_be *old_cc_ops;
- const char *cc_template;
errno_t ret;
/* ccache file might be of a different type if the user changed
@@ -73,10 +72,8 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
return EINVAL;
}
- cc_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
-
ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
- cc_template, valid);
+ valid);
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_FUNC,
("Saved ccache %s doesn't exist.\n", old_ccache));
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index c7ce574d513702132cb7e0c8ca4f1f1b80430f0b..de7ae0a8fe345c38f9458fb9642a5c1b83c906f5 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -144,6 +144,19 @@ static errno_t sss_get_system_ccname_template(TALLOC_CTX *mem_ctx,
}
#endif
+static void sss_check_cc_template(const char *cc_template)
+{
+ size_t template_len;
+
+ template_len = strlen(cc_template);
+ if (template_len >= 6 &&
+ strcmp(cc_template + (template_len - 6), "XXXXXX") != 0) {
+ DEBUG(SSSDBG_CONF_SETTINGS, ("ccache file name template [%s] doesn't "
+ "contain randomizing characters (XXXXXX), file might not "
+ "be rewritable\n", cc_template));
+ }
+}
+
errno_t check_and_export_options(struct dp_option *opts,
struct sss_domain_info *dom,
struct krb5_ctx *krb5_ctx)
@@ -282,6 +295,10 @@ errno_t check_and_export_options(struct dp_option *opts,
switch (cc_be) {
case SSS_KRB5_TYPE_FILE:
DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n"));
+ /* warn if the file type (which is usally created in a sticky bit
+ * laden directory) does not have randomizing chracters */
+ sss_check_cc_template(ccname);
+
krb5_ctx->cc_be = &file_cc;
if (ccname[0] != '/') {
/* FILE:/path/to/cc */
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 7f2ca2d5ba570e3467ec7dc4060f58f38b1f3428..b174462ee4e8f3992e6d9c06f91118098c598149 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1122,24 +1122,10 @@ cc_residual_exists(uid_t uid, const char *ccname,
return EOK;
}
-static void
-cc_check_template(const char *cc_template)
-{
- size_t template_len;
-
- template_len = strlen(cc_template);
- if (template_len >= 6 &&
- strcmp(cc_template + (template_len - 6), "XXXXXX") != 0) {
- DEBUG(SSSDBG_CONF_SETTINGS, ("ccache file name template [%s] doesn't "
- "contain randomizing characters (XXXXXX), file might not "
- "be rewritable\n", cc_template));
- }
-}
-
errno_t
cc_file_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_valid)
+ bool *_valid)
{
errno_t ret;
bool valid;
@@ -1162,7 +1148,6 @@ cc_file_check_existing(const char *location, uid_t uid,
DEBUG(SSSDBG_OP_FAILURE,
("Could not check if ccache is active.\n"));
}
- cc_check_template(cc_template);
return ret;
}
@@ -1201,7 +1186,7 @@ cc_dir_create(const char *location, pcre *illegal_re,
errno_t
cc_dir_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_valid)
+ bool *_valid)
{
bool valid;
enum sss_krb5_cc_type type;
@@ -1262,7 +1247,6 @@ cc_dir_check_existing(const char *location, uid_t uid,
DEBUG(SSSDBG_OP_FAILURE,
("Could not check if ccache is active.\n"));
}
- cc_check_template(cc_template);
goto done;
}
@@ -1326,7 +1310,7 @@ cc_keyring_create(const char *location, pcre *illegal_re,
errno_t
cc_keyring_check_existing(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *_valid)
+ bool *_valid)
{
errno_t ret;
bool valid;
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index ca33205817cbb726a75b809f71d1fb1589744e15..e241666289193bdc3c5eccadfffc4d3d669dff16 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -47,7 +47,7 @@ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
const char *realm, const char *princ,
- const char *cc_template, bool *valid);
+ bool *valid);
/* A ccache back end */
struct sss_krb5_cc_be {
--
1.8.3.1

View File

@ -0,0 +1,201 @@
From c121e65ed592bf3611053ee38032fd33c8d1b285 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 12:27:49 -0400
Subject: [PATCH 07/14] krb5: Make check_for_valid_tgt() static
check_for_valid_tgt() is used exclusively in krb5_uitls.c so move it there.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_utils.c | 74 +++++++++++++++++++++++++++++++++++++++++
src/util/sss_krb5.c | 72 ---------------------------------------
src/util/sss_krb5.h | 4 ---
3 files changed, 74 insertions(+), 76 deletions(-)
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index b174462ee4e8f3992e6d9c06f91118098c598149..463a5eb409d076825f25d45c034d58f4a89780eb 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -761,6 +761,80 @@ done:
return ret;
}
+static krb5_error_code check_for_valid_tgt(krb5_context context,
+ krb5_ccache ccache,
+ const char *realm,
+ const char *client_princ_str,
+ bool *result)
+{
+ krb5_error_code krberr;
+ TALLOC_CTX *tmp_ctx = NULL;
+ krb5_creds mcred;
+ krb5_creds cred;
+ char *server_name = NULL;
+ krb5_principal client_principal = NULL;
+ krb5_principal server_principal = NULL;
+
+ *result = false;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(1, ("talloc_new failed.\n"));
+ return ENOMEM;
+ }
+
+ server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
+ if (server_name == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ krberr = ENOMEM;
+ goto done;
+ }
+
+ krberr = krb5_parse_name(context, server_name, &server_principal);
+ if (krberr != 0) {
+ DEBUG(1, ("krb5_parse_name failed.\n"));
+ goto done;
+ }
+
+ krberr = krb5_parse_name(context, client_princ_str, &client_principal);
+ if (krberr != 0) {
+ DEBUG(1, ("krb5_parse_name failed.\n"));
+ goto done;
+ }
+
+ memset(&mcred, 0, sizeof(mcred));
+ memset(&cred, 0, sizeof(mcred));
+ mcred.client = client_principal;
+ mcred.server = server_principal;
+
+ krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
+ if (krberr != 0) {
+ DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
+ krberr = 0;
+ goto done;
+ }
+
+ DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
+
+ if (cred.times.endtime > time(NULL)) {
+ DEBUG(3, ("TGT is valid.\n"));
+ *result = true;
+ }
+ krb5_free_cred_contents(context, &cred);
+
+ krberr = 0;
+
+done:
+ if (client_principal != NULL) {
+ krb5_free_principal(context, client_principal);
+ }
+ if (server_principal != NULL) {
+ krb5_free_principal(context, server_principal);
+ }
+ talloc_free(tmp_ctx);
+ return krberr;
+}
+
static errno_t
check_cc_validity(const char *location,
const char *realm,
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index b25ed24919555666422e6a87ded8688ca76c345f..440edab8a4624b33b7d358e64ead93949fc3de88 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -546,78 +546,6 @@ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
}
-krb5_error_code check_for_valid_tgt(krb5_context context,
- krb5_ccache ccache, const char *realm,
- const char *client_princ_str, bool *result)
-{
- krb5_error_code krberr;
- TALLOC_CTX *tmp_ctx = NULL;
- krb5_creds mcred;
- krb5_creds cred;
- char *server_name = NULL;
- krb5_principal client_principal = NULL;
- krb5_principal server_principal = NULL;
-
- *result = false;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
- if (server_name == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- krberr = ENOMEM;
- goto done;
- }
-
- krberr = krb5_parse_name(context, server_name, &server_principal);
- if (krberr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- krberr = krb5_parse_name(context, client_princ_str, &client_principal);
- if (krberr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- memset(&mcred, 0, sizeof(mcred));
- memset(&cred, 0, sizeof(mcred));
- mcred.client = client_principal;
- mcred.server = server_principal;
-
- krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
- if (krberr != 0) {
- DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
- krberr = 0;
- goto done;
- }
-
- DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
-
- if (cred.times.endtime > time(NULL)) {
- DEBUG(3, ("TGT is valid.\n"));
- *result = true;
- }
- krb5_free_cred_contents(context, &cred);
-
- krberr = 0;
-
-done:
- if (client_principal != NULL) {
- krb5_free_principal(context, client_principal);
- }
- if (server_principal != NULL) {
- krb5_free_principal(context, server_principal);
- }
- talloc_free(tmp_ctx);
- return krberr;
-}
-
krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback(
krb5_context context,
krb5_get_init_creds_opt *opt,
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index b1074f813a6b12d132b8c3d0290ad914b003e70f..aaf2a64882254ba173fb57c5dab47d246082392c 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -70,10 +70,6 @@ void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name);
-krb5_error_code check_for_valid_tgt(krb5_context context,
- krb5_ccache ccache, const char *realm,
- const char *client_princ_str, bool *result);
-
int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
krb5_context context, krb5_keytab keytab);
--
1.8.3.1

View File

@ -0,0 +1,568 @@
From 84ce563e3f430eec1225a6f8493eb0a6c9a3013a Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 16:35:43 -0400
Subject: [PATCH 08/14] krb5: Use new function to validate ccaches
This function replaces and combines check_for_valid_tgt() and type specific
functions that checked for ccache existence by using generic krb5 cache
function and executing them as the target user (implicitly validate the
target use rcan properly access the ccache).
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 30 ++-
src/providers/krb5/krb5_utils.c | 423 +++++++---------------------------------
src/providers/krb5/krb5_utils.h | 6 +-
3 files changed, 88 insertions(+), 371 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index ca00ce7a3aefa6dae3116f57c994d1f5cd1f50ea..1ea179be3af48b16129aeb4c2d850a66244f7d08 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -59,27 +59,25 @@ static errno_t
check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
const char *realm, bool *active, bool *valid)
{
- struct sss_krb5_cc_be *old_cc_ops;
errno_t ret;
- /* ccache file might be of a different type if the user changed
- * configuration
- */
- old_cc_ops = get_cc_be_ops_ccache(old_ccache);
- if (old_cc_ops == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Cannot get operations on saved ccache %s\n", old_ccache));
- return EINVAL;
- }
+ *active = false;
+ *valid = false;
- ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
- valid);
- if (ret == ENOENT) {
+ ret = sss_krb5_cc_verify_ccache(old_ccache,
+ kr->uid, kr->gid,
+ realm, kr->upn);
+ switch (ret) {
+ case ERR_NOT_FOUND:
DEBUG(SSSDBG_TRACE_FUNC,
("Saved ccache %s doesn't exist.\n", old_ccache));
- return ret;
- }
- if (ret != EOK) {
+ return ENOENT;
+ case EINVAL:
+ /* cache found but no tgt or expired */
+ case EOK:
+ *valid = true;
+ break;
+ default:
DEBUG(SSSDBG_OP_FAILURE,
("Cannot check if saved ccache %s is valid\n",
old_ccache));
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 463a5eb409d076825f25d45c034d58f4a89780eb..c4849e74bd43b096b585398970f5b81e946212e9 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -761,136 +761,6 @@ done:
return ret;
}
-static krb5_error_code check_for_valid_tgt(krb5_context context,
- krb5_ccache ccache,
- const char *realm,
- const char *client_princ_str,
- bool *result)
-{
- krb5_error_code krberr;
- TALLOC_CTX *tmp_ctx = NULL;
- krb5_creds mcred;
- krb5_creds cred;
- char *server_name = NULL;
- krb5_principal client_principal = NULL;
- krb5_principal server_principal = NULL;
-
- *result = false;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
- if (server_name == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- krberr = ENOMEM;
- goto done;
- }
-
- krberr = krb5_parse_name(context, server_name, &server_principal);
- if (krberr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- krberr = krb5_parse_name(context, client_princ_str, &client_principal);
- if (krberr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
- goto done;
- }
-
- memset(&mcred, 0, sizeof(mcred));
- memset(&cred, 0, sizeof(mcred));
- mcred.client = client_principal;
- mcred.server = server_principal;
-
- krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
- if (krberr != 0) {
- DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
- krberr = 0;
- goto done;
- }
-
- DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
-
- if (cred.times.endtime > time(NULL)) {
- DEBUG(3, ("TGT is valid.\n"));
- *result = true;
- }
- krb5_free_cred_contents(context, &cred);
-
- krberr = 0;
-
-done:
- if (client_principal != NULL) {
- krb5_free_principal(context, client_principal);
- }
- if (server_principal != NULL) {
- krb5_free_principal(context, server_principal);
- }
- talloc_free(tmp_ctx);
- return krberr;
-}
-
-static errno_t
-check_cc_validity(const char *location,
- const char *realm,
- const char *princ,
- bool *_valid)
-{
- errno_t ret;
- bool valid = false;
- krb5_ccache ccache = NULL;
- krb5_context context = NULL;
- krb5_error_code krberr;
-
- krberr = krb5_init_context(&context);
- if (krberr) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to init kerberos context\n"));
- return EIO;
- }
-
- krberr = krb5_cc_resolve(context, location, &ccache);
- if (krberr == KRB5_FCC_NOFILE || ccache == NULL) {
- /* KRB5_FCC_NOFILE would be returned if the directory components
- * of the DIR cache do not exist, which is the case in /run
- * after a reboot
- */
- DEBUG(SSSDBG_TRACE_FUNC,
- ("ccache %s is missing or empty\n", location));
- valid = false;
- ret = EOK;
- goto done;
- } else if (krberr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
- DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
- ret = EIO;
- goto done;
- }
-
- krberr = check_for_valid_tgt(context, ccache, realm, princ, &valid);
- if (krberr != EOK) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Could not check if ccache contains a valid principal\n"));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret == EOK) {
- *_valid = valid;
- }
- if (ccache) krb5_cc_close(context, ccache);
- krb5_free_context(context);
- return ret;
-}
-
struct sss_krb5_ccache {
struct sss_creds *creds;
@@ -1085,6 +955,78 @@ done:
return ret;
}
+errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
+ const char *realm, const char *principal)
+{
+ struct sss_krb5_ccache *cc = NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+ krb5_principal tgt_princ = NULL;
+ krb5_principal princ = NULL;
+ char *tgt_name;
+ krb5_creds mcred = { 0 };
+ krb5_creds cred = { 0 };
+ krb5_error_code kerr;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
+ return ENOMEM;
+ }
+
+ ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
+ if (ret) {
+ goto done;
+ }
+
+ tgt_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
+ if (!tgt_name) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ kerr = krb5_parse_name(cc->context, tgt_name, &tgt_princ);
+ if (kerr) {
+ KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
+ if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
+ else ret = ERR_INTERNAL;
+ goto done;
+ }
+
+ kerr = krb5_parse_name(cc->context, principal, &princ);
+ if (kerr) {
+ KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
+ if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
+ else ret = ERR_INTERNAL;
+ goto done;
+ }
+
+ mcred.client = princ;
+ mcred.server = tgt_princ;
+ mcred.times.endtime = time(NULL);
+
+ kerr = krb5_cc_retrieve_cred(cc->context, cc->ccache,
+ KRB5_TC_MATCH_TIMES, &mcred, &cred);
+ if (kerr) {
+ if (kerr == KRB5_CC_NOTFOUND) {
+ DEBUG(SSSDBG_TRACE_INTERNAL, ("TGT not found or expired.\n"));
+ ret = EINVAL;
+ } else {
+ KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
+ ret = ERR_INTERNAL;
+ }
+ }
+ krb5_free_cred_contents(cc->context, &cred);
+
+done:
+ if (tgt_princ) krb5_free_principal(cc->context, tgt_princ);
+ if (princ) krb5_free_principal(cc->context, princ);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
/*======== ccache back end utilities ========*/
struct sss_krb5_cc_be *
get_cc_be_ops(enum sss_krb5_cc_type type)
@@ -1139,105 +1081,9 @@ cc_file_create(const char *location, pcre *illegal_re,
return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path);
}
-static errno_t
-cc_residual_exists(uid_t uid, const char *ccname,
- enum sss_krb5_cc_type type)
-{
- int ret;
- struct stat stat_buf;
-
- if (ccname == NULL || *ccname == '\0') {
- return EINVAL;
- }
-
- ret = lstat(ccname, &stat_buf);
-
- if (ret == -1) {
- ret = errno;
- if (ret == ENOENT) {
- DEBUG(SSSDBG_FUNC_DATA, ("Cache file [%s] does not exist, "
- "it will be recreated\n", ccname));
- return ENOENT;
- }
-
- DEBUG(SSSDBG_OP_FAILURE,
- ("stat failed [%d][%s].\n", ret, strerror(ret)));
- return ret;
- }
-
- if (stat_buf.st_uid != uid) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Cache file [%s] exists, but is owned by [%d] instead of "
- "[%d].\n", ccname, stat_buf.st_uid, uid));
- return EINVAL;
- }
-
- switch (type) {
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- ret = S_ISDIR(stat_buf.st_mode);
- break;
-#endif /* HAVE_KRB5_CC_COLLECTION */
- case SSS_KRB5_TYPE_FILE:
- ret = S_ISREG(stat_buf.st_mode);
- break;
- default:
- DEBUG(SSSDBG_CRIT_FAILURE, ("Unsupported ccache type\n"));
- return EINVAL;
- }
-
- if (ret == 0) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Cache file [%s] exists, but is not the expected type\n",
- ccname));
- return EINVAL;
- }
-
- return EOK;
-}
-
-errno_t
-cc_file_check_existing(const char *location, uid_t uid,
- const char *realm, const char *princ,
- bool *_valid)
-{
- errno_t ret;
- bool valid;
- const char *filename;
-
- filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
- if (!filename) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n", location));
- return EINVAL;
- }
-
- if (filename[0] != '/') {
- DEBUG(SSSDBG_OP_FAILURE, ("Only absolute path names are allowed.\n"));
- return EINVAL;
- }
-
- ret = cc_residual_exists(uid, filename, SSS_KRB5_TYPE_FILE);
- if (ret != EOK) {
- if (ret != ENOENT) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Could not check if ccache is active.\n"));
- }
- return ret;
- }
-
- ret = check_cc_validity(location, realm, princ, &valid);
- if (ret != EOK) {
- return ret;
- }
-
- *_valid = valid;
- return EOK;
-}
-
struct sss_krb5_cc_be file_cc = {
.type = SSS_KRB5_TYPE_FILE,
.create = cc_file_create,
- .check_existing = cc_file_check_existing,
};
#ifdef HAVE_KRB5_CC_COLLECTION
@@ -1257,107 +1103,9 @@ cc_dir_create(const char *location, pcre *illegal_re,
return create_ccache_dir_head(dir_name, illegal_re, uid, gid, private_path);
}
-errno_t
-cc_dir_check_existing(const char *location, uid_t uid,
- const char *realm, const char *princ,
- bool *_valid)
-{
- bool valid;
- enum sss_krb5_cc_type type;
- const char *filename;
- const char *dir;
- char *tmp;
- char *primary_file;
- errno_t ret;
- TALLOC_CTX *tmp_ctx;
-
- type = sss_krb5_get_type(location);
- if (type != SSS_KRB5_TYPE_DIR) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR:\n", location));
- return EINVAL;
- }
-
- filename = sss_krb5_cc_file_path(location);
- if (!filename) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Existing ccname does not contain path into the collection"));
- return EINVAL;
- }
-
- if (filename[0] != '/') {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Only absolute path names are allowed.\n"));
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- tmp = talloc_strdup(tmp_ctx, filename);
- if (!tmp) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- if (0 == strncmp(location, "DIR::", 5)) {
- dir = dirname(tmp);
- if (!dir) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Cannot get base directory of %s.\n", tmp));
- ret = EINVAL;
- goto done;
- }
- } else {
- dir = tmp;
- }
-
- ret = cc_residual_exists(uid, dir, SSS_KRB5_TYPE_DIR);
- if (ret != EOK) {
- if (ret != ENOENT) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Could not check if ccache is active.\n"));
- }
- goto done;
- }
-
- /* If primary file isn't in ccache dir, we will ignore it.
- * But if primary file has wrong permissions, we will fail.
- */
- primary_file = talloc_asprintf(tmp_ctx, "%s/primary", dir);
- if (!primary_file) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- ret = cc_residual_exists(uid, primary_file, SSS_KRB5_TYPE_FILE);
- if (ret != EOK && ret != ENOENT) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Could not check if file 'primary' [%s] in dir ccache"
- " is active.\n", primary_file));
- goto done;
- }
-
- ret = check_cc_validity(location, realm, princ, &valid);
- if (ret != EOK) {
- goto done;
- }
-
- *_valid = valid;
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
struct sss_krb5_cc_be dir_cc = {
.type = SSS_KRB5_TYPE_DIR,
.create = cc_dir_create,
- .check_existing = cc_dir_check_existing,
};
@@ -1381,36 +1129,9 @@ cc_keyring_create(const char *location, pcre *illegal_re,
return EOK;
}
-errno_t
-cc_keyring_check_existing(const char *location, uid_t uid,
- const char *realm, const char *princ,
- bool *_valid)
-{
- errno_t ret;
- bool valid;
- const char *residual;
-
- residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
- if (!residual) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("%s is not of type KEYRING:\n", location));
- return EINVAL;
- }
-
- /* Check if any user is actively using this cache */
- ret = check_cc_validity(location, realm, princ, &valid);
- if (ret != EOK) {
- return ret;
- }
-
- *_valid = valid;
- return EOK;
-}
-
struct sss_krb5_cc_be keyring_cc = {
.type = SSS_KRB5_TYPE_KEYRING,
.create = cc_keyring_create,
- .check_existing = cc_keyring_check_existing,
};
#endif /* HAVE_KRB5_CC_COLLECTION */
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index e241666289193bdc3c5eccadfffc4d3d669dff16..b364f87aa6e6f0070e8acb5559ee92f2e001e0a5 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -45,16 +45,12 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
/* Operations on a credential cache */
typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
-typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
- const char *realm, const char *princ,
- bool *valid);
/* A ccache back end */
struct sss_krb5_cc_be {
enum sss_krb5_cc_type type;
cc_be_create_fn create;
- cc_be_check_existing check_existing;
};
extern struct sss_krb5_cc_be file_cc;
@@ -83,6 +79,8 @@ errno_t restore_creds(struct sss_creds *saved_creds);
errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
const char *ccname, const char *principal);
+errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
+ const char *realm, const char *principal);
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
--
1.8.3.1

View File

@ -0,0 +1,348 @@
From 1c022b3556f442f57326c4a3f250128b1bd232ae Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 17:25:01 -0400
Subject: [PATCH 09/14] krb5: Unify function to create ccache files
Only 2 types (FILE and DIR) need to precreate files or directories
on the file system, and the 2 functions were basically identical.
Consolidate all in one common function and use that function directly
where needed instead of using indirection.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 6 ++--
src/providers/krb5/krb5_utils.c | 71 ++++++++++-------------------------------
src/providers/krb5/krb5_utils.h | 14 ++------
src/tests/krb5_child-test.c | 6 ++--
src/tests/krb5_utils-tests.c | 40 +++++++++++------------
5 files changed, 43 insertions(+), 94 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 1ea179be3af48b16129aeb4c2d850a66244f7d08..d2c53f98c04cda01c2a8e0efe038f5cd5fa82839 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -333,9 +333,9 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
return EINVAL;
}
- ret = kr->cc_be->create(kr->ccname,
- kr->krb5_ctx->illegal_path_re,
- kr->uid, kr->gid, private_path);
+ ret = sss_krb5_precreate_ccache(kr->ccname,
+ kr->krb5_ctx->illegal_path_re,
+ kr->uid, kr->gid, private_path);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("ccache creation failed.\n"));
return ret;
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index c4849e74bd43b096b585398970f5b81e946212e9..83e61e14ecc116b9556231c5d8a0f55b63260c77 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -722,19 +722,31 @@ done:
return EOK;
}
-static errno_t
-create_ccache_dir_head(const char *parent, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path)
+errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path)
{
+ TALLOC_CTX *tmp_ctx = NULL;
+ const char *filename;
char *ccdirname;
- TALLOC_CTX *tmp_ctx = NULL;
char *end;
errno_t ret;
+ if (ccname[0] == '/') {
+ filename = ccname;
+ } else if (strncmp(ccname, "FILE:", 5) == 0) {
+ filename = ccname + 5;
+ } else if (strncmp(ccname, "DIR:", 4) == 0) {
+ filename = ccname + 4;
+ } else {
+ /* only FILE and DIR types need precreation so far, we ignore any
+ * other type */
+ return EOK;
+ }
+
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
- ccdirname = talloc_strdup(tmp_ctx, parent);
+ ccdirname = talloc_strdup(tmp_ctx, filename);
if (ccdirname == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
ret = ENOMEM;
@@ -1066,72 +1078,23 @@ get_cc_be_ops_ccache(const char *ccache)
}
/*======== Operations on the FILE: back end ========*/
-errno_t
-cc_file_create(const char *location, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path)
-{
- const char *filename;
-
- filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
- if (filename == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Bad ccache type %s\n", location));
- return EINVAL;
- }
-
- return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path);
-}
struct sss_krb5_cc_be file_cc = {
.type = SSS_KRB5_TYPE_FILE,
- .create = cc_file_create,
};
#ifdef HAVE_KRB5_CC_COLLECTION
/*======== Operations on the DIR: back end ========*/
-errno_t
-cc_dir_create(const char *location, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path)
-{
- const char *dir_name;
-
- dir_name = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
- if (dir_name == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Bad residual type\n"));
- return EINVAL;
- }
-
- return create_ccache_dir_head(dir_name, illegal_re, uid, gid, private_path);
-}
struct sss_krb5_cc_be dir_cc = {
.type = SSS_KRB5_TYPE_DIR,
- .create = cc_dir_create,
};
/*======== Operations on the KEYRING: back end ========*/
-errno_t
-cc_keyring_create(const char *location, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path)
-{
- const char *residual;
-
- residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
- if (residual == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Bad ccache type %s\n", location));
- return EINVAL;
- }
-
- /* No special steps are needed to create a kernel keyring.
- * Everything is handled in libkrb5.
- */
- return EOK;
-}
-
struct sss_krb5_cc_be keyring_cc = {
.type = SSS_KRB5_TYPE_KEYRING,
- .create = cc_keyring_create,
};
#endif /* HAVE_KRB5_CC_COLLECTION */
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index b364f87aa6e6f0070e8acb5559ee92f2e001e0a5..5f720335aab1ac6e493843ac197c5af881a9b998 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -42,15 +42,9 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
const char *user,
const char *upn);
-/* Operations on a credential cache */
-typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path);
-
/* A ccache back end */
struct sss_krb5_cc_be {
enum sss_krb5_cc_type type;
-
- cc_be_create_fn create;
};
extern struct sss_krb5_cc_be file_cc;
@@ -58,9 +52,6 @@ extern struct sss_krb5_cc_be file_cc;
errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
-errno_t cc_file_create(const char *filename, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path);
-
struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
@@ -76,6 +67,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
struct sss_creds **saved_creds);
errno_t restore_creds(struct sss_creds *saved_creds);
+errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path);
errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
const char *ccname, const char *principal);
@@ -90,9 +83,6 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
extern struct sss_krb5_cc_be dir_cc;
extern struct sss_krb5_cc_be keyring_cc;
-errno_t cc_dir_create(const char *location, pcre *illegal_re,
- uid_t uid, gid_t gid, bool private_path);
-
#endif /* HAVE_KRB5_CC_COLLECTION */
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index dff62ab64dd1948d20da6b640a0570ee8ea6b11d..5ea30014f9c8f748e85506627b7f40d72b913b1b 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -287,9 +287,9 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
kr->ccname, kr->uid, kr->gid));
- ret = kr->krb5_ctx->cc_be->create(kr->ccname,
- kr->krb5_ctx->illegal_path_re,
- kr->uid, kr->gid, private);
+ ret = sss_krb5_precreate_ccache(kr->ccname,
+ kr->krb5_ctx->illegal_path_re,
+ kr->uid, kr->gid, private);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
goto fail;
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index 4715774ff189700bc1cbeb6c90f4438445a594b0..ea0292569135e0fc22a44251cfc4e8719a15837f 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -117,14 +117,14 @@ START_TEST(test_pub_ccache_dir)
ret = chmod(testpath, 0754);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, 12345, 12345, false);
- fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
+ ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
+ fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
"while x-bit is missing.");
ret = chmod(testpath, 0755);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, 12345, 12345, false);
- fail_unless(ret == EOK, "cc_file_create failed.");
+ ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
+ fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
check_dir(subdirname, 0, 0, 01777);
RMDIR(subdirname);
@@ -158,7 +158,7 @@ START_TEST(test_pub_ccache_dir_in_user_dir)
filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, NULL, 12345, 12345, false);
+ ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
fail_unless(ret == EINVAL, "Creating public ccache dir in user dir "
"does not failed with EINVAL.");
@@ -193,14 +193,14 @@ START_TEST(test_priv_ccache_dir)
ret = chmod(testpath, 0754);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
+ ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
+ fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
"while x-bit is missing.");
ret = chmod(testpath, 0755);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, uid, gid, true);
- fail_unless(ret == EOK, "cc_file_create failed.");
+ ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
+ fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
check_dir(subdir, uid, gid, 0700);
RMDIR(subdir);
@@ -248,14 +248,14 @@ START_TEST(test_private_ccache_dir_in_user_dir)
ret = chmod(user_dir, 0600);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
+ ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
+ fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
"while x-bit is missing.");
ret = chmod(user_dir, 0700);
fail_unless(ret == EOK, "chmod failed.");
- ret = cc_file_create(filename, NULL, uid, gid, true);
- fail_unless(ret == EOK, "cc_file_create failed.");
+ ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
+ fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
check_dir(dn3, uid, gid, 0700);
RMDIR(dn3);
@@ -292,7 +292,7 @@ START_TEST(test_private_ccache_dir_in_wrong_user_dir)
filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, NULL, 12345, 12345, true);
+ ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, true);
fail_unless(ret == EINVAL, "Creating private ccache dir in wrong user "
"dir does not failed with EINVAL.");
@@ -357,7 +357,6 @@ START_TEST(test_illegal_patterns)
}
END_TEST
-#ifdef HAVE_KRB5_CC_COLLECTION
START_TEST(test_cc_dir_create)
{
char *residual;
@@ -386,8 +385,8 @@ START_TEST(test_cc_dir_create)
residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
fail_unless(residual != NULL, "talloc_asprintf failed.");
- ret = cc_dir_create(residual, illegal_re, uid, gid, true);
- fail_unless(ret == EOK, "cc_dir_create failed\n");
+ ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid, true);
+ fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
ret = rmdir(dirname);
if (ret < 0) ret = errno;
fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
@@ -399,8 +398,8 @@ START_TEST(test_cc_dir_create)
residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
fail_unless(residual != NULL, "talloc_asprintf failed.");
- ret = cc_dir_create(residual, illegal_re, uid, gid, true);
- fail_unless(ret == EOK, "cc_dir_create failed\n");
+ ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid, true);
+ fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
ret = rmdir(dirname);
if (ret < 0) ret = errno;
fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
@@ -408,7 +407,6 @@ START_TEST(test_cc_dir_create)
free(cwd);
}
END_TEST
-#endif /* HAVE_KRB5_CC_COLLECTION */
void setup_talloc_context(void)
@@ -774,9 +772,7 @@ Suite *krb5_utils_suite (void)
tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
teardown_create_dir);
tcase_add_test (tc_create_dir, test_illegal_patterns);
-#ifdef HAVE_KRB5_CC_COLLECTION
tcase_add_test (tc_create_dir, test_cc_dir_create);
-#endif /* HAVE_KRB5_CC_COLLECTION */
if (getuid() == 0) {
tcase_add_test (tc_create_dir, test_priv_ccache_dir);
tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir);
--
1.8.3.1

View File

@ -0,0 +1,337 @@
From d20a5a74666413cadbf64c02eb656a5a3b4bb1de Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 20:11:42 -0400
Subject: [PATCH 10/14] krb5: Remove unused ccache backend infrastructure
Remove struct sss_krb5_cc_be and the remaining functions that reference
it as they are all unused now.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 26 -----------------
src/providers/krb5/krb5_auth.h | 1 -
src/providers/krb5/krb5_common.c | 54 ++++++++++--------------------------
src/providers/krb5/krb5_common.h | 2 --
src/providers/krb5/krb5_utils.c | 60 ----------------------------------------
src/providers/krb5/krb5_utils.h | 17 ------------
src/tests/krb5_child-test.c | 23 ---------------
7 files changed, 15 insertions(+), 168 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index d2c53f98c04cda01c2a8e0efe038f5cd5fa82839..1585f709655853827f2778010452a58657add5d0 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -324,15 +324,6 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
return ENOMEM;
}
- if (kr->cc_be == NULL) {
- kr->cc_be = get_cc_be_ops_ccache(kr->ccname);
- }
- if (kr->cc_be == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Cannot get operations on new ccache %s\n", kr->ccname));
- return EINVAL;
- }
-
ret = sss_krb5_precreate_ccache(kr->ccname,
kr->krb5_ctx->illegal_path_re,
kr->uid, kr->gid, private_path);
@@ -340,19 +331,6 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
DEBUG(SSSDBG_OP_FAILURE, ("ccache creation failed.\n"));
return ret;
}
- } else {
- DEBUG(SSSDBG_MINOR_FAILURE,
- ("Saved ccache %s if of different type than ccache in "
- "configuration file, reusing the old ccache\n",
- kr->old_ccname));
-
- kr->cc_be = get_cc_be_ops_ccache(kr->old_ccname);
- if (kr->cc_be == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Cannot get operations on saved ccache %s\n",
- kr->old_ccname));
- return EINVAL;
- }
}
return EOK;
@@ -614,10 +592,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
goto done;
}
- /* The type of the ccache might change during the request if we
- * end up reusing an old ccache */
- kr->cc_be = krb5_ctx->cc_be;
-
ccache_file = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_CCACHE_FILE,
NULL);
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index d31925dae6187b3c839e32502fd349e4d64deb32..022dc9b7645f18d01a8a334371e178aa470d92a1 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -41,7 +41,6 @@ struct krb5child_req {
struct pam_data *pd;
struct krb5_ctx *krb5_ctx;
- struct sss_krb5_cc_be *cc_be;
const char *ccname;
const char *old_ccname;
const char *homedir;
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index de7ae0a8fe345c38f9458fb9642a5c1b83c906f5..dedb734fc397d3df3eb7717b19c56051fb2243bb 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -167,7 +167,6 @@ errno_t check_and_export_options(struct dp_option *opts,
const char *dummy;
char *use_fast_str;
char *fast_principal;
- enum sss_krb5_cc_type cc_be;
char *ccname;
tmp_ctx = talloc_new(NULL);
@@ -291,53 +290,30 @@ errno_t check_and_export_options(struct dp_option *opts,
}
}
- cc_be = sss_krb5_get_type(ccname);
- switch (cc_be) {
- case SSS_KRB5_TYPE_FILE:
+ if ((ccname[0] == '/') || (strncmp(ccname, "FILE:", 5) == 0)) {
DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n"));
/* warn if the file type (which is usally created in a sticky bit
* laden directory) does not have randomizing chracters */
sss_check_cc_template(ccname);
- krb5_ctx->cc_be = &file_cc;
- if (ccname[0] != '/') {
- /* FILE:/path/to/cc */
- break;
- }
-
- DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
+ if (ccname[0] == '/') {
+ /* /path/to/cc prepend FILE: */
+ DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
"missing an explicit type, but is an absolute "
"path specifier. Assuming FILE:\n"));
- ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname);
- if (!ccname) {
- ret = ENOMEM;
- goto done;
+ ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname);
+ if (!ccname) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, ccname);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
+ goto done;
+ }
}
-
- ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, ccname);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
- goto done;
- }
- break;
-
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type DIR\n"));
- krb5_ctx->cc_be = &dir_cc;
- break;
-
- case SSS_KRB5_TYPE_KEYRING:
- DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type KEYRING\n"));
- krb5_ctx->cc_be = &keyring_cc;
- break;
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- default:
- DEBUG(SSSDBG_OP_FAILURE, ("Unknown ccname database\n"));
- ret = EINVAL;
- goto done;
}
ret = EOK;
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index e56bd496e04a7a5c8776a34648aabe0f2d73a3b9..eac0d6b1f0c0fec4a107a7b830d8b0c927f4fe42 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -89,7 +89,6 @@ struct krb5_service {
struct fo_service;
struct deferred_auth_ctx;
struct renew_tgt_ctx;
-struct sss_krb5_cc_be;
enum krb5_config_type {
K5C_GENERIC,
@@ -127,7 +126,6 @@ struct krb5_ctx {
struct krb5_service *kpasswd_service;
int child_debug_fd;
- struct sss_krb5_cc_be *cc_be;
pcre *illegal_path_re;
struct deferred_auth_ctx *deferred_auth_ctx;
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 83e61e14ecc116b9556231c5d8a0f55b63260c77..d0ccd2d7e03bcabe07113b5abb43d9119b35321c 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1039,66 +1039,6 @@ done:
}
-/*======== ccache back end utilities ========*/
-struct sss_krb5_cc_be *
-get_cc_be_ops(enum sss_krb5_cc_type type)
-{
- struct sss_krb5_cc_be *be = NULL;
-
- switch (type) {
- case SSS_KRB5_TYPE_FILE:
- be = &file_cc;
- break;
-
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- be = &dir_cc;
- break;
-
- case SSS_KRB5_TYPE_KEYRING:
- be = &keyring_cc;
- break;
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- case SSS_KRB5_TYPE_UNKNOWN:
- be = NULL;
- break;
- }
-
- return be;
-}
-
-struct sss_krb5_cc_be *
-get_cc_be_ops_ccache(const char *ccache)
-{
- enum sss_krb5_cc_type type;
-
- type = sss_krb5_get_type(ccache);
- return get_cc_be_ops(type);
-}
-
-/*======== Operations on the FILE: back end ========*/
-
-struct sss_krb5_cc_be file_cc = {
- .type = SSS_KRB5_TYPE_FILE,
-};
-
-#ifdef HAVE_KRB5_CC_COLLECTION
-/*======== Operations on the DIR: back end ========*/
-
-struct sss_krb5_cc_be dir_cc = {
- .type = SSS_KRB5_TYPE_DIR,
-};
-
-
-/*======== Operations on the KEYRING: back end ========*/
-
-struct sss_krb5_cc_be keyring_cc = {
- .type = SSS_KRB5_TYPE_KEYRING,
-};
-
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
errno_t get_domain_or_subdomain(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx,
char *domain_name,
struct sss_domain_info **dom)
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 5f720335aab1ac6e493843ac197c5af881a9b998..e41309e765b58f7cd2567f1d13fea30d093fd344 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -42,19 +42,9 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
const char *user,
const char *upn);
-/* A ccache back end */
-struct sss_krb5_cc_be {
- enum sss_krb5_cc_type type;
-};
-
-extern struct sss_krb5_cc_be file_cc;
-
errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
-struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
-struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
-
char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
const char *template, bool file_mode,
bool case_sensitive, bool *private_path);
@@ -78,13 +68,6 @@ errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
-#ifdef HAVE_KRB5_CC_COLLECTION
-
-extern struct sss_krb5_cc_be dir_cc;
-extern struct sss_krb5_cc_be keyring_cc;
-
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
errno_t get_domain_or_subdomain(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx,
char *domain_name,
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 5ea30014f9c8f748e85506627b7f40d72b913b1b..c32ccc318e9826d598bb29a766ed1839fd9bf066 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -196,7 +196,6 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
const char *ccname, const char *ccname_template,
int timeout)
{
- enum sss_krb5_cc_type cc_be;
struct krb5child_req *kr;
struct passwd *pwd;
bool private = false;
@@ -262,28 +261,6 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
}
if (!kr->ccname) goto fail;
- cc_be = sss_krb5_get_type(kr->ccname);
- switch (cc_be) {
- case SSS_KRB5_TYPE_FILE:
- kr->krb5_ctx->cc_be = &file_cc;
- break;
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- kr->krb5_ctx->cc_be = &dir_cc;
- break;
-#endif /* HAVE_KRB5_CC_COLLECTION */
- default:
- if (tmpl[0] != '/') {
- DEBUG(SSSDBG_OP_FAILURE, ("Unkown ccname database\n"));
- ret = EINVAL;
- goto fail;
- }
- DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
- "missing an explicit type, but looks like an absolute "
- "path specifier. Assuming FILE:\n"));
- kr->krb5_ctx->cc_be = &file_cc;
- break;
- }
DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
kr->ccname, kr->uid, kr->gid));
--
1.8.3.1

View File

@ -0,0 +1,69 @@
From 0dbcc64a5cee58d5fffaaef923302d9c7a951a7d Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 30 Aug 2013 20:55:38 -0400
Subject: [PATCH 11/14] krb5: Remove unused function
Related:
https://fedorahosted.org/sssd/ticket/2061
---
src/util/sss_krb5.c | 30 ------------------------------
src/util/sss_krb5.h | 2 --
2 files changed, 32 deletions(-)
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 440edab8a4624b33b7d358e64ead93949fc3de88..d4fee42a0297d5bb46135669a5fc12857ea95936 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -921,36 +921,6 @@ sss_krb5_residual_by_type(const char *full_location,
}
const char *
-sss_krb5_cc_file_path(const char *full_location)
-{
- enum sss_krb5_cc_type cc_type;
- const char *residual;
-
- cc_type = sss_krb5_get_type(full_location);
- residual = sss_krb5_residual_by_type(full_location, cc_type);
-
- switch(cc_type) {
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_KEYRING:
-#endif /* HAVE_KRB5_CC_COLLECTION */
- case SSS_KRB5_TYPE_FILE:
- return residual;
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- /* DIR::/run/user/tkt_foo */
- if (residual[0] == ':') {
- ++residual;
- }
- return residual;
-#endif /* HAVE_KRB5_CC_COLLECTION */
- case SSS_KRB5_TYPE_UNKNOWN:
- break;
- }
-
- return NULL;
-}
-
-const char *
sss_krb5_residual_check_type(const char *full_location,
enum sss_krb5_cc_type expected_type)
{
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index aaf2a64882254ba173fb57c5dab47d246082392c..efde48b62170a142ebfca907013c3558ec47f428 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -154,8 +154,6 @@ sss_krb5_get_type(const char *full_location);
const char *
sss_krb5_residual_by_type(const char *full_location, enum sss_krb5_cc_type type);
const char *
-sss_krb5_cc_file_path(const char *full_location);
-const char *
sss_krb5_residual_check_type(const char *full_location,
enum sss_krb5_cc_type expected_type);
--
1.8.3.1

View File

@ -0,0 +1,97 @@
From 14050f35224360883e20ebd810d3eb40f39267cf Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Sat, 31 Aug 2013 14:21:22 -0400
Subject: [PATCH 12/14] krb5: Add file/dir path precheck
Add a precheck on the actual existence at all of the file/dir ccname
targeted (for FILE/DIR types), and bail early if nothing is available.
While testing I found out that without this check, the krb5_cc_resolve()
function we call as user to check old paths would try to create the
directory if it didn't exist.
With a ccname of DIR:/tmp/ccdir_1000 saved in the user entry this would
cause two undesirable side effects:
First it would actually create a directory with the old name, when it
should not.
Second, because for some reason the umask is set to 0127 in sssd_be, it
would create the directory with permission 600 (missing the 'x' traverse
bit on the directory. If the new ccache has the same name it would cause
the krb5_child process to fal to store the credential cache in it.
Related:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_auth.c | 1 +
src/providers/krb5/krb5_utils.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 1585f709655853827f2778010452a58657add5d0..7cfa3e943c15c0f515f3372079cee18dd7978c92 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -69,6 +69,7 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
realm, kr->upn);
switch (ret) {
case ERR_NOT_FOUND:
+ case ENOENT:
DEBUG(SSSDBG_TRACE_FUNC,
("Saved ccache %s doesn't exist.\n", old_ccache));
return ENOENT;
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index d0ccd2d7e03bcabe07113b5abb43d9119b35321c..bb933d7f722cbef90b73f4a721382165572c69b9 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -967,6 +967,30 @@ done:
return ret;
}
+static errno_t sss_low_level_path_check(const char *ccname)
+{
+ const char *filename;
+ struct stat buf;
+ int ret;
+
+ if (ccname[0] == '/') {
+ filename = ccname;
+ } else if (strncmp(ccname, "FILE:", 5) == 0) {
+ filename = ccname + 5;
+ } else if (strncmp(ccname, "DIR:", 4) == 0) {
+ filename = ccname + 4;
+ if (filename[0] == ':') filename += 1;
+ } else {
+ /* only FILE and DIR types need file checks so far, we ignore any
+ * other type */
+ return EOK;
+ }
+
+ ret = stat(filename, &buf);
+ if (ret == -1) return errno;
+ return EOK;
+}
+
errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
const char *realm, const char *principal)
{
@@ -980,6 +1004,16 @@ errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
krb5_error_code kerr;
errno_t ret;
+ /* first of all verify if the old ccache file/dir exists as we may be
+ * trying to verify if an old ccache exists at all. If no file/dir
+ * exists bail out immediately otherwise a following krb5_cc_resolve()
+ * call may actually create paths and files we do not want to have
+ * around */
+ ret = sss_low_level_path_check(ccname);
+ if (ret) {
+ return ret;
+ }
+
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
--
1.8.3.1

View File

@ -0,0 +1,582 @@
From a6a0d4edebccd3cf04f9813fc65185845626b5d4 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Mon, 2 Sep 2013 23:52:46 -0400
Subject: [PATCH 13/14] krb5_child: Simplify ccache creation
The containing ccache directory is precreated by the parent code,
so there is no special need to do so here for any type.
Also the special handling for the FILE ccache temporary file is not really
useful, because libkrb5 internally unlinks and then recreate the file, so
mkstemp cannot really prevent subtle races, it can only make sure the file is
unique at creation time.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
---
src/providers/krb5/krb5_child.c | 480 ++++++++--------------------------------
1 file changed, 90 insertions(+), 390 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 842b50e6e23cf9b00f51c0a01cfd960e4156ee21..4f56736de152d1443add8b69db261faf3b75529f 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -424,11 +424,7 @@ static krb5_error_code create_empty_cred(krb5_context ctx, krb5_principal princ,
done:
if (kerr != 0) {
- if (cred != NULL && cred->client != NULL) {
- krb5_free_principal(ctx, cred->client);
- }
-
- free(cred);
+ krb5_free_creds(ctx, cred);
} else {
*_cred = cred;
}
@@ -436,281 +432,38 @@ done:
return kerr;
}
-#ifdef HAVE_KRB5_CC_COLLECTION
-static bool need_switch_to_principal(krb5_context ctx, krb5_principal princ)
-{
- krb5_error_code kerr;
- krb5_ccache default_cc = NULL;
- krb5_principal default_princ = NULL;
- char *default_full_name = NULL;
- char *full_name = NULL;
- bool ret = false;
-
- kerr = krb5_cc_default(ctx, &default_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
- goto done;
- }
-
- kerr = krb5_cc_get_principal(ctx, default_cc, &default_princ);
- if (kerr == KRB5_FCC_NOFILE) {
- /* There is not any default cache. */
- ret = true;
- goto done;
- } else if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
- goto done;
- }
-
- kerr = krb5_unparse_name(ctx, default_princ, &default_full_name);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
- goto done;
- }
-
- kerr = krb5_unparse_name(ctx, princ, &full_name);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
- goto done;
- }
-
- DEBUG(SSSDBG_FUNC_DATA,
- ("Comparing default principal [%s] and new principal [%s].\n",
- default_full_name, full_name));
- if (0 == strcmp(default_full_name, full_name)) {
- ret = true;
- }
-
-done:
- if (default_cc != NULL) {
- kerr = krb5_cc_close(ctx, default_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
- }
-
- /* all functions can be safely called with NULL. */
- krb5_free_principal(ctx, default_princ);
- krb5_free_unparsed_name(ctx, default_full_name);
- krb5_free_unparsed_name(ctx, full_name);
-
- return ret;
-}
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
-static krb5_error_code
-store_creds_in_ccache(krb5_context ctx, krb5_principal princ,
- krb5_ccache cc, krb5_creds *creds)
-{
- krb5_error_code kerr;
- krb5_creds *l_cred;
- char *ccname;
-
- if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
- kerr = krb5_cc_get_full_name(ctx, cc, &ccname);
- if (kerr != 0) {
- DEBUG(SSSDBG_TRACE_ALL,
- ("Couldn't determine full name of ccache\n"));
- } else {
- DEBUG(SSSDBG_TRACE_ALL,
- ("Storing credentials in [%s]\n", ccname));
- krb5_free_string(ctx, ccname);
- }
- }
-
- kerr = krb5_cc_initialize(ctx, cc, princ);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
-
- if (creds == NULL) {
- kerr = create_empty_cred(ctx, princ, &l_cred);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
- } else {
- l_cred = creds;
- }
-
- kerr = krb5_cc_store_cred(ctx, cc, l_cred);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
-
-#ifdef HAVE_KRB5_CC_COLLECTION
- if (need_switch_to_principal(ctx, princ)) {
- kerr = krb5_cc_switch(ctx, cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
- }
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- kerr = krb5_cc_close(ctx, cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
-
-done:
- return kerr;
-}
-static krb5_error_code create_ccache_file(krb5_context ctx,
- krb5_principal princ,
- char *ccname, krb5_creds *creds)
+static errno_t handle_randomized(char *in)
{
- krb5_error_code kerr;
- krb5_ccache tmp_cc = NULL;
- char *cc_file_name;
- int fd = -1;
size_t ccname_len;
- char *dummy;
- char *tmp_ccname;
- TALLOC_CTX *tmp_ctx = NULL;
- mode_t old_umask;
+ char *ccname = NULL;
+ int ret;
+ int fd;
- DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
-
- if (strncmp(ccname, "FILE:", 5) == 0) {
- cc_file_name = ccname + 5;
+ /* We only treat the FILE type case in a special way due to the history
+ * of storing FILE type ccache in /tmp and associated security issues */
+ if (in[0] == '/') {
+ ccname = in;
+ } else if (strncmp(in, "FILE:", 5) == 0) {
+ ccname = in + 5;
} else {
- cc_file_name = ccname;
- }
-
- if (cc_file_name[0] != '/') {
- DEBUG(1, ("Ccache filename is not an absolute path.\n"));
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(tmp_ctx);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- dummy = strrchr(cc_file_name, '/');
- tmp_ccname = talloc_strndup(tmp_ctx, cc_file_name,
- (size_t) (dummy-cc_file_name));
- if (tmp_ccname == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- kerr = ENOMEM;
- goto done;
- }
- tmp_ccname = talloc_asprintf_append(tmp_ccname, "/.krb5cc_dummy_XXXXXX");
- if (tmp_ccname == NULL) {
- kerr = ENOMEM;
- goto done;
- }
-
- old_umask = umask(077);
- fd = mkstemp(tmp_ccname);
- umask(old_umask);
- if (fd == -1) {
- kerr = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
- goto done;
- }
-
- kerr = krb5_cc_resolve(ctx, tmp_ccname, &tmp_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- goto done;
- }
-
- kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
- if (fd != -1) {
- close(fd);
- fd = -1;
- }
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- goto done;
- }
-
-
- ccname_len = strlen(cc_file_name);
- if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len - 6), "XXXXXX") == 0) {
- fd = mkstemp(cc_file_name);
+ return EOK;
+ }
+
+ ccname_len = strlen(ccname);
+ if (ccname_len >= 6 && strcmp(ccname + (ccname_len - 6), "XXXXXX") == 0) {
+ /* NOTE: this call is only used to create a unique name, as later
+ * krb5_cc_initialize() will unlink and recreate the file.
+ * This is ok because this part of the code is called with
+ * privileges already dropped when handling user ccache, or the ccache
+ * is stored in a private directory. So we do not have huge issues if
+ * something races, we mostly care only about not accidentally use
+ * an existing name and thus failing in the process of saving the
+ * cache. Malicious races can only be avoided by libkrb5 itself. */
+ fd = mkstemp(ccname);
if (fd == -1) {
- kerr = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
- goto done;
- }
- }
-
- kerr = rename(tmp_ccname, cc_file_name);
- if (kerr == -1) {
- kerr = errno;
- DEBUG(1, ("rename failed [%d][%s].\n", kerr, strerror(kerr)));
- }
-
- DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", ccname));
-
-done:
- if (kerr != 0 && tmp_cc != NULL) {
- krb5_cc_destroy(ctx, tmp_cc);
- }
-
- if (fd != -1) {
- close(fd);
- }
-
- talloc_free(tmp_ctx);
- return kerr;
-}
-
-#ifdef HAVE_KRB5_CC_COLLECTION
-
-static errno_t
-create_ccdir(const char *dirname, uid_t uid, gid_t gid)
-{
- mode_t old_umask;
- struct stat statbuf;
- errno_t ret;
-
- old_umask = umask(0000);
- ret = mkdir(dirname, 0700);
- umask(old_umask);
- if (ret == -1) {
- /* Failing the mkdir is only OK if the directory already
- * exists AND it is owned by the same user and group and
- * has the correct permissions.
- */
- ret = errno;
- if (ret == EEXIST) {
- errno = 0;
- ret = stat(dirname, &statbuf);
- if (ret == -1) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("stat failed [%d]: %s\n", ret, strerror(ret)));
- return EIO;
- }
-
- if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("The directory %s is owned by %d/%d, expected %d/%d\n",
- dirname, statbuf.st_uid, statbuf.st_gid, uid, gid));
- return EACCES;
- }
-
- if ((statbuf.st_mode & ~S_IFMT) != 0700) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("The directory %s has wrong permissions %o, expected 0700\n",
- dirname, (statbuf.st_mode & ~S_IFMT)));
- return EACCES;
- }
- } else {
- DEBUG(SSSDBG_CRIT_FAILURE, ("mkdir [%s] failed [%d]: %s\n",
- dirname, ret, strerror(ret)));
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE, ("mkstemp(\"%s\") failed!\n", ccname));
return ret;
}
}
@@ -718,136 +471,79 @@ create_ccdir(const char *dirname, uid_t uid, gid_t gid)
return EOK;
}
-static krb5_error_code
-create_ccache_in_dir(uid_t uid, gid_t gid,
- krb5_context ctx,
- krb5_principal princ,
- char *ccname, krb5_creds *creds)
+/* NOTE: callers rely on 'name' being *changed* if it needs to be randomized,
+ * as they will then send the name back to the new name via the return call
+ * k5c_attach_ccname_msg(). Callers will send in a copy of the name if they
+ * do not care for changes. */
+static krb5_error_code create_ccache(char *ccname, krb5_creds *creds)
{
+ krb5_context kctx = NULL;
+ krb5_ccache kcc = NULL;
+ const char *type;
krb5_error_code kerr;
- krb5_ccache tmp_cc = NULL;
- const char *dirname;
-
- DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
-
- dirname = sss_krb5_residual_check_type(ccname, SSS_KRB5_TYPE_DIR);
- if (dirname == NULL) {
- return EIO;
+#ifdef HAVE_KRB5_CC_COLLECTION
+ krb5_ccache cckcc;
+ bool switch_to_cc = false;
+#endif
+
+ /* Set a restrictive umask, just in case we end up creating any file */
+ umask(077);
+
+ /* we create a new context here as the main process one may have been
+ * opened as root and contain possibly references (even open handles ?)
+ * to resources we do not have or do not want to have access to */
+ kerr = krb5_init_context(&kctx);
+ if (kerr) {
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+ return ERR_INTERNAL;
}
- if (dirname[0] == ':') {
- /* Cache name in the form of DIR::filepath represents a single
- * ccache in a collection that we are trying to reuse.
- * See src/lib/krb5/ccache/cc_dir.c in the MIT Kerberos tree.
- */
- kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
- } else if (dirname[0] == '/') {
- /* An absolute path denotes that krb5_child should create a new
- * ccache. We can afford to just call mkdir(dirname) because we
- * only want the last component to be created.
- */
+ kerr = handle_randomized(ccname);
+ if (kerr) goto done;
- kerr = create_ccdir(dirname, uid, gid);
- if (kerr) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Cannot create directory %s\n", dirname));
- goto done;
- }
+ kerr = krb5_cc_resolve(kctx, ccname, &kcc);
+ if (kerr) goto done;
- kerr = krb5_cc_set_default_name(ctx, ccname);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
+ type = krb5_cc_get_type(kctx, kcc);
+ DEBUG(SSSDBG_TRACE_ALL, ("Initializing ccache of type [%s]\n", type));
- kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
+#ifdef HAVE_KRB5_CC_COLLECTION
+ if (krb5_cc_support_switch(kctx, type)) {
+ kerr = krb5_cc_set_default_name(kctx, ccname);
+ if (kerr) goto done;
+
+ kerr = krb5_cc_cache_match(kctx, creds->client, &cckcc);
+ if (kerr == KRB5_CC_NOTFOUND) {
+ kerr = krb5_cc_new_unique(kctx, type, NULL, &cckcc);
+ switch_to_cc = true;
}
- } else {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("Wrong residual format for DIR in ccache %s\n", ccname));
- return EIO;
+ if (kerr) goto done;
+ krb5_cc_close(kctx, kcc);
+ kcc = cckcc;
}
+#endif
- kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
- goto done;
- }
-
-done:
- if (kerr != 0 && tmp_cc != NULL) {
- krb5_cc_destroy(ctx, tmp_cc);
- }
- return kerr;
-}
-
-static krb5_error_code
-create_ccache_keyring(krb5_context ctx,
- krb5_principal princ,
- char *ccname,
- krb5_creds *creds)
-{
- krb5_error_code kerr;
- krb5_ccache tmp_cc = NULL;
-
- DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
+ kerr = krb5_cc_initialize(kctx, kcc, creds->client);
+ if (kerr) goto done;
- kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- goto done;
- }
+ kerr = krb5_cc_store_cred(kctx, kcc, creds);
+ if (kerr) goto done;
- kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- goto done;
+#ifdef HAVE_KRB5_CC_COLLECTION
+ if (switch_to_cc) {
+ kerr = krb5_cc_switch(kctx, kcc);
+ if (kerr) goto done;
}
+#endif
done:
- if (kerr != 0 && tmp_cc != NULL) {
- krb5_cc_destroy(ctx, tmp_cc);
+ if (kcc) {
+ /* FIXME: should we krb5_cc_destroy in case of error ? */
+ krb5_cc_close(kctx, kcc);
}
-
return kerr;
}
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
-static krb5_error_code
-create_ccache(uid_t uid, gid_t gid, krb5_context ctx,
- krb5_principal princ, char *ccname, krb5_creds *creds)
-{
- enum sss_krb5_cc_type cctype;
-
- cctype = sss_krb5_get_type(ccname);
- switch (cctype) {
- case SSS_KRB5_TYPE_FILE:
- return create_ccache_file(ctx, princ, ccname, creds);
-
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- return create_ccache_in_dir(uid, gid, ctx, princ, ccname, creds);
-
- case SSS_KRB5_TYPE_KEYRING:
- return create_ccache_keyring(ctx, princ, ccname, creds);
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- default:
- DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n"));
- return EINVAL;
- }
-
- return EINVAL; /* Should never get here */
-}
-
static errno_t pack_response_packet(TALLOC_CTX *mem_ctx, errno_t error,
struct response_data *resp_list,
uint8_t **_buf, size_t *_len)
@@ -1176,7 +872,7 @@ static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx,
}
/* Use the updated principal in the creds in case canonicalized */
- kerr = create_ccache_file(ctx, creds.client, ccname, &creds);
+ kerr = create_ccache(ccname, &creds);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
@@ -1255,8 +951,7 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
}
/* Use the updated principal in the creds in case canonicalized */
- kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
- principal, cc_name, kr->creds);
+ kerr = create_ccache(cc_name, kr->creds);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
@@ -1647,18 +1342,23 @@ done:
static errno_t create_empty_ccache(struct krb5_req *kr)
{
+ krb5_creds *creds = NULL;
krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
- kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
- kr->princ, kr->ccname, NULL);
+ kerr = create_empty_cred(kr->ctx, kr->princ, &creds);
+ if (kerr == 0) {
+ kerr = create_ccache(kr->ccname, creds);
+ }
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
} else {
kerr = k5c_attach_ccname_msg(kr);
}
+ krb5_free_creds(kr->ctx, creds);
+
return map_krb5_error(kerr);
}
--
1.8.3.1

View File

@ -0,0 +1,127 @@
From 077fa994f62641a13665b6a07d38b3d5a903dcdc Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Tue, 3 Sep 2013 20:57:58 -0400
Subject: [PATCH 14/14] krb5: Remove unused helper functions
these functions are not needed anymore.
Related:
https://fedorahosted.org/sssd/ticket/2061
---
src/util/sss_krb5.c | 80 -----------------------------------------------------
src/util/sss_krb5.h | 8 ------
2 files changed, 88 deletions(-)
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index d4fee42a0297d5bb46135669a5fc12857ea95936..f8a7e6f9be15c7b2dfee9906af914533bd8ac4cd 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -854,86 +854,6 @@ sss_krb5_free_keytab_entry_contents(krb5_context context,
}
#endif
-#define SSS_KRB5_FILE "FILE:"
-#define SSS_KRB5_DIR "DIR:"
-#define SSS_KRB5_KEYRING "KEYRING:"
-
-enum sss_krb5_cc_type
-sss_krb5_get_type(const char *full_location)
-{
- if (!full_location) {
- return SSS_KRB5_TYPE_UNKNOWN;
- }
-
- if (strncmp(full_location, SSS_KRB5_FILE,
- sizeof(SSS_KRB5_FILE)-1) == 0) {
- return SSS_KRB5_TYPE_FILE;
- }
-#ifdef HAVE_KRB5_CC_COLLECTION
- else if (strncmp(full_location, SSS_KRB5_DIR,
- sizeof(SSS_KRB5_DIR)-1) == 0) {
- return SSS_KRB5_TYPE_DIR;
- }
- else if (strncmp(full_location, SSS_KRB5_KEYRING,
- sizeof(SSS_KRB5_KEYRING)-1) == 0) {
- return SSS_KRB5_TYPE_KEYRING;
- }
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- else if (full_location[0] == '/') {
- return SSS_KRB5_TYPE_FILE;
- }
-
- return SSS_KRB5_TYPE_UNKNOWN;
-}
-
-const char *
-sss_krb5_residual_by_type(const char *full_location,
- enum sss_krb5_cc_type type)
-{
- size_t offset;
-
- if (full_location == NULL) return NULL;
-
- switch (type) {
- case SSS_KRB5_TYPE_FILE:
- if (full_location[0] == '/') {
- offset = 0;
- } else {
- offset = sizeof(SSS_KRB5_FILE)-1;
- }
- break;
-#ifdef HAVE_KRB5_CC_COLLECTION
- case SSS_KRB5_TYPE_DIR:
- offset = sizeof(SSS_KRB5_DIR)-1;
- break;
-
- case SSS_KRB5_TYPE_KEYRING:
- offset = sizeof(SSS_KRB5_KEYRING)-1;
- break;
-#endif /* HAVE_KRB5_CC_COLLECTION */
-
- default:
- return NULL;
- }
-
- return full_location + offset;
-}
-
-const char *
-sss_krb5_residual_check_type(const char *full_location,
- enum sss_krb5_cc_type expected_type)
-{
- enum sss_krb5_cc_type type;
-
- type = sss_krb5_get_type(full_location);
- if (type != expected_type) {
- DEBUG(SSSDBG_OP_FAILURE, ("Unexpected ccache type\n"));
- return NULL;
- }
-
- return sss_krb5_residual_by_type(full_location, type);
-}
#ifdef HAVE_KRB5_SET_TRACE_CALLBACK
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index efde48b62170a142ebfca907013c3558ec47f428..db47e0a6b61fc706cdadc74ad1d4c1e9e7ef3589 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -149,14 +149,6 @@ enum sss_krb5_cc_type {
SSS_KRB5_TYPE_UNKNOWN
};
-enum sss_krb5_cc_type
-sss_krb5_get_type(const char *full_location);
-const char *
-sss_krb5_residual_by_type(const char *full_location, enum sss_krb5_cc_type type);
-const char *
-sss_krb5_residual_check_type(const char *full_location,
- enum sss_krb5_cc_type expected_type);
-
/* === Compatibility routines for the Heimdal Kerberos implementation === */
void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
--
1.8.3.1

View File

@ -8,7 +8,7 @@
Name: sssd
Version: 1.11.0
Release: 1%{?dist}
Release: 2%{?dist}
Group: Applications/System
Summary: System Security Services Daemon
License: GPLv3+
@ -17,6 +17,20 @@ Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
### Patches ###
Patch0001: 0001-krb5-Add-calls-to-change-and-restore-credentials.patch
Patch0002: 0002-krb5-Add-helper-to-destroy-ccache-as-user.patch
Patch0003: 0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch
Patch0004: 0004-krb5-Replace-type-specific-ccache-principal-check.patch
Patch0005: 0005-krb5-Move-determination-of-user-being-active.patch
Patch0006: 0006-krb5-move-template-check-to-initializzation.patch
Patch0007: 0007-krb5-Make-check_for_valid_tgt-static.patch
Patch0008: 0008-krb5-Use-new-function-to-validate-ccaches.patch
Patch0009: 0009-krb5-Unify-function-to-create-ccache-files.patch
Patch0010: 0010-krb5-Remove-unused-ccache-backend-infrastructure.patch
Patch0011: 0011-krb5-Remove-unused-function.patch
Patch0012: 0012-krb5-Add-file-dir-path-precheck.patch
Patch0013: 0013-krb5_child-Simplify-ccache-creation.patch
Patch0014: 0014-krb5-Remove-unused-helper-functions.patch
### Dependencies ###
Requires: sssd-common = %{version}-%{release}
@ -676,6 +690,10 @@ fi
%postun -n libsss_idmap -p /sbin/ldconfig
%changelog
* Wed Aug 28 2013 Jakub Hrozek <jhrozek@redhat.com> - 1.11.0-2
- Backport simplification of ccache management from 1.11.1
- Resolves: rhbz#1010553 - sssd setting KRB5CCNAME=(null) on login
* Wed Aug 28 2013 Jakub Hrozek <jhrozek@redhat.com> - 1.11.0-1
- New upstream release 1.11.0
- https://fedorahosted.org/sssd/wiki/Releases/Notes-1.11.0