From 9a3ba9ca00e73adc3fb17ce8afa532076768023b Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 5 Jun 2012 23:41:12 +0200 Subject: Add support for storing credential caches in the DIR: back end https://fedorahosted.org/sssd/ticket/974 --- src/providers/krb5/krb5_child.c | 228 +++++++++++++++++++++++++---- src/providers/krb5/krb5_common.c | 34 ++++- src/providers/krb5/krb5_opts.h | 4 +- src/providers/krb5/krb5_utils.c | 307 ++++++++++++++++++++++++++++++++++----- src/providers/krb5/krb5_utils.h | 7 + 5 files changed, 510 insertions(+), 70 deletions(-) (limited to 'src/providers') diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index 195c431af..6b8722a8a 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 ) { @@ -338,16 +360,161 @@ 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); } + + talloc_free(tmp_ctx); + return kerr; +} + +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))); + return ret; + } + } + + 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) +{ + 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; + } + + kerr = become_user(uid, gid); + if (kerr != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("become_user failed.\n")); + goto done; + } + + 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. We can afford to just call mkdir(dirname) because we + * only want the last component to be created. + */ + + kerr = create_ccdir(dirname, uid, gid); + if (kerr) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot create directory %s\n", dirname)); + goto done; + } + + 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; +} - talloc_free(tmp_ctx); +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); + case SSS_KRB5_TYPE_DIR: + return create_ccache_in_dir(uid, gid, ctx, princ, ccname, creds); + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n")); + return EINVAL; + } - return kerr; + return EINVAL; /* Should never get here */ } static errno_t pack_response_packet(struct response *resp, int status, @@ -729,9 +896,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->uid, kr->gid, kr->ctx, + kr->creds ? kr->creds->client : kr->princ, + kr->ccname, kr->creds); if (kerr != 0) { KRB5_DEBUG(1, kerr); goto done; @@ -1142,7 +1309,8 @@ 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->uid, kr->gid, 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 91816662b..f4033d295 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_opts.h b/src/providers/krb5/krb5_opts.h index 7f47290c9..45dfec544 100644 --- a/src/providers/krb5/krb5_opts.h +++ b/src/providers/krb5/krb5_opts.h @@ -28,8 +28,8 @@ struct dp_option default_krb5_opts[] = { { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_ccachedir", DP_OPT_STRING, { "/tmp" }, NULL_STRING }, - { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING}, + { "krb5_ccachedir", DP_OPT_STRING, { "/run/user/%u" }, NULL_STRING }, + { "krb5_ccname_template", DP_OPT_STRING, { "DIR:%d" }, NULL_STRING}, { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER }, { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING }, { "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c index 9f02fe332..35ece8117 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" @@ -330,7 +331,7 @@ check_ccache_re(const char *filename, pcre *illegal_re) return EFAULT; } -static errno_t +errno_t create_ccache_dir(const char *dirname, pcre *illegal_re, uid_t uid, gid_t gid, bool private_path) { @@ -518,6 +519,42 @@ 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) +{ + char *dirname; + TALLOC_CTX *tmp_ctx = NULL; + char *end; + errno_t ret; + + dirname = talloc_strdup(tmp_ctx, parent); + if (dirname == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + + /* We'll remove all trailing slashes from the back so that + * we only pass /some/path to find_ccdir_parent_data, not + * /some/path/ */ + do { + end = strrchr(dirname, '/'); + if (end == NULL || end == dirname) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot find parent directory of [%s], " + "/ is not allowed.\n", dirname)); + ret = EINVAL; + goto done; + } + *end = '\0'; + } while (*(end+1) == '\0'); + + ret = create_ccache_dir(dirname, illegal_re, uid, gid, private_path); +done: + 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) @@ -528,6 +565,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; @@ -551,10 +591,6 @@ cc_file_create(const char *location, pcre *illegal_re, uid_t uid, gid_t gid, bool private_path) { const char *filename; - char *dirname; - char *end; - TALLOC_CTX *tmp_ctx = NULL; - errno_t ret; filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE); if (filename == NULL) { @@ -562,31 +598,7 @@ cc_file_create(const char *location, pcre *illegal_re, return EINVAL; } - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n")); - return ENOMEM; - } - - dirname = talloc_strdup(tmp_ctx, filename); - if (dirname == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } - - end = strrchr(dirname, '/'); - if (end == NULL || end == dirname) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Missing filename in [%s].\n", dirname)); - ret = EINVAL; - goto done; - } - *end = '\0'; - - ret = create_ccache_dir(dirname, illegal_re, uid, gid, private_path); -done: - talloc_free(tmp_ctx); - return ret; + return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path); } static errno_t @@ -619,6 +631,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; @@ -661,6 +676,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) { @@ -679,11 +697,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; @@ -735,3 +768,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_head(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 87bba2bae..5f677cae2 100644 --- a/src/providers/krb5/krb5_utils.h +++ b/src/providers/krb5/krb5_utils.h @@ -53,10 +53,17 @@ struct sss_krb5_cc_be { }; struct sss_krb5_cc_be file_cc; +struct sss_krb5_cc_be dir_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); +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); -- cgit