>From e085431a60a1ef31898c2c9277905d21f70c537a Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 5 Jun 2012 23:41:12 +0200 Subject: [PATCH 09/11] Add support for storing credential caches in the DIR: back end https://fedorahosted.org/sssd/ticket/974 --- src/man/sssd-krb5.5.xml | 10 +- src/providers/krb5/krb5_child.c | 164 +++++++++++++++++++++----- src/providers/krb5/krb5_common.c | 34 +++++- src/providers/krb5/krb5_utils.c | 239 +++++++++++++++++++++++++++++++++++++- src/providers/krb5/krb5_utils.h | 4 + src/tests/krb5_child-test.c | 46 ++++++-- src/tests/krb5_utils-tests.c | 46 ++++++++ src/util/sss_krb5.c | 21 +--- src/util/sss_krb5.h | 3 +- 9 files changed, 495 insertions(+), 72 deletions(-) diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml index 247337a90a80b078d0395b27a02e5ea2c72a5ce8..1baee36e9b0ade76de2990fd4f06bc655b5ce06c 100644 --- a/src/man/sssd-krb5.5.xml +++ b/src/man/sssd-krb5.5.xml @@ -157,10 +157,12 @@ krb5_ccname_template (string) - Location of the user's credential cache. Currently - only file based credential caches are supported. In - the template the following sequences are - substituted: + Location of the user's credential cache. Two credential + cache types are currently supported - FILE + and DIR. The cache can either be specified + as TYPE:RESIDUAL, or an absolute + path, which implies the FILE type. In the + template the following sequences are substituted: %u diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index b6c456efb5f1776b40bd9940dddbffe503a009b6..93844fab9925ef67181105cb73c452f5796f0272 100644 --- a/src/providers/krb5/krb5_child.c +++ b/src/providers/krb5/krb5_child.c @@ -221,6 +221,51 @@ done: return kerr; } +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; + + kerr = krb5_cc_initialize(ctx, cc, princ); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + + if (creds == NULL) { + kerr = create_empty_cred(ctx, princ, &l_cred); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + } else { + l_cred = creds; + } + + kerr = krb5_cc_store_cred(ctx, cc, l_cred); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + + kerr = krb5_cc_switch(ctx, cc); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + + kerr = krb5_cc_close(ctx, cc); + if (kerr != 0) { + KRB5_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) @@ -232,7 +277,6 @@ static krb5_error_code create_ccache_file(krb5_context ctx, size_t ccname_len; char *dummy; char *tmp_ccname; - krb5_creds *l_cred; TALLOC_CTX *tmp_ctx = NULL; mode_t old_umask; @@ -285,38 +329,16 @@ static krb5_error_code create_ccache_file(krb5_context ctx, goto done; } - kerr = krb5_cc_initialize(ctx, tmp_cc, princ); - if (kerr != 0) { - KRB5_DEBUG(1, kerr); - goto done; - } + kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds); if (fd != -1) { close(fd); fd = -1; } - - if (creds == NULL) { - kerr = create_empty_cred(ctx, princ, &l_cred); - if (kerr != 0) { - KRB5_DEBUG(1, kerr); - goto done; - } - } else { - l_cred = creds; - } - - kerr = krb5_cc_store_cred(ctx, tmp_cc, l_cred); if (kerr != 0) { KRB5_DEBUG(1, kerr); goto done; } - kerr = krb5_cc_close(ctx, tmp_cc); - if (kerr != 0) { - KRB5_DEBUG(1, kerr); - goto done; - } - tmp_cc = NULL; ccname_len = strlen(cc_file_name); if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len-6), "XXXXXX")==0 ) { @@ -337,18 +359,98 @@ static krb5_error_code create_ccache_file(krb5_context ctx, 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); } - if (kerr != 0 && tmp_cc != NULL) { - krb5_cc_destroy(ctx, tmp_cc); - } talloc_free(tmp_ctx); + return kerr; +} + +static krb5_error_code +create_ccache_in_dir(krb5_context ctx, + krb5_principal princ, + char *ccname, krb5_creds *creds) +{ + 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; + } + + 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_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + } else if (dirname[0] == '/') { + /* An absolute path denotes that krb5_child should create a new + * ccache + */ + kerr = krb5_cc_set_default_name(ctx, ccname); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc); + if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr); + goto done; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Wrong residual format for DIR in ccache %s\n", ccname)); + return EIO; + } + + kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds); + if (kerr != 0) { + KRB5_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(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); + case SSS_KRB5_TYPE_DIR: + return create_ccache_in_dir(ctx, princ, ccname, creds); + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n")); + return EINVAL; + } + + return EINVAL; /* Should never get here */ +} + static errno_t pack_response_packet(struct response *resp, int status, struct pam_data *pd) { @@ -728,9 +830,9 @@ 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_file(kr->ctx, - kr->creds ? kr->creds->client : kr->princ, - kr->ccname, kr->creds); + kerr = create_ccache(kr->ctx, + kr->creds ? kr->creds->client : kr->princ, + kr->ccname, kr->creds); if (kerr != 0) { KRB5_DEBUG(1, kerr); goto done; @@ -1141,7 +1243,7 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr) DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n")); - ret = create_ccache_file(kr->ctx, kr->princ, kr->ccname, NULL); + ret = create_ccache(kr->ctx, kr->princ, kr->ccname, NULL); if (ret != 0) { KRB5_DEBUG(1, ret); pam_status = PAM_SYSTEM_ERR; diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c index 91816662b8a694fbf31933eae05db2793e3a9dbc..f4033d29597661d1a9b4ff66e0ee02b4bf649f21 100644 --- a/src/providers/krb5/krb5_common.c +++ b/src/providers/krb5/krb5_common.c @@ -182,13 +182,37 @@ errno_t check_and_export_options(struct dp_option *opts, } cc_be = sss_krb5_get_type(dummy); - if (cc_be != SSS_KRB5_TYPE_FILE || dummy[0] != '/') { - DEBUG(SSSDBG_CONF_SETTINGS, - ("Currently only file based credential caches are supported " - "and krb5ccname_template must start with '/' or 'FILE:'\n")); + switch (cc_be) { + case SSS_KRB5_TYPE_FILE: + DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n")); + krb5_ctx->cc_be = &file_cc; + if (dummy[0] != '/') { + /* FILE:/path/to/cc */ + break; + } + + DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was " + "missing an explicit type, but is an absolute " + "path specifier. Assuming FILE:\n")); + + dummy = talloc_asprintf(opts, "FILE:%s", dummy); + if (!dummy) return ENOMEM; + + ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, dummy); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n")); + return ret; + } + break; + case SSS_KRB5_TYPE_DIR: + DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type DIR\n")); + krb5_ctx->cc_be = &dir_cc; + break; + default: + DEBUG(SSSDBG_OP_FAILURE, ("Unkown ccname database\n")); return EINVAL; + break; } - krb5_ctx->cc_be = &file_cc; return EOK; } diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c index 333d4b5f616d7d89094adf50259bb4667ae325f0..e32703d8ae37d07241397ae2ad22c5641f0d0017 100644 --- a/src/providers/krb5/krb5_utils.c +++ b/src/providers/krb5/krb5_utils.c @@ -23,6 +23,7 @@ */ #include #include +#include #include "providers/krb5/krb5_utils.h" #include "providers/krb5/krb5_auth.h" @@ -525,6 +526,9 @@ get_cc_be_ops(enum sss_krb5_cc_type type) case SSS_KRB5_TYPE_FILE: be = &file_cc; break; + case SSS_KRB5_TYPE_DIR: + be = &dir_cc; + break; case SSS_KRB5_TYPE_UNKNOWN: be = NULL; break; @@ -616,6 +620,9 @@ cc_residual_is_used(uid_t uid, const char *ccname, } switch (type) { + case SSS_KRB5_TYPE_DIR: + ret = S_ISDIR(stat_buf.st_mode); + break; case SSS_KRB5_TYPE_FILE: ret = S_ISREG(stat_buf.st_mode); break; @@ -658,6 +665,9 @@ cc_file_check_existing(const char *location, uid_t uid, bool active; bool valid; const char *filename; + krb5_ccache ccache = NULL; + krb5_context context = NULL; + krb5_error_code kerr; filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE); if (!filename) { @@ -676,11 +686,26 @@ cc_file_check_existing(const char *location, uid_t uid, return ret; } - ret = check_for_valid_tgt(location, realm, princ, &valid); - if (ret != EOK) { + kerr = krb5_init_context(&context); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to init kerberos context\n")); + return EIO; + } + + kerr = krb5_cc_resolve(context, location, &ccache); + if (kerr != 0) { + krb5_free_context(context); + DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n")); + return EIO; + } + + kerr = check_for_valid_tgt(context, ccache, realm, princ, &valid); + krb5_free_context(context); + krb5_cc_close(context, ccache); + if (kerr != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not check if ccache contains a valid principal\n")); - return ret; + return EIO; } *_active = active; @@ -732,3 +757,211 @@ struct sss_krb5_cc_be file_cc = { .ccache_for_princ = cc_file_cache_for_princ, .remove = cc_file_remove, }; + +/*======== 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 *dirname; + + dirname = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR); + if (dirname == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Bad residual type\n")); + return EINVAL; + } + + return create_ccache_dir(dirname, illegal_re, uid, gid, private_path); +} + +static krb5_error_code +get_ccache_for_princ(krb5_context context, const char *location, + const char *princ, krb5_ccache *_ccache) +{ + krb5_error_code krberr; + krb5_principal client_principal = NULL; + + krberr = krb5_cc_set_default_name(context, location); + if (krberr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_resolve failed.\n")); + return krberr; + } + + krberr = krb5_parse_name(context, princ, &client_principal); + if (krberr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_parse_name failed.\n")); + return krberr; + } + + krberr = krb5_cc_cache_match(context, client_principal, _ccache); + krb5_free_principal(context, client_principal); + return krberr; +} + +errno_t +cc_dir_check_existing(const char *location, uid_t uid, + const char *realm, const char *princ, + bool *_active, bool *_valid) +{ + bool active = false; + bool valid = false; + krb5_ccache ccache = NULL; + krb5_context context = NULL; + krb5_error_code krberr; + enum sss_krb5_cc_type type; + const char *filename; + const char *dir; + char *tmp; + errno_t ret; + + 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 = talloc_strdup(NULL, filename); + if (!tmp) return ENOMEM; + + dir = dirname(tmp); + if (!dir) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot base get directory of %s\n", location)); + return EINVAL; + } + + ret = cc_residual_is_used(uid, dir, SSS_KRB5_TYPE_DIR, &active); + talloc_free(tmp); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not check if ccache is active\n")); + return ret; + } + + 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) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Could not check if ccache contains a valid principal\n")); + ret = EIO; + goto done; + } + + ret = EOK; +done: + if (ccache) krb5_cc_close(context, ccache); + krb5_free_context(context); + *_active = active; + *_valid = valid; + 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; + krb5_ccache ccache = NULL; + char *name; + const char *ccname; + + 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 = get_ccache_for_princ(context, location, princ, &ccache); + if (krberr) { + DEBUG(SSSDBG_TRACE_FUNC, ("No principal for %s in %s\n", + princ, location)); + krb5_free_context(context); + return NULL; + } + + krberr = krb5_cc_get_full_name(context, ccache, &name); + if (ccache) krb5_cc_close(context, ccache); + krb5_free_context(context); + if (krberr) { + DEBUG(SSSDBG_TRACE_FUNC, ("Could not get full name of ccache\n")); + return NULL; + } + + return talloc_strdup(mem_ctx, 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 +}; diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h index 87bba2bae403b1271f45a7cea685a9bcf02207f8..684c520151831eb7fbe619a1b14be38a6092e56a 100644 --- a/src/providers/krb5/krb5_utils.h +++ b/src/providers/krb5/krb5_utils.h @@ -53,10 +53,14 @@ struct sss_krb5_cc_be { }; struct sss_krb5_cc_be file_cc; +struct sss_krb5_cc_be dir_cc; errno_t cc_file_create(const char *filename, pcre *illegal_re, uid_t uid, gid_t gid, bool private_path); +errno_t cc_dir_create(const char *location, 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); diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c index 64a0289d58470b66be18d17ba04740a716e91a37..59172384a052152fc302161ee293fb4ad3fe4927 100644 --- a/src/tests/krb5_child-test.c +++ b/src/tests/krb5_child-test.c @@ -40,6 +40,7 @@ extern struct dp_option default_krb5_opts[]; extern struct sss_krb5_cc_be file_cc; +extern struct sss_krb5_cc_be dir_cc; static krb5_context krb5_error_ctx; #define KRB5_DEBUG(level, krb5_error) do { \ @@ -119,8 +120,6 @@ create_dummy_krb5_ctx(TALLOC_CTX *mem_ctx, const char *realm) krb5_ctx = talloc_zero(mem_ctx, struct krb5_ctx); if (!krb5_ctx) return NULL; - krb5_ctx->cc_be = &file_cc; - krb5_ctx->illegal_path_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0, &errval, &errstr, &errpos, NULL); if (krb5_ctx->illegal_path_re == NULL) { @@ -202,10 +201,12 @@ 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; errno_t ret; + const char *tmpl; /* The top level child request */ kr = talloc_zero(mem_ctx, struct krb5child_req); @@ -237,6 +238,9 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user, ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL, ccname_template); if (ret != EOK) goto fail; + tmpl = ccname_template; + } else { + tmpl = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL); } if (timeout) { @@ -252,18 +256,42 @@ 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); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n")); - } } else { kr->ccname = talloc_strdup(kr, ccname); } 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; + case SSS_KRB5_TYPE_DIR: + kr->krb5_ctx->cc_be = &dir_cc; + break; + 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)); + + ret = kr->krb5_ctx->cc_be->create(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; + } + return kr; fail: diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c index 4a572488f0dfc3e8bae59813d646ee0791b1f428..4a4b75df21e0b2a1b6ab3528d045a5cfbc792f18 100644 --- a/src/tests/krb5_utils-tests.c +++ b/src/tests/krb5_utils-tests.c @@ -357,6 +357,51 @@ START_TEST(test_illegal_patterns) } END_TEST +START_TEST(test_cc_dir_create) +{ + char *residual; + char *dirname; + char *cwd; + uid_t uid = getuid(); + gid_t gid = getgid(); + pcre *illegal_re; + errno_t ret; + const char *errstr; + int errval; + int errpos; + + illegal_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0, + &errval, &errstr, &errpos, NULL); + fail_unless(illegal_re != NULL, "Invalid Regular Expression pattern at " + " position %d. (Error: %d [%s])\n", + errpos, errval, errstr); + + cwd = getcwd(NULL, 0); + fail_unless(cwd != NULL, "getcwd failed."); + + residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s/priv_ccdir", + cwd, TESTS_PATH); + 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"); + dirname = strchr(residual, ':') + 1; + ret = rmdir(dirname); + fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname); + talloc_free(residual); + + dirname = talloc_asprintf(tmp_ctx, "DIR:%s/%s/priv_ccdir2/", + cwd, TESTS_PATH); + 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"); + dirname = strchr(residual, ':') + 1; + ret = rmdir(dirname); + fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname); + talloc_free(residual); + free(cwd); +} +END_TEST + void setup_talloc_context(void) { int ret; @@ -645,6 +690,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); + tcase_add_test (tc_create_dir, test_cc_dir_create); 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); diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c index 5bc1140d0778882aa001a4a4504ddca42a63a4f8..8a6bfe2dc471e346b94069b2f7c04a671b8f4d37 100644 --- a/src/util/sss_krb5.c +++ b/src/util/sss_krb5.c @@ -604,11 +604,10 @@ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name) } -krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm, +krb5_error_code check_for_valid_tgt(krb5_context context, + krb5_ccache ccache, const char *realm, const char *client_princ_str, bool *result) { - krb5_context context = NULL; - krb5_ccache ccache = NULL; krb5_error_code krberr; TALLOC_CTX *tmp_ctx = NULL; krb5_creds mcred; @@ -625,18 +624,6 @@ krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm, return ENOMEM; } - krberr = krb5_init_context(&context); - if (krberr) { - DEBUG(1, ("Failed to init kerberos context\n")); - goto done; - } - - krberr = krb5_cc_resolve(context, ccname, &ccache); - if (krberr != 0) { - DEBUG(1, ("krb5_cc_resolve failed.\n")); - goto done; - } - server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm); if (server_name == NULL) { DEBUG(1, ("talloc_asprintf failed.\n")); @@ -685,10 +672,6 @@ done: if (server_principal != NULL) { krb5_free_principal(context, server_principal); } - if (ccache != NULL) { - krb5_cc_close(context, ccache); - } - if (context != NULL) krb5_free_context(context); talloc_free(tmp_ctx); return krberr; } diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h index bba2a7eda38b2da9fa3d875b327026de7cbe50cf..89ec00021f09333e94b6fbf1b0bcc1394f9523df 100644 --- a/src/util/sss_krb5.h +++ b/src/util/sss_krb5.h @@ -55,7 +55,8 @@ 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(const char *ccname, const char *realm, +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(const char *principal, -- 1.7.10.2