summaryrefslogtreecommitdiffstats
path: root/0004-Make-ksu-respect-the-default_ccache_name-setting.patch
diff options
context:
space:
mode:
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.patch378
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
+