From ef8e4da01035981b228d8d26ca25598dd81bc766 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 19 Oct 2014 13:49:24 -0400 Subject: [PATCH] only perform dir separator normalization for file paths Commit ad7e54d698433cea77bfb4c98ac93255743d0c93 introduced the use of _krb5_expand_path_tokens() to expand tokens (and on Windows convert path delimiters) within credential cache names. This is safe to do for the path based credential cache types FILE, DIR and SCC but on Windows is unsafe for the non-path types. For example on Windows, the API credential cache names are often based on the principal name and the principal name is parsed from the ccname. This practice was introduced with the version v2 ccapi when there was no method of enumerating the caches from the krb5 library. This change adds a "filepath" boolean parameter to _krb5_expand_path_tokens() which is set to TRUE (non-zero) when the input is a file path and FALSE (zero) when the input is not a file path. _krb5_expand_path_tokens() will only perform directory separator normalization on Windows when the "filepath" parameter is TRUE. This change is not the preferred solution because it requires that the library be aware of all credential cache types that use path based residuals. The preferred solution would require that the credential cache implementation indicate whether or not it uses a path based residual. This change has been implemented using a prefix test and not a change to struct krb5_cc_ops because existing ccache plugins will not know how to advertise their use of path based residuals and that path expansion is safe. Change-Id: I8135991e8ce69fc5273d381ea9c2078bc2bcd19a --- lib/krb5/acache.c | 2 +- lib/krb5/cache.c | 25 +++++++++++++++++++++---- lib/krb5/config_file.c | 2 +- lib/krb5/expand_path.c | 7 +++++-- lib/krb5/fcache.c | 2 +- lib/krb5/kuserok.c | 2 +- lib/krb5/pkinit.c | 2 +- lib/krb5/test_expand_toks.c | 2 +- 8 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/krb5/acache.c b/lib/krb5/acache.c index aaaf71df1..9d33df133 100644 --- a/lib/krb5/acache.c +++ b/lib/krb5/acache.c @@ -125,7 +125,7 @@ init_ccapi(krb5_context context) #ifdef KRB5_USE_PATH_TOKENS { char * explib = NULL; - if (_krb5_expand_path_tokens(context, lib, &explib) == 0) { + if (_krb5_expand_path_tokens(context, lib, 0, &explib) == 0) { cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL); free(explib); } diff --git a/lib/krb5/cache.c b/lib/krb5/cache.c index 40682c4ab..e5032a3af 100644 --- a/lib/krb5/cache.c +++ b/lib/krb5/cache.c @@ -188,8 +188,13 @@ allocate_ccache (krb5_context context, krb5_error_code ret; #ifdef KRB5_USE_PATH_TOKENS char * exp_residual = NULL; + int filepath; - ret = _krb5_expand_path_tokens(context, residual, &exp_residual); + filepath = (strcmp("FILE", ops->prefix) == 0 + || strcmp("DIR", ops->prefix) == 0 + || strcmp("SCC", ops->prefix) == 0); + + ret = _krb5_expand_path_tokens(context, residual, filepath, &exp_residual); if (ret) return ret; @@ -409,7 +414,13 @@ krb5_cc_get_ops(krb5_context context, krb5_ccache id) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) { - return _krb5_expand_path_tokens(context, str, res); + int filepath; + + filepath = (strncmp("FILE:", str, 5) == 0 + || strncmp("DIR:", str, 4) == 0 + || strncmp("SCC:", str, 4) == 0); + + return _krb5_expand_path_tokens(context, str, filepath, res); } /* @@ -501,6 +512,7 @@ krb5_cc_set_default_name(krb5_context context, const char *name) { krb5_error_code ret = 0; char *p = NULL, *exp_p = NULL; + int filepath; if (name == NULL) { const char *e = NULL; @@ -556,15 +568,20 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if (p == NULL) return krb5_enomem(context); - ret = _krb5_expand_path_tokens(context, p, &exp_p); + filepath = (strncmp("FILE:", p, 5) == 0 + || strncmp("DIR:", p, 4) == 0 + || strncmp("SCC:", p, 4) == 0); + + ret = _krb5_expand_path_tokens(context, p, filepath, &exp_p); free(p); + p = exp_p; if (ret) return ret; if (context->default_cc_name) free(context->default_cc_name); - context->default_cc_name = exp_p; + context->default_cc_name = p; return 0; } diff --git a/lib/krb5/config_file.c b/lib/krb5/config_file.c index d7045272f..44d441fdd 100644 --- a/lib/krb5/config_file.c +++ b/lib/krb5/config_file.c @@ -478,7 +478,7 @@ krb5_config_parse_file_multi (krb5_context context, #ifdef KRB5_USE_PATH_TOKENS char * exp_fname = NULL; - ret = _krb5_expand_path_tokens(context, fname, &exp_fname); + ret = _krb5_expand_path_tokens(context, fname, 1, &exp_fname); if (ret) { if (newfname) free(newfname); diff --git a/lib/krb5/expand_path.c b/lib/krb5/expand_path.c index 2111fea53..3315efa5a 100644 --- a/lib/krb5/expand_path.c +++ b/lib/krb5/expand_path.c @@ -424,9 +424,10 @@ _expand_token(krb5_context context, KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_path_tokens(krb5_context context, const char *path_in, + int filepath, char **ppath_out) { - return _krb5_expand_path_tokensv(context, path_in, ppath_out, NULL); + return _krb5_expand_path_tokensv(context, path_in, filepath, ppath_out, NULL); } static void @@ -458,6 +459,7 @@ free_extra_tokens(char **extra_tokens) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_path_tokensv(krb5_context context, const char *path_in, + int filepath, char **ppath_out, ...) { char *tok_begin, *tok_end, *append; @@ -587,8 +589,9 @@ _krb5_expand_path_tokensv(krb5_context context, #ifdef _WIN32 /* Also deal with slashes */ - if (*ppath_out) { + if (filepath && *ppath_out) { char * c; + for (c = *ppath_out; *c; c++) if (*c == '/') *c = '\\'; diff --git a/lib/krb5/fcache.c b/lib/krb5/fcache.c index 9eb25ab38..b7ec047fc 100644 --- a/lib/krb5/fcache.c +++ b/lib/krb5/fcache.c @@ -334,7 +334,7 @@ fcc_gen_new(krb5_context context, krb5_ccache *id) N_("malloc: out of memory", "")); return KRB5_CC_NOMEM; } - ret = _krb5_expand_path_tokens(context, file, &exp_file); + ret = _krb5_expand_path_tokens(context, file, 1, &exp_file); free(file); if (ret) { free(f); diff --git a/lib/krb5/kuserok.c b/lib/krb5/kuserok.c index 52992396d..492d0c6b8 100644 --- a/lib/krb5/kuserok.c +++ b/lib/krb5/kuserok.c @@ -639,7 +639,7 @@ kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context, if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1) return krb5_enomem(context); - ret = _krb5_expand_path_tokensv(context, path, &path_exp, + ret = _krb5_expand_path_tokensv(context, path, 1, &path_exp, "luser", luser, NULL); free(path); if (ret) diff --git a/lib/krb5/pkinit.c b/lib/krb5/pkinit.c index 0a4804a2f..c0bd40bfd 100644 --- a/lib/krb5/pkinit.c +++ b/lib/krb5/pkinit.c @@ -2207,7 +2207,7 @@ _krb5_parse_moduli(krb5_context context, const char *file, { char * exp_file; - if (_krb5_expand_path_tokens(context, file, &exp_file) == 0) { + if (_krb5_expand_path_tokens(context, file, 1, &exp_file) == 0) { f = fopen(exp_file, "r"); krb5_xfree(exp_file); } else { diff --git a/lib/krb5/test_expand_toks.c b/lib/krb5/test_expand_toks.c index 9a736e963..7f3d79f0d 100644 --- a/lib/krb5/test_expand_toks.c +++ b/lib/krb5/test_expand_toks.c @@ -80,7 +80,7 @@ main(int argc, char **argv) if (ret) errx (1, "krb5_init_context failed: %d", ret); - ret = _krb5_expand_path_tokensv(context, "/tmp/%{foo}/%{bar}%{baz}/x", + ret = _krb5_expand_path_tokensv(context, "/tmp/%{foo}/%{bar}%{baz}/x", 0, &expanded, "foo", "abc", "bar", "dce", -- 2.11.4.GIT