diff options
Diffstat (limited to '0004-Make-ksu-respect-the-default_ccache_name-setting.patch')
-rw-r--r-- | 0004-Make-ksu-respect-the-default_ccache_name-setting.patch | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/0004-Make-ksu-respect-the-default_ccache_name-setting.patch b/0004-Make-ksu-respect-the-default_ccache_name-setting.patch new file mode 100644 index 0000000..cb45f1b --- /dev/null +++ b/0004-Make-ksu-respect-the-default_ccache_name-setting.patch @@ -0,0 +1,378 @@ +From 3a456898af626dcab4e1ab0749ca2ccb9ad6162b Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai <nalin@dahyabhai.net> +Date: Wed, 30 Oct 2013 21:47:14 -0400 +Subject: [PATCH 4/7] Make ksu respect the default_ccache_name setting + +Move the logic for resolving and initializing a cache that we're +copying creds into out of krb5_ccache_copy(), and let the caller deal +with it. Add a helper functions to select/resolve an output ccache in +the default location for the target user after we've switched to the +target user's privileges. If the destination is a collection, take +care not to change which subsidiary is its primary, and reuse a +subsidiary cache if we can. If the destination is not a collection, +append a unique value to its name to make a new ccache. + +[ghudson@mit.edu: some changes to variable names and comments; move +responsibility for getting target ccache name from +resolve_target_ccache to main] + +ticket: 7984 (new) +--- + src/clients/ksu/ccache.c | 35 +++------ + src/clients/ksu/ksu.h | 6 +- + src/clients/ksu/main.c | 181 ++++++++++++++++++++++++++++++++++++++--------- + 3 files changed, 157 insertions(+), 65 deletions(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index d0fc389..4693bd4 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -46,59 +46,41 @@ void show_credential(); + with k5 beta 3 release. + */ + +-krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, +- primary_principal, restrict_creds, +- target_principal, cc_out, stored, target_uid) ++krb5_error_code krb5_ccache_copy(context, cc_def, target_principal, cc_target, ++ restrict_creds, primary_principal, stored) + /* IN */ + krb5_context context; + krb5_ccache cc_def; +- char *cc_other_tag; +- krb5_principal primary_principal; +- krb5_boolean restrict_creds; + krb5_principal target_principal; +- uid_t target_uid; ++ krb5_ccache cc_target; ++ krb5_boolean restrict_creds; ++ krb5_principal primary_principal; + /* OUT */ +- krb5_ccache *cc_out; + krb5_boolean *stored; + { + int i=0; +- krb5_ccache * cc_other; + krb5_error_code retval=0; + krb5_creds ** cc_def_creds_arr = NULL; + krb5_creds ** cc_other_creds_arr = NULL; + +- cc_other = (krb5_ccache *) xcalloc(1, sizeof (krb5_ccache)); +- +- if ((retval = krb5_cc_resolve(context, cc_other_tag, cc_other))){ +- com_err(prog_name, retval, _("resolving ccache %s"), cc_other_tag); +- return retval; +- } +- + if (ks_ccache_is_initialized(context, cc_def)) { + if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ + return retval; + } + } + +- if (ks_ccache_name_is_initialized(context, cc_other_tag)) +- return EINVAL; +- +- if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { +- return errno; +- } +- +- retval = krb5_cc_initialize(context, *cc_other, target_principal); ++ retval = krb5_cc_initialize(context, cc_target, target_principal); + if (retval) + return retval; + + if (restrict_creds) { +- retval = krb5_store_some_creds(context, *cc_other, cc_def_creds_arr, ++ retval = krb5_store_some_creds(context, cc_target, cc_def_creds_arr, + cc_other_creds_arr, primary_principal, + stored); + } else { + *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr, + primary_principal); +- retval = krb5_store_all_creds(context, *cc_other, cc_def_creds_arr, ++ retval = krb5_store_all_creds(context, cc_target, cc_def_creds_arr, + cc_other_creds_arr); + } + +@@ -118,7 +100,6 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + } + } + +- *cc_out = *cc_other; + return retval; + } + +diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h +index 08bf01b..fbbf217 100644 +--- a/src/clients/ksu/ksu.h ++++ b/src/clients/ksu/ksu.h +@@ -44,8 +44,6 @@ + #define KRB5_DEFAULT_OPTIONS 0 + #define KRB5_DEFAULT_TKT_LIFE 60*60*12 /* 12 hours */ + +-#define KRB5_SECONDARY_CACHE "FILE:/tmp/krb5cc_" +- + #define KRB5_LOGIN_NAME ".k5login" + #define KRB5_USERS_NAME ".k5users" + #define USE_DEFAULT_REALM_NAME "." +@@ -106,8 +104,8 @@ extern krb5_error_code get_best_principal + + /* ccache.c */ + extern krb5_error_code krb5_ccache_copy +-(krb5_context, krb5_ccache, char *, krb5_principal, krb5_boolean, +- krb5_principal, krb5_ccache *, krb5_boolean *, uid_t); ++(krb5_context, krb5_ccache, krb5_principal, krb5_ccache, ++ krb5_boolean, krb5_principal, krb5_boolean *); + + extern krb5_error_code krb5_store_all_creds + (krb5_context, krb5_ccache, krb5_creds **, krb5_creds **); +diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c +index d1bb8ca..41a3bf8 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -54,6 +54,10 @@ static void print_status( const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))) + #endif + ; ++static krb5_error_code resolve_target_cache(krb5_context ksu_context, ++ krb5_principal princ, ++ krb5_ccache *ccache_out, ++ krb5_boolean *ccache_reused); + + /* Note -e and -a options are mutually exclusive */ + /* insure the proper specification of target user as well as catching +@@ -112,7 +116,7 @@ main (argc, argv) + extern char * getpass(), *crypt(); + int pargc; + char ** pargv; +- krb5_boolean stored = FALSE; ++ krb5_boolean stored = FALSE, cc_reused = FALSE; + krb5_principal kdc_server; + krb5_boolean zero_password; + krb5_boolean restrict_creds; +@@ -416,23 +420,8 @@ main (argc, argv) + exit(1); + } + +- /* +- * Make sure that the new ticket file does not already exist. +- * This is run as source_uid because it is reasonable to +- * require the source user to have write to where the target +- * cache will be created. +- */ +- cc_target_tag = (char *)xcalloc(KRB5_SEC_BUFFSIZE, sizeof(char)); +- do { +- snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%s%ld.%d", +- KRB5_SECONDARY_CACHE, +- (long)target_uid, gen_sym()); +- } while (ks_ccache_name_is_initialized(ksu_context, cc_target_tag)); +- +- if (auth_debug){ ++ if (auth_debug) + fprintf(stderr, " source cache = %s\n", cc_source_tag); +- fprintf(stderr, " target cache = %s\n", cc_target_tag); +- } + + /* + * After proper authentication and authorization, populate a cache for the +@@ -455,14 +444,19 @@ main (argc, argv) + com_err(prog_name, retval, _("while parsing temporary name")); + exit(1); + } +- retval = krb5_ccache_copy(ksu_context, cc_source, KS_TEMPORARY_CACHE, +- client, restrict_creds, tmp_princ, &cc_tmp, +- &stored, 0); ++ retval = krb5_cc_resolve(ksu_context, KS_TEMPORARY_CACHE, &cc_tmp); ++ if (retval) { ++ com_err(prog_name, retval, _("while creating temporary cache")); ++ exit(1); ++ } ++ retval = krb5_ccache_copy(ksu_context, cc_source, tmp_princ, cc_tmp, ++ restrict_creds, client, &stored); + if (retval) { + com_err(prog_name, retval, _("while copying cache %s to %s"), + krb5_cc_get_name(ksu_context, cc_source), KS_TEMPORARY_CACHE); + exit(1); + } ++ krb5_cc_close(ksu_context, cc_source); + + /* Become root for authentication*/ + +@@ -686,23 +680,38 @@ main (argc, argv) + exit(1); + } + +- retval = krb5_ccache_copy(ksu_context, cc_tmp, cc_target_tag, +- client, FALSE, client, &cc_target, &stored, +- target_pwd->pw_uid); ++ retval = resolve_target_cache(ksu_context, client, &cc_target, &cc_reused); ++ if (retval) ++ exit(1); ++ retval = krb5_cc_get_full_name(ksu_context, cc_target, &cc_target_tag); + if (retval) { +- com_err(prog_name, retval, _("while copying cache %s to %s"), +- KS_TEMPORARY_CACHE, cc_target_tag); ++ com_err(prog_name, retval, _("while getting name of target ccache")); ++ sweep_up(ksu_context, cc_target); + exit(1); + } ++ if (auth_debug) ++ fprintf(stderr, " target cache = %s\n", cc_target_tag); ++ if (cc_reused) ++ keep_target_cache = TRUE; + +- if (stored && !ks_ccache_is_initialized(ksu_context, cc_target)) { +- com_err(prog_name, errno, +- _("%s does not have correct permissions for %s, %s aborted"), +- target_user, cc_target_tag, prog_name); +- exit(1); ++ if (stored) { ++ retval = krb5_ccache_copy(ksu_context, cc_tmp, client, cc_target, ++ FALSE, client, &stored); ++ if (retval) { ++ com_err(prog_name, retval, _("while copying cache %s to %s"), ++ KS_TEMPORARY_CACHE, cc_target_tag); ++ exit(1); ++ } ++ ++ if (!ks_ccache_is_initialized(ksu_context, cc_target)) { ++ com_err(prog_name, errno, ++ _("%s does not have correct permissions for %s, " ++ "%s aborted"), target_user, cc_target_tag, prog_name); ++ exit(1); ++ } + } + +- free(cc_target_tag); ++ krb5_free_string(ksu_context, cc_target_tag); + + /* Set the cc env name to target. */ + retval = set_ccname_env(ksu_context, cc_target); +@@ -711,9 +720,6 @@ main (argc, argv) + exit(1); + } + +- if ( cc_source) +- krb5_cc_close(ksu_context, cc_source); +- + if (cmd){ + if ((source_uid == 0) || (source_uid == target_uid )){ + exec_cmd = cmd; +@@ -803,6 +809,113 @@ set_ccname_env(krb5_context ksu_context, krb5_ccache ccache) + return retval; + } + ++/* ++ * Get the configured default ccache name. Unset KRB5CCNAME and force a ++ * recomputation so we don't use values for the source user. Print an error ++ * message on failure. ++ */ ++static krb5_error_code ++get_configured_defccname(krb5_context context, char **target_out) ++{ ++ krb5_error_code retval; ++ const char *defname; ++ char *target; ++ ++ *target_out = NULL; ++ ++ if (unsetenv(KRB5_ENV_CCNAME) != 0) { ++ retval = errno; ++ com_err(prog_name, retval, _("while clearing the value of %s"), ++ KRB5_ENV_CCNAME); ++ return retval; ++ } ++ ++ /* Make sure we don't have a cached value for a different uid. */ ++ retval = krb5_cc_set_default_name(context, NULL); ++ if (retval != 0) { ++ com_err(prog_name, retval, _("while resetting target ccache name")); ++ return retval; ++ } ++ ++ defname = krb5_cc_default_name(context); ++ target = (defname == NULL) ? NULL : strdup(defname); ++ if (target == NULL) { ++ com_err(prog_name, ENOMEM, _("while determining target ccache name")); ++ return ENOMEM; ++ } ++ *target_out = target; ++ return 0; ++} ++ ++/* Determine where the target user's creds should be stored. Print an error ++ * message on failure. */ ++static krb5_error_code ++resolve_target_cache(krb5_context context, krb5_principal princ, ++ krb5_ccache *ccache_out, krb5_boolean *ccache_reused) ++{ ++ krb5_error_code retval; ++ krb5_boolean switchable, reused = FALSE; ++ krb5_ccache ccache = NULL; ++ char *sep, *ccname = NULL, *target; ++ ++ *ccache_out = NULL; ++ *ccache_reused = FALSE; ++ ++ retval = get_configured_defccname(context, &target); ++ if (retval != 0) ++ return retval; ++ ++ /* Check if the configured default name uses a switchable type. */ ++ sep = strchr(target, ':'); ++ *sep = '\0'; ++ switchable = krb5_cc_support_switch(context, target); ++ *sep = ':'; ++ ++ if (!switchable) { ++ /* Try to avoid destroying an in-use target ccache by coming up with ++ * the name of a cache that doesn't exist yet. */ ++ do { ++ free(ccname); ++ if (asprintf(&ccname, "%s.%d", target, gen_sym()) < 0) { ++ retval = ENOMEM; ++ com_err(prog_name, ENOMEM, ++ _("while allocating memory for target ccache name")); ++ goto cleanup; ++ } ++ } while (ks_ccache_name_is_initialized(context, ccname)); ++ retval = krb5_cc_resolve(context, ccname, &ccache); ++ } else { ++ /* Look for a cache in the collection that we can reuse. */ ++ retval = krb5_cc_cache_match(context, princ, &ccache); ++ if (retval == 0) { ++ reused = TRUE; ++ } else { ++ /* There isn't one, so create a new one. */ ++ *sep = '\0'; ++ retval = krb5_cc_new_unique(context, target, NULL, &ccache); ++ *sep = ':'; ++ if (retval) { ++ com_err(prog_name, retval, ++ _("while creating new target ccache")); ++ goto cleanup; ++ } ++ retval = krb5_cc_initialize(context, ccache, princ); ++ if (retval) { ++ com_err(prog_name, retval, ++ _("while initializing target cache")); ++ goto cleanup; ++ } ++ } ++ } ++ ++ *ccache_out = ccache; ++ *ccache_reused = reused; ++ ++cleanup: ++ free(target); ++ return retval; ++} ++ + #ifdef HAVE_GETUSERSHELL + + int standard_shell(sh) +-- +2.0.4 + |