From 8d72fcd9009baa7e1063415b20bc7784ca6d753f Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 23 Sep 2013 12:23:42 +0200 Subject: [PATCH] Backport simplification of ccache management from 1.11.1 - Resolves: rhbz#1010553 - sssd setting KRB5CCNAME=(null) on login --- ...ls-to-change-and-restore-credentials.patch | 168 +++++ ...Add-helper-to-destroy-ccache-as-user.patch | 154 +++++ ...rb5_cc_destroy-to-remove-old-ccaches.patch | 279 +++++++++ ...type-specific-ccache-principal-check.patch | 357 +++++++++++ ...e-determination-of-user-being-active.patch | 220 +++++++ ...ve-template-check-to-initializzation.patch | 160 +++++ ...krb5-Make-check_for_valid_tgt-static.patch | 201 ++++++ ...Use-new-function-to-validate-ccaches.patch | 568 +++++++++++++++++ ...nify-function-to-create-ccache-files.patch | 348 +++++++++++ ...unused-ccache-backend-infrastructure.patch | 337 ++++++++++ 0011-krb5-Remove-unused-function.patch | 69 +++ 0012-krb5-Add-file-dir-path-precheck.patch | 97 +++ ...-krb5_child-Simplify-ccache-creation.patch | 582 ++++++++++++++++++ ...-krb5-Remove-unused-helper-functions.patch | 127 ++++ sssd.spec | 20 +- 15 files changed, 3686 insertions(+), 1 deletion(-) create mode 100644 0001-krb5-Add-calls-to-change-and-restore-credentials.patch create mode 100644 0002-krb5-Add-helper-to-destroy-ccache-as-user.patch create mode 100644 0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch create mode 100644 0004-krb5-Replace-type-specific-ccache-principal-check.patch create mode 100644 0005-krb5-Move-determination-of-user-being-active.patch create mode 100644 0006-krb5-move-template-check-to-initializzation.patch create mode 100644 0007-krb5-Make-check_for_valid_tgt-static.patch create mode 100644 0008-krb5-Use-new-function-to-validate-ccaches.patch create mode 100644 0009-krb5-Unify-function-to-create-ccache-files.patch create mode 100644 0010-krb5-Remove-unused-ccache-backend-infrastructure.patch create mode 100644 0011-krb5-Remove-unused-function.patch create mode 100644 0012-krb5-Add-file-dir-path-precheck.patch create mode 100644 0013-krb5_child-Simplify-ccache-creation.patch create mode 100644 0014-krb5-Remove-unused-helper-functions.patch diff --git a/0001-krb5-Add-calls-to-change-and-restore-credentials.patch b/0001-krb5-Add-calls-to-change-and-restore-credentials.patch new file mode 100644 index 0000000..e377e55 --- /dev/null +++ b/0001-krb5-Add-calls-to-change-and-restore-credentials.patch @@ -0,0 +1,168 @@ +From 0371fbcf60d4dd8e25b9bb0a83029c812b66f3d6 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch b/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch new file mode 100644 index 0000000..6c4c8b5 --- /dev/null +++ b/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch @@ -0,0 +1,154 @@ +From 04c49a183f49c28f9ef900bdbc4eb30f23278e17 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch b/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch new file mode 100644 index 0000000..d18f7c2 --- /dev/null +++ b/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch @@ -0,0 +1,279 @@ +From a70e88f62e8ba48c5042b881f20ed6586cb135a8 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0004-krb5-Replace-type-specific-ccache-principal-check.patch b/0004-krb5-Replace-type-specific-ccache-principal-check.patch new file mode 100644 index 0000000..c47eebd --- /dev/null +++ b/0004-krb5-Replace-type-specific-ccache-principal-check.patch @@ -0,0 +1,357 @@ +From 1536e39c191a013bc50bb6fd4b8eaef11cf0d436 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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:::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 + diff --git a/0005-krb5-Move-determination-of-user-being-active.patch b/0005-krb5-Move-determination-of-user-being-active.patch new file mode 100644 index 0000000..8172582 --- /dev/null +++ b/0005-krb5-Move-determination-of-user-being-active.patch @@ -0,0 +1,220 @@ +From bfd32c9e8f302d7722838a68572c6801f5640657 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0006-krb5-move-template-check-to-initializzation.patch b/0006-krb5-move-template-check-to-initializzation.patch new file mode 100644 index 0000000..63b350f --- /dev/null +++ b/0006-krb5-move-template-check-to-initializzation.patch @@ -0,0 +1,160 @@ +From 5dc3b01fd9b2fa244e7c2820ce04602c9f059370 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0007-krb5-Make-check_for_valid_tgt-static.patch b/0007-krb5-Make-check_for_valid_tgt-static.patch new file mode 100644 index 0000000..377cfb3 --- /dev/null +++ b/0007-krb5-Make-check_for_valid_tgt-static.patch @@ -0,0 +1,201 @@ +From c121e65ed592bf3611053ee38032fd33c8d1b285 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0008-krb5-Use-new-function-to-validate-ccaches.patch b/0008-krb5-Use-new-function-to-validate-ccaches.patch new file mode 100644 index 0000000..9274577 --- /dev/null +++ b/0008-krb5-Use-new-function-to-validate-ccaches.patch @@ -0,0 +1,568 @@ +From 84ce563e3f430eec1225a6f8493eb0a6c9a3013a Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0009-krb5-Unify-function-to-create-ccache-files.patch b/0009-krb5-Unify-function-to-create-ccache-files.patch new file mode 100644 index 0000000..00797d2 --- /dev/null +++ b/0009-krb5-Unify-function-to-create-ccache-files.patch @@ -0,0 +1,348 @@ +From 1c022b3556f442f57326c4a3f250128b1bd232ae Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch b/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch new file mode 100644 index 0000000..93ccba0 --- /dev/null +++ b/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch @@ -0,0 +1,337 @@ +From d20a5a74666413cadbf64c02eb656a5a3b4bb1de Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0011-krb5-Remove-unused-function.patch b/0011-krb5-Remove-unused-function.patch new file mode 100644 index 0000000..d5019ea --- /dev/null +++ b/0011-krb5-Remove-unused-function.patch @@ -0,0 +1,69 @@ +From 0dbcc64a5cee58d5fffaaef923302d9c7a951a7d Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0012-krb5-Add-file-dir-path-precheck.patch b/0012-krb5-Add-file-dir-path-precheck.patch new file mode 100644 index 0000000..f4c5a5c --- /dev/null +++ b/0012-krb5-Add-file-dir-path-precheck.patch @@ -0,0 +1,97 @@ +From 14050f35224360883e20ebd810d3eb40f39267cf Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0013-krb5_child-Simplify-ccache-creation.patch b/0013-krb5_child-Simplify-ccache-creation.patch new file mode 100644 index 0000000..ab4c6f8 --- /dev/null +++ b/0013-krb5_child-Simplify-ccache-creation.patch @@ -0,0 +1,582 @@ +From a6a0d4edebccd3cf04f9813fc65185845626b5d4 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/0014-krb5-Remove-unused-helper-functions.patch b/0014-krb5-Remove-unused-helper-functions.patch new file mode 100644 index 0000000..bbfec9e --- /dev/null +++ b/0014-krb5-Remove-unused-helper-functions.patch @@ -0,0 +1,127 @@ +From 077fa994f62641a13665b6a07d38b3d5a903dcdc Mon Sep 17 00:00:00 2001 +From: Simo Sorce +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 + diff --git a/sssd.spec b/sssd.spec index e76a9f5..82b306e 100644 --- a/sssd.spec +++ b/sssd.spec @@ -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 - 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 - 1.11.0-1 - New upstream release 1.11.0 - https://fedorahosted.org/sssd/wiki/Releases/Notes-1.11.0