From 3e53a8cd98b9410cd378ad68d8528e2a8d6d4f6a Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 17 Nov 2014 17:39:38 +0100 Subject: krb5: add copy_ccache_into_memory() Reviewed-by: Jakub Hrozek --- src/providers/krb5/krb5_ccache.c | 110 +++++++++++++++++++++++++++++++++++++++ src/providers/krb5/krb5_ccache.h | 17 ++++++ 2 files changed, 127 insertions(+) (limited to 'src/providers/krb5') diff --git a/src/providers/krb5/krb5_ccache.c b/src/providers/krb5/krb5_ccache.c index 7aa36b744..de6e694a9 100644 --- a/src/providers/krb5/krb5_ccache.c +++ b/src/providers/krb5/krb5_ccache.c @@ -667,3 +667,113 @@ errno_t safe_remove_old_ccache_file(const char *old_ccache, return sss_krb5_cc_destroy(old_ccache, uid, gid); } + +krb5_error_code copy_ccache_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx, + const char *ccache_file, + char **_mem_name) +{ + krb5_error_code kerr; + krb5_ccache ccache; + krb5_ccache mem_ccache = NULL; + char *ccache_name = NULL; + krb5_principal princ = NULL; + char *mem_name = NULL; + char *sep; + + kerr = krb5_cc_resolve(kctx, ccache_file, &ccache); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error resolving ccache [%s].\n", + ccache_file); + return kerr; + } + + kerr = krb5_cc_get_full_name(kctx, ccache, &ccache_name); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read name for ccache [%s].\n", + ccache_file); + goto done; + } + + sep = strchr(ccache_name, ':'); + if (sep == NULL || sep[1] == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Ccache name [%s] does not have delimiter[:] .\n", ccache_name); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + + if (strncmp(ccache_name, "MEMORY:", sizeof("MEMORY:") -1) == 0) { + DEBUG(SSSDBG_TRACE_FUNC, "Ccache [%s] is already memory ccache.\n", + ccache_name); + *_mem_name = talloc_strdup(mem_ctx, ccache_name); + if(*_mem_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + kerr = 0; + goto done; + } + if (strncmp(ccache_name, "FILE:", sizeof("FILE:") -1) == 0) { + mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s", sep + 1); + if (mem_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + } else { + DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected ccache type for ccache [%s], " \ + "currently only FILE is supported.\n", + ccache_name); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + + kerr = krb5_cc_resolve(kctx, mem_name, &mem_ccache); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error resolving ccache [%s].\n", mem_name); + goto done; + } + + kerr = krb5_cc_get_principal(kctx, ccache, &princ); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "error reading principal from ccache [%s].\n", ccache_name); + goto done; + } + + kerr = krb5_cc_initialize(kctx, mem_ccache, princ); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialize ccache [%s].\n", mem_name); + goto done; + } + + kerr = krb5_cc_copy_creds(kctx, ccache, mem_ccache); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to copy ccache [%s] to [%s].\n", ccache_name, mem_name); + goto done; + } + + *_mem_name = mem_name; + kerr = 0; + +done: + if (kerr != 0) { + talloc_free(mem_name); + } + + free(ccache_name); + krb5_free_principal(kctx, princ); + + if (krb5_cc_close(kctx, ccache) != 0) { + DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_close failed.\n"); + } + + if (krb5_cc_close(kctx, mem_ccache) != 0) { + DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_close failed.\n"); + } + + return kerr; +} diff --git a/src/providers/krb5/krb5_ccache.h b/src/providers/krb5/krb5_ccache.h index e47df3665..f3928e644 100644 --- a/src/providers/krb5/krb5_ccache.h +++ b/src/providers/krb5/krb5_ccache.h @@ -53,4 +53,21 @@ errno_t safe_remove_old_ccache_file(const char *old_ccache, const char *new_ccache, uid_t uid, gid_t gid); +/** + * @brief Copy given ccache into a MEMORY ccache + * + * @param[in] mem_ctx Talloc memory context the new ccache name should be + * allocated on + * @param[in] kctx Kerberos context + * @param[in] ccache_file Name of existing ccache + * @param[out] _mem_name Name of the new MEMORY ccache + * + * In contrast to MEMORY keytabs MEMORY ccaches can and must be removed + * explicitly with krb5_cc_destroy() from the memory. Just calling + * krb5_cc_close() will keep the MEMORY ccache in memory even if there are no + * open handles for the given MEMORY ccache. + */ +krb5_error_code copy_ccache_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx, + const char *ccache_file, + char **_mem_name); #endif /* __KRB5_CCACHE_H__ */ -- cgit