From c042f71c80c2a49c6d62bfceff303faeb7e742e1 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Fri, 15 Aug 2014 13:55:48 -0400 Subject: Update collection cache patch set for ksu - replace older proposed changes for ksu with backports of the changes after review and merging upstream (#1015559, #1026099, #1118347) --- ...-try-to-stat-not-on-disk-ccache-residuals.patch | 316 ---------------- ...su-merge-krb5_ccache_copy-and-_restricted.patch | 230 ++++++++++++ ...u-don-t-stat-not-on-disk-ccache-residuals.patch | 369 ++++++++++++++++++ ...n-memory-cache-until-we-need-the-target-s.patch | 321 ---------------- ...-to-destroy-the-ccache-we-re-copying-from.patch | 95 ----- 0003-Use-an-intermediate-memory-cache-in-ksu.patch | 417 +++++++++++++++++++++ ...u-respect-the-default_ccache_name-setting.patch | 378 +++++++++++++++++++ ...e-the-default_ccache_name-d-as-the-target.patch | 149 -------- ...more-careful-of-target-ccache-collections.patch | 179 --------- ...y-config-entries-to-the-ksu-target-ccache.patch | 30 ++ ...-Copy-config-entries-to-the-target-ccache.patch | 28 -- ...-randomness-for-ksu-secondary-cache-names.patch | 115 ++++++ ...krb5_cc_new_unique-create-DIR-directories.patch | 37 ++ krb5-1.12.1-pam.patch | 18 +- krb5.spec | 32 +- 15 files changed, 1601 insertions(+), 1113 deletions(-) delete mode 100644 0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch create mode 100644 0001-In-ksu-merge-krb5_ccache_copy-and-_restricted.patch create mode 100644 0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals.patch delete mode 100644 0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch delete mode 100644 0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch create mode 100644 0003-Use-an-intermediate-memory-cache-in-ksu.patch create mode 100644 0004-Make-ksu-respect-the-default_ccache_name-setting.patch delete mode 100644 0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch delete mode 100644 0005-Be-more-careful-of-target-ccache-collections.patch create mode 100644 0005-Copy-config-entries-to-the-ksu-target-ccache.patch delete mode 100644 0006-Copy-config-entries-to-the-target-ccache.patch create mode 100644 0006-Use-more-randomness-for-ksu-secondary-cache-names.patch create mode 100644 0007-Make-krb5_cc_new_unique-create-DIR-directories.patch diff --git a/0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch b/0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch deleted file mode 100644 index ac6ce53..0000000 --- a/0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 9f902f70a79ab864083078d104196a83943844ac Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Fri, 1 Nov 2013 09:48:13 -0400 -Subject: [PATCH 1/6] Don't try to stat() not-on-disk ccache residuals - -Don't assume that ccache residual names are filenames which we can -stat() usefully. Instead, use helper functions to call the library -routines to try to read the default principal name from caches. ---- - src/clients/ksu/ccache.c | 88 +++++++++++++++++++++++++++------------------ - src/clients/ksu/heuristic.c | 13 ++----- - src/clients/ksu/ksu.h | 6 ++++ - src/clients/ksu/main.c | 17 +++++---- - 4 files changed, 70 insertions(+), 54 deletions(-) - -diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c -index 9916c75..7917af2 100644 ---- a/src/clients/ksu/ccache.c -+++ b/src/clients/ksu/ccache.c -@@ -60,12 +60,10 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - { - int i=0; - krb5_ccache * cc_other; -- const char * cc_def_name; -- const char * cc_other_name; -+ const char * cc_other_type; - krb5_error_code retval=0; - krb5_creds ** cc_def_creds_arr = NULL; - krb5_creds ** cc_other_creds_arr = NULL; -- struct stat st_temp; - - cc_other = (krb5_ccache *) xcalloc(1, sizeof (krb5_ccache)); - -@@ -74,10 +72,9 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - return retval; - } - -- cc_def_name = krb5_cc_get_name(context, cc_def); -- cc_other_name = krb5_cc_get_name(context, *cc_other); -+ cc_other_type = krb5_cc_get_type(context, *cc_other); - -- if ( ! stat(cc_def_name, &st_temp)){ -+ if (krb5_ccache_is_initialized(context, cc_def)) { - if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ - return retval; - } -@@ -86,7 +83,8 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr, - primary_principal); - -- if (!lstat( cc_other_name, &st_temp)) -+ if (!krb5_cc_support_switch(context, cc_other_type) && -+ krb5_ccache_name_is_initialized(context, cc_other_tag)) - return EINVAL; - - if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { -@@ -533,24 +531,18 @@ krb5_error_code krb5_ccache_overwrite(context, ccs, cct, primary_principal) - krb5_ccache cct; - krb5_principal primary_principal; - { -- const char * cct_name; -- const char * ccs_name; - krb5_error_code retval=0; - krb5_principal temp_principal; - krb5_creds ** ccs_creds_arr = NULL; - int i=0; -- struct stat st_temp; - -- ccs_name = krb5_cc_get_name(context, ccs); -- cct_name = krb5_cc_get_name(context, cct); -- -- if ( ! stat(ccs_name, &st_temp)){ -+ if (krb5_ccache_is_initialized(context, ccs)) { - if ((retval = krb5_get_nonexp_tkts(context, ccs, &ccs_creds_arr))){ - return retval; - } - } - -- if ( ! stat(cct_name, &st_temp)){ -+ if (krb5_ccache_is_initialized(context, cct)) { - if ((retval = krb5_cc_get_principal(context, cct, &temp_principal))){ - return retval; - } -@@ -649,12 +641,10 @@ krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, - - int i=0; - krb5_ccache * cc_other; -- const char * cc_def_name; -- const char * cc_other_name; -+ const char * cc_other_type; - krb5_error_code retval=0; - krb5_creds ** cc_def_creds_arr = NULL; - krb5_creds ** cc_other_creds_arr = NULL; -- struct stat st_temp; - - cc_other = (krb5_ccache *) xcalloc(1, sizeof (krb5_ccache)); - -@@ -663,19 +653,17 @@ krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, - return retval; - } - -- cc_def_name = krb5_cc_get_name(context, cc_def); -- cc_other_name = krb5_cc_get_name(context, *cc_other); -+ cc_other_type = krb5_cc_get_type(context, *cc_other); - -- if ( ! stat(cc_def_name, &st_temp)){ -- if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ -+ if (krb5_ccache_is_initialized(context, cc_def)) { -+ retval = krb5_get_nonexp_tkts(context, cc_def, &cc_def_creds_arr); -+ if (retval) - return retval; -- } -- - } - -- if (!lstat( cc_other_name, &st_temp)) { -+ if (!krb5_cc_support_switch(context, cc_other_type) && -+ krb5_ccache_name_is_initialized(context, cc_other_tag)) - return EINVAL; -- } - - if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { - return errno; -@@ -723,12 +711,10 @@ krb5_error_code krb5_ccache_filter (context, cc, prst) - krb5_creds ** cc_creds_arr = NULL; - const char * cc_name; - krb5_boolean stored; -- struct stat st_temp; - - cc_name = krb5_cc_get_name(context, cc); - -- if ( ! stat(cc_name, &st_temp)){ -- -+ if (krb5_ccache_is_initialized(context, cc)) { - if (auth_debug) { - fprintf(stderr,"putting cache %s through a filter for -z option\n", cc_name); - } -@@ -793,12 +779,8 @@ krb5_error_code krb5_find_princ_in_cache (context, cc, princ, found) - { - krb5_error_code retval; - krb5_creds ** creds_list = NULL; -- const char * cc_name; -- struct stat st_temp; - -- cc_name = krb5_cc_get_name(context, cc); -- -- if ( ! stat(cc_name, &st_temp)){ -+ if (krb5_ccache_is_initialized(context, cc)) { - if ((retval = krb5_get_nonexp_tkts(context, cc, &creds_list))){ - return retval; - } -@@ -807,3 +789,41 @@ krb5_error_code krb5_find_princ_in_cache (context, cc, princ, found) - *found = krb5_find_princ_in_cred_list(context, creds_list, princ); - return 0; - } -+ -+extern krb5_boolean -+krb5_ccache_name_is_initialized(krb5_context context, const char *cctag) -+{ -+ krb5_error_code retval = 0; -+ krb5_ccache cc; -+ krb5_principal princ; -+ -+ retval = krb5_cc_resolve(context, cctag, &cc); -+ if (retval) -+ return FALSE; -+ -+ retval = krb5_cc_get_principal(context, cc, &princ); -+ if (retval == 0) -+ krb5_free_principal(context, princ); -+ krb5_cc_close(context, cc); -+ -+ return retval == 0; -+} -+ -+extern krb5_boolean -+krb5_ccache_is_initialized(krb5_context context, krb5_ccache def_cc) -+{ -+ krb5_error_code retval = 0; -+ krb5_boolean result; -+ char *def_cc_name; -+ -+ if (def_cc == NULL) -+ return FALSE; -+ -+ retval = krb5_cc_get_full_name(context, def_cc, &def_cc_name); -+ if (retval) -+ return FALSE; -+ -+ result = krb5_ccache_name_is_initialized(context, def_cc_name); -+ krb5_free_string(context, def_cc_name); -+ return result; -+} -diff --git a/src/clients/ksu/heuristic.c b/src/clients/ksu/heuristic.c -index c7e691c..bfde451 100644 ---- a/src/clients/ksu/heuristic.c -+++ b/src/clients/ksu/heuristic.c -@@ -404,12 +404,8 @@ krb5_error_code find_either_ticket (context, cc, client, end_server, found) - krb5_principal kdc_server; - krb5_error_code retval; - krb5_boolean temp_found = FALSE; -- const char * cc_source_name; -- struct stat st_temp; - -- cc_source_name = krb5_cc_get_name(context, cc); -- -- if ( ! stat(cc_source_name, &st_temp)){ -+ if (krb5_ccache_is_initialized(context, cc)) { - - retval = find_ticket(context, cc, client, end_server, &temp_found); - if (retval) -@@ -546,7 +542,6 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, - { - - princ_info princ_trials[10]; -- const char * cc_source_name; - krb5_principal cc_def_princ = NULL; - krb5_principal temp_client; - krb5_principal target_client; -@@ -558,7 +553,6 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, - struct stat tb; - int count =0; - int i; -- struct stat st_temp; - - *path_out = 0; - -@@ -566,10 +560,7 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, - if (options->princ) - return 0; - -- cc_source_name = krb5_cc_get_name(context, cc_source); -- -- -- if (! stat(cc_source_name, &st_temp)) { -+ if (krb5_ccache_is_initialized(context, cc_source)) { - retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ); - if (retval) - return retval; -diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h -index f2c0811..2a63c21 100644 ---- a/src/clients/ksu/ksu.h -+++ b/src/clients/ksu/ksu.h -@@ -141,6 +141,12 @@ extern krb5_error_code krb5_store_some_creds - (krb5_context, krb5_ccache, krb5_creds **, krb5_creds **, - krb5_principal, krb5_boolean *); - -+extern krb5_boolean krb5_ccache_name_is_initialized -+(krb5_context, const char *); -+ -+extern krb5_boolean krb5_ccache_is_initialized -+(krb5_context, krb5_ccache); -+ - extern krb5_error_code krb5_ccache_copy_restricted - (krb5_context, krb5_ccache, char *, krb5_principal, - krb5_ccache *, krb5_boolean *, uid_t); -diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c -index 233eb52..e2ca06a 100644 ---- a/src/clients/ksu/main.c -+++ b/src/clients/ksu/main.c -@@ -112,7 +112,6 @@ main (argc, argv) - extern char * getpass(), *crypt(); - int pargc; - char ** pargv; -- struct stat st_temp; - krb5_boolean stored = FALSE; - krb5_principal kdc_server; - krb5_boolean zero_password; -@@ -265,9 +264,10 @@ main (argc, argv) - if ( strchr(cc_source_tag, ':')){ - cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1; - -- if( stat( cc_source_tag_tmp, &st_temp)){ -+ if (!krb5_ccache_name_is_initialized(ksu_context, -+ cc_source_tag)) { - com_err(prog_name, errno, -- _("while looking for credentials file %s"), -+ _("while looking for credentials cache %s"), - cc_source_tag_tmp); - exit (1); - } -@@ -432,7 +432,8 @@ main (argc, argv) - (long) target_uid, gen_sym()); - cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1; - -- }while ( !stat ( cc_target_tag_tmp, &st_temp)); -+ } while (krb5_ccache_name_is_initialized(ksu_context, -+ cc_target_tag)); - } - - -@@ -884,8 +885,6 @@ static void sweep_up(context, cc) - krb5_ccache cc; - { - krb5_error_code retval; -- const char * cc_name; -- struct stat st_temp; - - krb5_seteuid(0); - if (krb5_seteuid(target_uid) < 0) { -@@ -894,9 +893,9 @@ static void sweep_up(context, cc) - exit(1); - } - -- cc_name = krb5_cc_get_name(context, cc); -- if ( ! stat(cc_name, &st_temp)){ -- if ((retval = krb5_cc_destroy(context, cc))) -+ if (krb5_ccache_is_initialized(context, cc)) { -+ retval = krb5_cc_destroy(context, cc); -+ if (retval) - com_err(prog_name, retval, _("while destroying cache")); - } - } --- -1.8.5.3 - diff --git a/0001-In-ksu-merge-krb5_ccache_copy-and-_restricted.patch b/0001-In-ksu-merge-krb5_ccache_copy-and-_restricted.patch new file mode 100644 index 0000000..ac7baa1 --- /dev/null +++ b/0001-In-ksu-merge-krb5_ccache_copy-and-_restricted.patch @@ -0,0 +1,230 @@ +From 74e775ac6d937c9d22be4fc1d429e5e62705fb7d Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Thu, 24 Jul 2014 15:39:53 -0400 +Subject: [PATCH 1/7] In ksu, merge krb5_ccache_copy() and _restricted() + +Other than whether or not they limit the creds it stores to the new +ccache based on the principal name of the client for whom the creds were +issued, there's no meaningful difference between what these two +functions do. Merge them. +--- + src/clients/ksu/ccache.c | 106 ++++++----------------------------------------- + src/clients/ksu/ksu.h | 6 +-- + src/clients/ksu/main.c | 27 ++++-------- + 3 files changed, 22 insertions(+), 117 deletions(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index 9916c75..118fc53 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -47,12 +47,14 @@ void show_credential(); + */ + + krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, +- primary_principal, cc_out, stored, target_uid) ++ primary_principal, restrict_creds, cc_out, ++ stored, target_uid) + /* IN */ + krb5_context context; + krb5_ccache cc_def; + char *cc_other_tag; + krb5_principal primary_principal; ++ krb5_boolean restrict_creds; + uid_t target_uid; + /* OUT */ + krb5_ccache *cc_out; +@@ -83,9 +85,6 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + } + } + +- *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr, +- primary_principal); +- + if (!lstat( cc_other_name, &st_temp)) + return EINVAL; + +@@ -98,8 +97,16 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + return retval; + } + +- retval = krb5_store_all_creds(context, * cc_other, cc_def_creds_arr, +- cc_other_creds_arr); ++ if (restrict_creds) { ++ retval = krb5_store_some_creds(context, *cc_other, 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, ++ cc_other_creds_arr); ++ } + + if (cc_def_creds_arr){ + while (cc_def_creds_arr[i]){ +@@ -623,93 +630,6 @@ krb5_error_code krb5_store_some_creds(context, cc, creds_def, creds_other, prst, + *stored = temp_stored; + return 0; + } +-/****************************************************************** +-krb5_cache_copy_restricted +- +-gets rid of any expired tickets in the secondary cache, +-copies the default cache into the secondary cache, +-only credentials that are for prst are copied. +- +-the algorithm may look a bit funny, +-but I had to do it this way, since cc_remove function did not come +-with k5 beta 3 release. +-************************************************************************/ +- +-krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, +- prst, cc_out, stored, target_uid) +- krb5_context context; +- krb5_ccache cc_def; +- char *cc_other_tag; +- krb5_principal prst; +- uid_t target_uid; +- /* OUT */ +- krb5_ccache *cc_out; +- krb5_boolean *stored; +-{ +- +- int i=0; +- krb5_ccache * cc_other; +- const char * cc_def_name; +- const char * cc_other_name; +- krb5_error_code retval=0; +- krb5_creds ** cc_def_creds_arr = NULL; +- krb5_creds ** cc_other_creds_arr = NULL; +- struct stat st_temp; +- +- 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; +- } +- +- cc_def_name = krb5_cc_get_name(context, cc_def); +- cc_other_name = krb5_cc_get_name(context, *cc_other); +- +- if ( ! stat(cc_def_name, &st_temp)){ +- if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ +- return retval; +- } +- +- } +- +- if (!lstat( cc_other_name, &st_temp)) { +- return EINVAL; +- } +- +- if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { +- return errno; +- } +- +- +- if ((retval = krb5_cc_initialize(context, *cc_other, prst))){ +- return retval; +- } +- +- retval = krb5_store_some_creds(context, * cc_other, +- cc_def_creds_arr, cc_other_creds_arr, prst, stored); +- +- +- +- if (cc_def_creds_arr){ +- while (cc_def_creds_arr[i]){ +- krb5_free_creds(context, cc_def_creds_arr[i]); +- i++; +- } +- } +- +- i=0; +- +- if(cc_other_creds_arr){ +- while (cc_other_creds_arr[i]){ +- krb5_free_creds(context, cc_other_creds_arr[i]); +- i++; +- } +- } +- +- *cc_out = *cc_other; +- return retval; +-} + + krb5_error_code krb5_ccache_filter (context, cc, prst) + krb5_context context; +diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h +index f2c0811..9e0c613 100644 +--- a/src/clients/ksu/ksu.h ++++ b/src/clients/ksu/ksu.h +@@ -107,7 +107,7 @@ extern krb5_error_code get_best_principal + /* ccache.c */ + extern krb5_error_code krb5_ccache_copy + (krb5_context, krb5_ccache, char *, krb5_principal, +- krb5_ccache *, krb5_boolean *, uid_t); ++ krb5_boolean, krb5_ccache *, krb5_boolean *, uid_t); + + extern krb5_error_code krb5_store_all_creds + (krb5_context, krb5_ccache, krb5_creds **, krb5_creds **); +@@ -141,10 +141,6 @@ extern krb5_error_code krb5_store_some_creds + (krb5_context, krb5_ccache, krb5_creds **, krb5_creds **, + krb5_principal, krb5_boolean *); + +-extern krb5_error_code krb5_ccache_copy_restricted +-(krb5_context, krb5_ccache, char *, krb5_principal, +- krb5_ccache *, krb5_boolean *, uid_t); +- + extern krb5_error_code krb5_ccache_refresh + (krb5_context, krb5_ccache); + +diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c +index 233eb52..62f3bc0 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -117,6 +117,7 @@ main (argc, argv) + krb5_principal kdc_server; + krb5_boolean zero_password; + char * dir_of_cc_target; ++ krb5_boolean restrict_creds; + + options.opt = KRB5_DEFAULT_OPTIONS; + options.lifetime = KRB5_DEFAULT_TKT_LIFE; +@@ -464,25 +465,13 @@ main (argc, argv) + then only the credentials for that particular user + should be copied */ + +- if ((source_uid == 0) && (target_uid != 0)) { +- +- if ((retval = krb5_ccache_copy_restricted(ksu_context, cc_source, +- cc_target_tag, client, +- &cc_target, &stored, +- target_uid))){ +- com_err(prog_name, retval, _("while copying cache %s to %s"), +- krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); +- exit(1); +- } +- +- } else { +- if ((retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag, +- client,&cc_target, &stored, target_uid))) { +- com_err(prog_name, retval, _("while copying cache %s to %s"), +- krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); +- exit(1); +- } +- ++ restrict_creds = (source_uid == 0) && (target_uid != 0); ++ retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag, client, ++ restrict_creds, &cc_target, &stored, target_uid); ++ if (retval) { ++ com_err(prog_name, retval, _("while copying cache %s to %s"), ++ krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); ++ exit(1); + } + + /* Become root for authentication*/ +-- +2.0.4 + diff --git a/0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals.patch b/0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals.patch new file mode 100644 index 0000000..262e7c7 --- /dev/null +++ b/0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals.patch @@ -0,0 +1,369 @@ +From 9ebae7cb434b9b177c0af85c67a6d6267f46bc68 Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Fri, 1 Nov 2013 09:48:13 -0400 +Subject: [PATCH 2/7] In ksu, don't stat() not-on-disk ccache residuals + +Don't assume that ccache residual names are filenames which we can +stat() usefully. Instead, use helper functions to call the library +routines to try to read the default principal name from caches, and +use whether or not that succeeds as an indication of whether or not +there's a ccache in a given location. + +ticket: 7728 +--- + src/clients/ksu/ccache.c | 60 ++++++++++++++++++++-------------- + src/clients/ksu/heuristic.c | 13 ++------ + src/clients/ksu/ksu.h | 8 +++-- + src/clients/ksu/main.c | 79 +++++++++------------------------------------ + 4 files changed, 60 insertions(+), 100 deletions(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index 118fc53..5f57279 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -62,12 +62,9 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + { + int i=0; + krb5_ccache * cc_other; +- const char * cc_def_name; +- const char * cc_other_name; + krb5_error_code retval=0; + krb5_creds ** cc_def_creds_arr = NULL; + krb5_creds ** cc_other_creds_arr = NULL; +- struct stat st_temp; + + cc_other = (krb5_ccache *) xcalloc(1, sizeof (krb5_ccache)); + +@@ -76,16 +73,13 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + return retval; + } + +- cc_def_name = krb5_cc_get_name(context, cc_def); +- cc_other_name = krb5_cc_get_name(context, *cc_other); +- +- if ( ! stat(cc_def_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, cc_def)) { + if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ + return retval; + } + } + +- if (!lstat( cc_other_name, &st_temp)) ++ if (ks_ccache_name_is_initialized(context, cc_other_tag)) + return EINVAL; + + if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { +@@ -540,24 +534,18 @@ krb5_error_code krb5_ccache_overwrite(context, ccs, cct, primary_principal) + krb5_ccache cct; + krb5_principal primary_principal; + { +- const char * cct_name; +- const char * ccs_name; + krb5_error_code retval=0; + krb5_principal temp_principal; + krb5_creds ** ccs_creds_arr = NULL; + int i=0; +- struct stat st_temp; + +- ccs_name = krb5_cc_get_name(context, ccs); +- cct_name = krb5_cc_get_name(context, cct); +- +- if ( ! stat(ccs_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, ccs)) { + if ((retval = krb5_get_nonexp_tkts(context, ccs, &ccs_creds_arr))){ + return retval; + } + } + +- if ( ! stat(cct_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, cct)) { + if ((retval = krb5_cc_get_principal(context, cct, &temp_principal))){ + return retval; + } +@@ -643,12 +631,10 @@ krb5_error_code krb5_ccache_filter (context, cc, prst) + krb5_creds ** cc_creds_arr = NULL; + const char * cc_name; + krb5_boolean stored; +- struct stat st_temp; + + cc_name = krb5_cc_get_name(context, cc); + +- if ( ! stat(cc_name, &st_temp)){ +- ++ if (ks_ccache_is_initialized(context, cc)) { + if (auth_debug) { + fprintf(stderr,"putting cache %s through a filter for -z option\n", cc_name); + } +@@ -713,12 +699,8 @@ krb5_error_code krb5_find_princ_in_cache (context, cc, princ, found) + { + krb5_error_code retval; + krb5_creds ** creds_list = NULL; +- const char * cc_name; +- struct stat st_temp; +- +- cc_name = krb5_cc_get_name(context, cc); + +- if ( ! stat(cc_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, cc)) { + if ((retval = krb5_get_nonexp_tkts(context, cc, &creds_list))){ + return retval; + } +@@ -727,3 +709,33 @@ krb5_error_code krb5_find_princ_in_cache (context, cc, princ, found) + *found = krb5_find_princ_in_cred_list(context, creds_list, princ); + return 0; + } ++ ++krb5_boolean ++ks_ccache_name_is_initialized(krb5_context context, const char *cctag) ++{ ++ krb5_boolean result; ++ krb5_ccache cc; ++ ++ if (krb5_cc_resolve(context, cctag, &cc) != 0) ++ return FALSE; ++ result = ks_ccache_is_initialized(context, cc); ++ krb5_cc_close(context, cc); ++ ++ return result; ++} ++ ++krb5_boolean ++ks_ccache_is_initialized(krb5_context context, krb5_ccache cc) ++{ ++ krb5_principal princ; ++ krb5_error_code retval; ++ ++ if (cc == NULL) ++ return FALSE; ++ ++ retval = krb5_cc_get_principal(context, cc, &princ); ++ if (retval == 0) ++ krb5_free_principal(context, princ); ++ ++ return retval == 0; ++} +diff --git a/src/clients/ksu/heuristic.c b/src/clients/ksu/heuristic.c +index 99b54e5..f73b8eb 100644 +--- a/src/clients/ksu/heuristic.c ++++ b/src/clients/ksu/heuristic.c +@@ -397,12 +397,8 @@ krb5_error_code find_either_ticket (context, cc, client, end_server, found) + krb5_principal kdc_server; + krb5_error_code retval; + krb5_boolean temp_found = FALSE; +- const char * cc_source_name; +- struct stat st_temp; + +- cc_source_name = krb5_cc_get_name(context, cc); +- +- if ( ! stat(cc_source_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, cc)) { + + retval = find_ticket(context, cc, client, end_server, &temp_found); + if (retval) +@@ -539,7 +535,6 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, + { + + princ_info princ_trials[10]; +- const char * cc_source_name; + krb5_principal cc_def_princ = NULL; + krb5_principal temp_client; + krb5_principal target_client; +@@ -551,7 +546,6 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, + struct stat tb; + int count =0; + int i; +- struct stat st_temp; + + *path_out = 0; + +@@ -559,10 +553,7 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, + if (options->princ) + return 0; + +- cc_source_name = krb5_cc_get_name(context, cc_source); +- +- +- if (! stat(cc_source_name, &st_temp)) { ++ if (ks_ccache_is_initialized(context, cc_source)) { + retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ); + if (retval) + return retval; +diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h +index 9e0c613..e1e34f1 100644 +--- a/src/clients/ksu/ksu.h ++++ b/src/clients/ksu/ksu.h +@@ -141,6 +141,12 @@ extern krb5_error_code krb5_store_some_creds + (krb5_context, krb5_ccache, krb5_creds **, krb5_creds **, + krb5_principal, krb5_boolean *); + ++extern krb5_boolean ks_ccache_name_is_initialized ++(krb5_context, const char *); ++ ++extern krb5_boolean ks_ccache_is_initialized ++(krb5_context, krb5_ccache); ++ + extern krb5_error_code krb5_ccache_refresh + (krb5_context, krb5_ccache); + +@@ -198,8 +204,6 @@ extern int standard_shell (char *); + + extern krb5_error_code get_params (int *, int, char **, char ***); + +-extern char *get_dir_of_file (const char *); +- + /* heuristic.c */ + extern krb5_error_code get_all_princ_from_file (FILE *, char ***); + +diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c +index 62f3bc0..8c49f94 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -51,7 +51,6 @@ static void print_status( const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))) + #endif + ; +-char * get_dir_of_file(); + + /* Note -e and -a options are mutually exclusive */ + /* insure the proper specification of target user as well as catching +@@ -96,7 +95,6 @@ main (argc, argv) + const char * cc_source_tag = NULL; + uid_t source_gid; + const char * cc_source_tag_tmp = NULL; +- char * cc_target_tag_tmp=NULL; + char * cmd = NULL, * exec_cmd = NULL; + int errflg = 0; + krb5_boolean auth_val; +@@ -112,11 +110,9 @@ main (argc, argv) + extern char * getpass(), *crypt(); + int pargc; + char ** pargv; +- struct stat st_temp; + krb5_boolean stored = FALSE; + krb5_principal kdc_server; + krb5_boolean zero_password; +- char * dir_of_cc_target; + krb5_boolean restrict_creds; + + options.opt = KRB5_DEFAULT_OPTIONS; +@@ -266,9 +262,10 @@ main (argc, argv) + if ( strchr(cc_source_tag, ':')){ + cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1; + +- if( stat( cc_source_tag_tmp, &st_temp)){ ++ if (!ks_ccache_name_is_initialized(ksu_context, ++ cc_source_tag)) { + com_err(prog_name, errno, +- _("while looking for credentials file %s"), ++ _("while looking for credentials cache %s"), + cc_source_tag_tmp); + exit (1); + } +@@ -419,32 +416,18 @@ main (argc, argv) + exit(1); + } + +- if (cc_target_tag == NULL) { +- +- cc_target_tag = (char *)xcalloc(KRB5_SEC_BUFFSIZE ,sizeof(char)); +- /* 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.*/ +- +- do { +- snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%s%ld.%d", +- KRB5_SECONDARY_CACHE, +- (long) target_uid, gen_sym()); +- cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1; +- +- }while ( !stat ( cc_target_tag_tmp, &st_temp)); +- } +- +- +- dir_of_cc_target = get_dir_of_file(cc_target_tag_tmp); +- +- if (access(dir_of_cc_target, R_OK | W_OK )){ +- fprintf(stderr, +- _("%s does not have correct permissions for %s\n"), +- source_user, cc_target_tag); +- 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){ + fprintf(stderr, " source cache = %s\n", cc_source_tag); +@@ -747,13 +730,6 @@ main (argc, argv) + exit(1); + } + +- if (access( cc_target_tag_tmp, R_OK | W_OK )){ +- com_err(prog_name, errno, +- _("%s does not have correct permissions for %s, %s aborted"), +- target_user, cc_target_tag_tmp, prog_name); +- exit(1); +- } +- + if ( cc_source) + krb5_cc_close(ksu_context, cc_source); + +@@ -873,8 +849,6 @@ static void sweep_up(context, cc) + krb5_ccache cc; + { + krb5_error_code retval; +- const char * cc_name; +- struct stat st_temp; + + krb5_seteuid(0); + if (krb5_seteuid(target_uid) < 0) { +@@ -883,8 +857,7 @@ static void sweep_up(context, cc) + exit(1); + } + +- cc_name = krb5_cc_get_name(context, cc); +- if ( ! stat(cc_name, &st_temp)){ ++ if (ks_ccache_is_initialized(context, cc)) { + if ((retval = krb5_cc_destroy(context, cc))) + com_err(prog_name, retval, _("while destroying cache")); + } +@@ -937,26 +910,6 @@ void print_status(const char *fmt, ...) + } + } + +- +-char *get_dir_of_file(path) +- const char *path; +-{ +- char * temp_path; +- char * ptr; +- +- temp_path = xstrdup(path); +- +- if ((ptr = strrchr( temp_path, '/'))) { +- *ptr = '\0'; +- } else { +- free (temp_path); +- temp_path = xmalloc(MAXPATHLEN); +- if (temp_path) +- getcwd(temp_path, MAXPATHLEN); +- } +- return temp_path; +-} +- + krb5_error_code + ksu_tgtname(context, server, client, tgtprinc) + krb5_context context; +-- +2.0.4 + diff --git a/0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch b/0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch deleted file mode 100644 index ef62793..0000000 --- a/0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch +++ /dev/null @@ -1,321 +0,0 @@ -From 5195c2b20593330192feff67dd5f271e88f562e7 Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Wed, 30 Oct 2013 21:45:35 -0400 -Subject: [PATCH 2/6] Use an in-memory cache until we need the target's - -Instead of copying source or obtained creds into the target cache and -changing ownership if everything succeeds, copy them into a MEMORY: -cache and then, if everything succeeds, create the target cache as the -target user. ---- - src/clients/ksu/ksu.h | 1 + - src/clients/ksu/main.c | 133 +++++++++++++++++++++++++++++-------------------- - 2 files changed, 80 insertions(+), 54 deletions(-) - -diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h -index 2a63c21..1d102a1 100644 ---- a/src/clients/ksu/ksu.h -+++ b/src/clients/ksu/ksu.h -@@ -45,6 +45,7 @@ - #define KRB5_DEFAULT_TKT_LIFE 60*60*12 /* 12 hours */ - - #define KRB5_SECONDARY_CACHE "FILE:/tmp/krb5cc_" -+#define KRB5_TEMPORARY_CACHE "MEMORY:_ksu" - - #define KRB5_LOGIN_NAME ".k5login" - #define KRB5_USERS_NAME ".k5users" -diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c -index e2ca06a..fa86c78 100644 ---- a/src/clients/ksu/main.c -+++ b/src/clients/ksu/main.c -@@ -86,7 +86,7 @@ main (argc, argv) - int statusp=0; - krb5_error_code retval = 0; - krb5_principal client = NULL; -- krb5_ccache cc_target = NULL; -+ krb5_ccache cc_tmp = NULL, cc_target = NULL; - krb5_context ksu_context; - char * cc_target_tag = NULL; - char * target_user = NULL; -@@ -452,14 +452,15 @@ main (argc, argv) - } - - /* -- Only when proper authentication and authorization -- takes place, the target user becomes the owner of the cache. -- */ -- -- /* we continue to run as source uid until -- the middle of the copy, when becomewe become the target user -- The cache is owned by the target user.*/ -+ * Only after proper authentication and authorization has -+ * taken place, do we populate a cache for the target user. -+ */ - -+ /* -+ * We read the set of creds we want to copy from the source ccache as the -+ * source uid, become root for authentication, and then become the target -+ * user to handle authorization and creating the target user's cache. -+ */ - - /* if root ksu's to a regular user, then - then only the credentials for that particular user -@@ -468,19 +469,23 @@ main (argc, argv) - if ((source_uid == 0) && (target_uid != 0)) { - - if ((retval = krb5_ccache_copy_restricted(ksu_context, cc_source, -- cc_target_tag, client, -- &cc_target, &stored, -- target_uid))){ -+ KRB5_TEMPORARY_CACHE, client, -+ &cc_tmp, &stored, -+ 0))){ - com_err(prog_name, retval, _("while copying cache %s to %s"), -- krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); -+ krb5_cc_get_name(ksu_context, cc_source), -+ KRB5_TEMPORARY_CACHE); - exit(1); - } - - } else { -- if ((retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag, -- client,&cc_target, &stored, target_uid))) { -+ -+ retval = krb5_ccache_copy(ksu_context, cc_source, KRB5_TEMPORARY_CACHE, -+ client, &cc_tmp, &stored, 0); -+ if (retval) { - com_err(prog_name, retval, _("while copying cache %s to %s"), -- krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); -+ krb5_cc_get_name(ksu_context, cc_source), -+ KRB5_TEMPORARY_CACHE); - exit(1); - } - -@@ -502,7 +507,7 @@ main (argc, argv) - &kdc_server))){ - com_err(prog_name, retval, - _("while creating tgt for local realm")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -510,13 +515,13 @@ main (argc, argv) - "enter it here and are logged\n")); - fprintf(stderr, _(" in remotely using an unsecure " - "(non-encrypted) channel.\n")); -- if (krb5_get_tkt_via_passwd (ksu_context, &cc_target, client, -- kdc_server, &options, -- &zero_password) == FALSE){ -+ if (krb5_get_tkt_via_passwd(ksu_context, &cc_tmp, client, -+ kdc_server, &options, -+ &zero_password) == FALSE){ - - if (zero_password == FALSE){ - fprintf(stderr, _("Goodbye\n")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -535,15 +540,16 @@ main (argc, argv) - if (source_uid && (source_uid != target_uid)) { - char * client_name; - -- auth_val = krb5_auth_check(ksu_context, client, localhostname, &options, -- target_user,cc_target, &path_passwd, target_uid); -+ auth_val = krb5_auth_check(ksu_context, client, localhostname, -+ &options, target_user, cc_tmp, -+ &path_passwd, target_uid); - - /* if Kerberos authentication failed then exit */ - if (auth_val ==FALSE){ - fprintf(stderr, _("Authentication failed.\n")); - syslog(LOG_WARNING, "'%s %s' authentication failed for %s%s", - prog_name,target_user,source_user,ontty()); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -576,7 +582,7 @@ main (argc, argv) - - if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) { - com_err(prog_name, retval, _("When unparsing name")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -589,7 +595,7 @@ main (argc, argv) - if (krb5_seteuid(target_uid)) { - com_err(prog_name, errno, _("while switching to target for " - "authorization check")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -597,14 +603,14 @@ main (argc, argv) - cmd, &authorization_val, &exec_cmd))){ - com_err(prog_name,retval, _("while checking authorization")); - krb5_seteuid(0); /*So we have some chance of sweeping up*/ -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - - if (krb5_seteuid(0)) { - com_err(prog_name, errno, _("while switching back from target " - "after authorization check")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - if (authorization_val == TRUE){ -@@ -646,21 +652,23 @@ main (argc, argv) - - } - -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - } - - if( some_rest_copy){ -- if ((retval = krb5_ccache_filter(ksu_context, cc_target, client))){ -+ retval = krb5_ccache_filter(ksu_context, cc_tmp, client); -+ if (retval) { - com_err(prog_name,retval, _("while calling cc_filter")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - } - - if (all_rest_copy){ -- if ((retval = krb5_cc_initialize(ksu_context, cc_target, client))){ -+ retval = krb5_cc_initialize(ksu_context, cc_tmp, client); -+ if (retval) { - com_err(prog_name, retval, _("while erasing target cache")); - exit(1); - } -@@ -682,7 +690,7 @@ main (argc, argv) - - if (!standard_shell(target_pwd->pw_shell) && source_uid) { - fprintf(stderr, _("ksu: permission denied (shell).\n")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - #endif /* HAVE_GETUSERSHELL */ -@@ -692,43 +700,33 @@ main (argc, argv) - if(set_env_var("USER", target_pwd->pw_name)){ - fprintf(stderr, - _("ksu: couldn't set environment variable USER\n")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - } - - if(set_env_var( "HOME", target_pwd->pw_dir)){ - fprintf(stderr, _("ksu: couldn't set environment variable HOME\n")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - - if(set_env_var( "SHELL", shell)){ - fprintf(stderr, _("ksu: couldn't set environment variable SHELL\n")); -- sweep_up(ksu_context, cc_target); -- exit(1); -- } -- -- /* set the cc env name to target */ -- -- if(set_env_var( KRB5_ENV_CCNAME, cc_target_tag)){ -- fprintf(stderr, _("ksu: couldn't set environment variable %s\n"), -- KRB5_ENV_CCNAME); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - - /* set permissions */ - if (setgid(target_pwd->pw_gid) < 0) { - perror("ksu: setgid"); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -- - if (initgroups(target_user, target_pwd->pw_gid)) { - fprintf(stderr, _("ksu: initgroups failed.\n")); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - -@@ -748,22 +746,49 @@ main (argc, argv) - */ - if (setluid((uid_t) pwd->pw_uid) < 0) { - perror("setluid"); -- sweep_up(ksu_context, cc_target); -+ sweep_up(ksu_context, cc_tmp); - exit(1); - } - #endif /* HAVE_SETLUID */ - -- if (setuid(target_pwd->pw_uid) < 0) { -+ if (seteuid(0) < 0 || seteuid(target_pwd->pw_uid) < 0) { -+ perror("ksu: seteuid"); -+ sweep_up(ksu_context, cc_tmp); -+ exit(1); -+ } -+ -+ retval = krb5_ccache_copy(ksu_context, cc_tmp, cc_target_tag, -+ client, &cc_target, &stored, -+ target_pwd->pw_uid); -+ if (retval) { -+ com_err(prog_name, retval, _("while copying cache %s to %s"), -+ krb5_cc_get_name(ksu_context, cc_tmp), cc_target_tag); -+ exit(1); -+ } -+ -+ if (setuid(0) < 0 || setuid(target_pwd->pw_uid) < 0) { - perror("ksu: setuid"); - sweep_up(ksu_context, cc_target); - exit(1); - } - -- if (access( cc_target_tag_tmp, R_OK | W_OK )){ -- com_err(prog_name, errno, -- _("%s does not have correct permissions for %s, %s aborted"), -- target_user, cc_target_tag_tmp, prog_name); -- exit(1); -+ /* set the cc env name to target */ -+ if (stored) { -+ if (krb5_cc_get_full_name(ksu_context, cc_target, -+ &cc_target_tag) == 0) { -+ if (set_env_var(KRB5_ENV_CCNAME, cc_target_tag)){ -+ fprintf(stderr, -+ _("ksu: couldn't set environment variable %s\n"), -+ KRB5_ENV_CCNAME); -+ sweep_up(ksu_context, cc_target); -+ exit(1); -+ } -+ krb5_free_string(ksu_context, cc_target_tag); -+ } else { -+ com_err(prog_name, retval, _("while reading cache name from %s"), -+ cc_target_tag); -+ exit(1); -+ } - } - - if ( cc_source) --- -1.8.5.3 - diff --git a/0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch b/0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch deleted file mode 100644 index ae96369..0000000 --- a/0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 85ac175a62fcd629592c049f2318fff79949884b Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Thu, 31 Oct 2013 15:43:49 -0400 -Subject: [PATCH 3/6] Learn to destroy the ccache we're copying from - -Add a flag to krb5_ccache_copy() which will instruct it to destroy a -source ccache after reading its contents. Using this when we copy the -creds from a MEMORY cache to somewhere else is necessary to avoid having -a subsequent call to krb5_cc_cache_match() select the MEMORY cache when -we're trying to have it search a different location by default. ---- - src/clients/ksu/ccache.c | 10 +++++++++- - src/clients/ksu/ksu.h | 2 +- - src/clients/ksu/main.c | 5 +++-- - 3 files changed, 13 insertions(+), 4 deletions(-) - -diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c -index 7917af2..90ba2f2 100644 ---- a/src/clients/ksu/ccache.c -+++ b/src/clients/ksu/ccache.c -@@ -47,12 +47,14 @@ void show_credential(); - */ - - krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, -- primary_principal, cc_out, stored, target_uid) -+ primary_principal, destroy_def, -+ cc_out, stored, target_uid) - /* IN */ - krb5_context context; - krb5_ccache cc_def; - char *cc_other_tag; - krb5_principal primary_principal; -+ krb5_boolean destroy_def; - uid_t target_uid; - /* OUT */ - krb5_ccache *cc_out; -@@ -80,6 +82,12 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - } - } - -+ if (destroy_def) { -+ retval = krb5_cc_destroy(context, cc_def); -+ if (retval) -+ return retval; -+ } -+ - *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr, - primary_principal); - -diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h -index 1d102a1..a889fb9 100644 ---- a/src/clients/ksu/ksu.h -+++ b/src/clients/ksu/ksu.h -@@ -108,7 +108,7 @@ extern krb5_error_code get_best_principal - /* ccache.c */ - extern krb5_error_code krb5_ccache_copy - (krb5_context, krb5_ccache, char *, krb5_principal, -- krb5_ccache *, krb5_boolean *, uid_t); -+ krb5_boolean, krb5_ccache *, krb5_boolean *, uid_t); - - 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 fa86c78..7497a2b 100644 ---- a/src/clients/ksu/main.c -+++ b/src/clients/ksu/main.c -@@ -28,6 +28,7 @@ - - #include "ksu.h" - #include "adm_proto.h" -+#include "../../lib/krb5/os/os-proto.h" - #include - #include - #include -@@ -481,7 +482,7 @@ main (argc, argv) - } else { - - retval = krb5_ccache_copy(ksu_context, cc_source, KRB5_TEMPORARY_CACHE, -- client, &cc_tmp, &stored, 0); -+ client, FALSE, &cc_tmp, &stored, 0); - if (retval) { - com_err(prog_name, retval, _("while copying cache %s to %s"), - krb5_cc_get_name(ksu_context, cc_source), -@@ -758,7 +759,7 @@ main (argc, argv) - } - - retval = krb5_ccache_copy(ksu_context, cc_tmp, cc_target_tag, -- client, &cc_target, &stored, -+ client, TRUE, &cc_target, &stored, - target_pwd->pw_uid); - if (retval) { - com_err(prog_name, retval, _("while copying cache %s to %s"), --- -1.8.5.3 - diff --git a/0003-Use-an-intermediate-memory-cache-in-ksu.patch b/0003-Use-an-intermediate-memory-cache-in-ksu.patch new file mode 100644 index 0000000..4bef600 --- /dev/null +++ b/0003-Use-an-intermediate-memory-cache-in-ksu.patch @@ -0,0 +1,417 @@ +From dccc80a469b1925fcfe7697406a69912efe4baa1 Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Wed, 30 Oct 2013 21:45:35 -0400 +Subject: [PATCH 3/7] Use an intermediate memory cache in ksu + +Instead of copying source or obtained creds into the target cache and +changing ownership if everything succeeds, copy them into a MEMORY: +cache and then, if everything succeeds, create the target cache as the +target user. + +We no longer need to clean up the temporary ccache when exiting in +most error cases. + +Use a fake principal name ("_ksu/_ksu@_ksu") as the primary holder of +the temporary cache so that we won't accidentally select it when we +make a subsequent call to krb5_cc_cache_match() (to be added in a +later patch) to find the target location where the creds should be +stored for use while running as the target user. +--- + src/clients/ksu/ccache.c | 10 +-- + src/clients/ksu/ksu.h | 4 +- + src/clients/ksu/main.c | 156 ++++++++++++++++++++++++----------------------- + 3 files changed, 87 insertions(+), 83 deletions(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index 5f57279..d0fc389 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -47,14 +47,15 @@ void show_credential(); + */ + + krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, +- primary_principal, restrict_creds, cc_out, +- stored, target_uid) ++ primary_principal, restrict_creds, ++ target_principal, cc_out, stored, target_uid) + /* 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; + /* OUT */ + krb5_ccache *cc_out; +@@ -86,10 +87,9 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, + return errno; + } + +- +- if ((retval = krb5_cc_initialize(context, *cc_other, primary_principal))){ ++ retval = krb5_cc_initialize(context, *cc_other, target_principal); ++ if (retval) + return retval; +- } + + if (restrict_creds) { + retval = krb5_store_some_creds(context, *cc_other, cc_def_creds_arr, +diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h +index e1e34f1..08bf01b 100644 +--- a/src/clients/ksu/ksu.h ++++ b/src/clients/ksu/ksu.h +@@ -106,8 +106,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_ccache *, krb5_boolean *, uid_t); ++(krb5_context, krb5_ccache, char *, krb5_principal, krb5_boolean, ++ krb5_principal, krb5_ccache *, krb5_boolean *, uid_t); + + 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 8c49f94..d1bb8ca 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -42,10 +42,13 @@ char * gb_err = NULL; + int quiet = 0; + /***********/ + ++#define KS_TEMPORARY_CACHE "MEMORY:_ksu" ++#define KS_TEMPORARY_PRINC "_ksu/_ksu@_ksu" + #define _DEF_CSH "/bin/csh" + static int set_env_var (char *, char *); + static void sweep_up (krb5_context, krb5_ccache); + static char * ontty (void); ++static krb5_error_code set_ccname_env(krb5_context, krb5_ccache); + static void print_status( const char *fmt, ...) + #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) + __attribute__ ((__format__ (__printf__, 1, 2))) +@@ -84,8 +87,8 @@ main (argc, argv) + int option=0; + int statusp=0; + krb5_error_code retval = 0; +- krb5_principal client = NULL; +- krb5_ccache cc_target = NULL; ++ krb5_principal client = NULL, tmp_princ = NULL; ++ krb5_ccache cc_tmp = NULL, cc_target = NULL; + krb5_context ksu_context; + char * cc_target_tag = NULL; + char * target_user = NULL; +@@ -93,7 +96,6 @@ main (argc, argv) + + krb5_ccache cc_source = NULL; + const char * cc_source_tag = NULL; +- uid_t source_gid; + const char * cc_source_tag_tmp = NULL; + char * cmd = NULL, * exec_cmd = NULL; + int errflg = 0; +@@ -342,8 +344,6 @@ main (argc, argv) + /* allocate space and copy the usernamane there */ + source_user = xstrdup(pwd->pw_name); + source_uid = pwd->pw_uid; +- source_gid = pwd->pw_gid; +- + + if (!strcmp(SOURCE_USER_LOGIN, target_user)){ + target_user = xstrdup (source_user); +@@ -435,25 +435,32 @@ main (argc, argv) + } + + /* +- Only when proper authentication and authorization +- takes place, the target user becomes the owner of the cache. +- */ +- +- /* we continue to run as source uid until +- the middle of the copy, when becomewe become the target user +- The cache is owned by the target user.*/ ++ * After proper authentication and authorization, populate a cache for the ++ * target user. ++ */ + ++ /* ++ * We read the set of creds we want to copy from the source ccache as the ++ * source uid, become root for authentication, and then become the target ++ * user to handle authorization and creating the target user's cache. ++ */ + + /* if root ksu's to a regular user, then + then only the credentials for that particular user + should be copied */ + + restrict_creds = (source_uid == 0) && (target_uid != 0); +- retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag, client, +- restrict_creds, &cc_target, &stored, target_uid); ++ retval = krb5_parse_name(ksu_context, KS_TEMPORARY_PRINC, &tmp_princ); ++ if (retval) { ++ 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); + if (retval) { + com_err(prog_name, retval, _("while copying cache %s to %s"), +- krb5_cc_get_name(ksu_context, cc_source), cc_target_tag); ++ krb5_cc_get_name(ksu_context, cc_source), KS_TEMPORARY_CACHE); + exit(1); + } + +@@ -473,7 +480,6 @@ main (argc, argv) + &kdc_server))){ + com_err(prog_name, retval, + _("while creating tgt for local realm")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +@@ -481,13 +487,12 @@ main (argc, argv) + "enter it here and are logged\n")); + fprintf(stderr, _(" in remotely using an unsecure " + "(non-encrypted) channel.\n")); +- if (krb5_get_tkt_via_passwd (ksu_context, &cc_target, client, +- kdc_server, &options, +- &zero_password) == FALSE){ ++ if (krb5_get_tkt_via_passwd(ksu_context, &cc_tmp, client, ++ kdc_server, &options, ++ &zero_password) == FALSE){ + + if (zero_password == FALSE){ + fprintf(stderr, _("Goodbye\n")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +@@ -506,48 +511,20 @@ main (argc, argv) + if (source_uid && (source_uid != target_uid)) { + char * client_name; + +- auth_val = krb5_auth_check(ksu_context, client, localhostname, &options, +- target_user,cc_target, &path_passwd, target_uid); ++ auth_val = krb5_auth_check(ksu_context, client, localhostname, ++ &options, target_user, cc_tmp, ++ &path_passwd, target_uid); + + /* if Kerberos authentication failed then exit */ + if (auth_val ==FALSE){ + fprintf(stderr, _("Authentication failed.\n")); + syslog(LOG_WARNING, "'%s %s' authentication failed for %s%s", + prog_name,target_user,source_user,ontty()); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +-#if 0 +- /* At best, this avoids a single kdc request +- It is hard to implement dealing with file permissions and +- is unnecessary. It is important +- to properly handle races in chown if this code is ever re-enabled. +- */ +- /* cache the tickets if possible in the source cache */ +- if (!path_passwd){ +- +- if ((retval = krb5_ccache_overwrite(ksu_context, cc_target, cc_source, +- client))){ +- com_err (prog_name, retval, +- "while copying cache %s to %s", +- krb5_cc_get_name(ksu_context, cc_target), +- krb5_cc_get_name(ksu_context, cc_source)); +- sweep_up(ksu_context, cc_target); +- exit(1); +- } +- if (chown(cc_source_tag_tmp, source_uid, source_gid)){ +- com_err(prog_name, errno, +- "while changing owner for %s", +- cc_source_tag_tmp); +- exit(1); +- } +- } +-#endif /*0*/ +- + if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) { + com_err(prog_name, retval, _("When unparsing name")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +@@ -560,7 +537,6 @@ main (argc, argv) + if (krb5_seteuid(target_uid)) { + com_err(prog_name, errno, _("while switching to target for " + "authorization check")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +@@ -568,14 +544,12 @@ main (argc, argv) + cmd, &authorization_val, &exec_cmd))){ + com_err(prog_name,retval, _("while checking authorization")); + krb5_seteuid(0); /*So we have some chance of sweeping up*/ +- sweep_up(ksu_context, cc_target); + exit(1); + } + + if (krb5_seteuid(0)) { + com_err(prog_name, errno, _("while switching back from target " + "after authorization check")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + if (authorization_val == TRUE){ +@@ -617,25 +591,25 @@ main (argc, argv) + + } + +- sweep_up(ksu_context, cc_target); + exit(1); + } + } + + if( some_rest_copy){ +- if ((retval = krb5_ccache_filter(ksu_context, cc_target, client))){ ++ retval = krb5_ccache_filter(ksu_context, cc_tmp, client); ++ if (retval) { + com_err(prog_name,retval, _("while calling cc_filter")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + } + + if (all_rest_copy){ +- if ((retval = krb5_cc_initialize(ksu_context, cc_target, client))){ ++ retval = krb5_cc_initialize(ksu_context, cc_tmp, tmp_princ); ++ if (retval) { + com_err(prog_name, retval, _("while erasing target cache")); + exit(1); + } +- ++ stored = FALSE; + } + + /* get the shell of the user, this will be the shell used by su */ +@@ -653,7 +627,6 @@ main (argc, argv) + + if (!standard_shell(target_pwd->pw_shell) && source_uid) { + fprintf(stderr, _("ksu: permission denied (shell).\n")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + #endif /* HAVE_GETUSERSHELL */ +@@ -663,43 +636,28 @@ main (argc, argv) + if(set_env_var("USER", target_pwd->pw_name)){ + fprintf(stderr, + _("ksu: couldn't set environment variable USER\n")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + } + + if(set_env_var( "HOME", target_pwd->pw_dir)){ + fprintf(stderr, _("ksu: couldn't set environment variable HOME\n")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + + if(set_env_var( "SHELL", shell)){ + fprintf(stderr, _("ksu: couldn't set environment variable SHELL\n")); +- sweep_up(ksu_context, cc_target); +- exit(1); +- } +- +- /* set the cc env name to target */ +- +- if(set_env_var( KRB5_ENV_CCNAME, cc_target_tag)){ +- fprintf(stderr, _("ksu: couldn't set environment variable %s\n"), +- KRB5_ENV_CCNAME); +- sweep_up(ksu_context, cc_target); + exit(1); + } + + /* set permissions */ + if (setgid(target_pwd->pw_gid) < 0) { + perror("ksu: setgid"); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +- + if (initgroups(target_user, target_pwd->pw_gid)) { + fprintf(stderr, _("ksu: initgroups failed.\n")); +- sweep_up(ksu_context, cc_target); + exit(1); + } + +@@ -719,13 +677,36 @@ main (argc, argv) + */ + if (setluid((uid_t) pwd->pw_uid) < 0) { + perror("setluid"); +- sweep_up(ksu_context, cc_target); + exit(1); + } + #endif /* HAVE_SETLUID */ + + if (setuid(target_pwd->pw_uid) < 0) { + perror("ksu: setuid"); ++ exit(1); ++ } ++ ++ retval = krb5_ccache_copy(ksu_context, cc_tmp, cc_target_tag, ++ client, FALSE, client, &cc_target, &stored, ++ target_pwd->pw_uid); ++ if (retval) { ++ com_err(prog_name, retval, _("while copying cache %s to %s"), ++ KS_TEMPORARY_CACHE, cc_target_tag); ++ exit(1); ++ } ++ ++ 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); ++ } ++ ++ free(cc_target_tag); ++ ++ /* Set the cc env name to target. */ ++ retval = set_ccname_env(ksu_context, cc_target); ++ if (retval != 0) { + sweep_up(ksu_context, cc_target); + exit(1); + } +@@ -799,6 +780,29 @@ main (argc, argv) + } + } + ++/* Set KRB5CCNAME in the environment to point to ccache. Print an error ++ * message on failure. */ ++static krb5_error_code ++set_ccname_env(krb5_context ksu_context, krb5_ccache ccache) ++{ ++ krb5_error_code retval; ++ char *ccname; ++ ++ retval = krb5_cc_get_full_name(ksu_context, ccache, &ccname); ++ if (retval) { ++ com_err(prog_name, retval, _("while reading cache name from ccache")); ++ return retval; ++ } ++ if (set_env_var(KRB5_ENV_CCNAME, ccname)) { ++ retval = errno; ++ fprintf(stderr, ++ _("ksu: couldn't set environment variable %s\n"), ++ KRB5_ENV_CCNAME); ++ } ++ krb5_free_string(ksu_context, ccname); ++ return retval; ++} ++ + #ifdef HAVE_GETUSERSHELL + + int standard_shell(sh) +-- +2.0.4 + 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 +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 + diff --git a/0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch b/0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch deleted file mode 100644 index bd78d12..0000000 --- a/0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch +++ /dev/null @@ -1,149 +0,0 @@ -From acbb59cd4b1759afe492b8503cddb0a2f719e6c8 Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Wed, 30 Oct 2013 21:47:14 -0400 -Subject: [PATCH 4/6] Try to use the default_ccache_name'd as the target - -Try to use the location named by the default_ccache_name setting as the -target cache. If it's a collection, just create or update a subsidiary -cache. If it's not, then fall back to creating a new cache to try to -avoid destroying the contents of one that might already be there. We -can't really detect this in advance for KEYRING: caches, though. ---- - src/clients/ksu/ksu.h | 2 +- - src/clients/ksu/main.c | 91 ++++++++++++++++++++++++++++++++++++-------------- - 2 files changed, 67 insertions(+), 26 deletions(-) - -diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h -index a889fb9..a195f52 100644 ---- a/src/clients/ksu/ksu.h -+++ b/src/clients/ksu/ksu.h -@@ -44,7 +44,7 @@ - #define KRB5_DEFAULT_OPTIONS 0 - #define KRB5_DEFAULT_TKT_LIFE 60*60*12 /* 12 hours */ - --#define KRB5_SECONDARY_CACHE "FILE:/tmp/krb5cc_" -+#define KRB5_DEFAULT_SECONDARY_CACHE "FILE:/tmp/krb5cc_%{uid}" - #define KRB5_TEMPORARY_CACHE "MEMORY:_ksu" - - #define KRB5_LOGIN_NAME ".k5login" -diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c -index 7497a2b..58df6a1 100644 ---- a/src/clients/ksu/main.c -+++ b/src/clients/ksu/main.c -@@ -90,7 +90,10 @@ main (argc, argv) - krb5_ccache cc_tmp = NULL, cc_target = NULL; - krb5_context ksu_context; - char * cc_target_tag = NULL; -+ char * cc_target_tag_conf; -+ krb5_boolean cc_target_switchable; - char * target_user = NULL; -+ char * target_user_uid_str; - char * source_user; - - krb5_ccache cc_source = NULL; -@@ -116,7 +119,6 @@ main (argc, argv) - krb5_boolean stored = FALSE; - krb5_principal kdc_server; - krb5_boolean zero_password; -- char * dir_of_cc_target; - - options.opt = KRB5_DEFAULT_OPTIONS; - options.lifetime = KRB5_DEFAULT_TKT_LIFE; -@@ -420,31 +422,70 @@ main (argc, argv) - } - - if (cc_target_tag == NULL) { -- - cc_target_tag = (char *)xcalloc(KRB5_SEC_BUFFSIZE ,sizeof(char)); -- /* 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.*/ -- -- do { -- snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%s%ld.%d", -- KRB5_SECONDARY_CACHE, -- (long) target_uid, gen_sym()); -- cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1; -- -- } while (krb5_ccache_name_is_initialized(ksu_context, -- cc_target_tag)); -- } -- -- -- dir_of_cc_target = get_dir_of_file(cc_target_tag_tmp); -- -- if (access(dir_of_cc_target, R_OK | W_OK )){ -- fprintf(stderr, -- _("%s does not have correct permissions for %s\n"), -- source_user, cc_target_tag); -- exit(1); -+ if (cc_target_tag == NULL) { -+ com_err(prog_name, retval , _("while allocating memory for the " -+ "target ccache name")); -+ exit(1); -+ } -+ /* Read the configured value. */ -+ if (profile_get_string(ksu_context->profile, KRB5_CONF_LIBDEFAULTS, -+ KRB5_CONF_DEFAULT_CCACHE_NAME, NULL, -+ KRB5_DEFAULT_SECONDARY_CACHE, -+ &cc_target_tag_conf)) { -+ com_err(prog_name, retval , _("while allocating memory for the " -+ "target ccache name")); -+ exit(1); -+ } -+ /* Prepend "FILE:" if a cctype wasn't specified in the config. */ -+ if (strchr(cc_target_tag_conf, ':')) { -+ cc_target_tag_tmp = strdup(cc_target_tag_conf); -+ } else { -+ if (asprintf(&cc_target_tag_tmp, "FILE:%s", -+ cc_target_tag_conf) < 0) -+ cc_target_tag_tmp = NULL; -+ } -+ profile_release_string(cc_target_tag_conf); -+ if (cc_target_tag_tmp == NULL) { -+ com_err(prog_name, retval , _("while allocating memory for the " -+ "target ccache name")); -+ exit(1); -+ } -+ /* Resolve parameters in the configured value for the target user. */ -+ if (asprintf(&target_user_uid_str, "%lu", -+ (unsigned long)target_uid) < 0) { -+ com_err(prog_name, retval , _("while allocating memory for the " -+ "target ccache name")); -+ exit(1); -+ } -+ if (k5_expand_path_tokens_extra(ksu_context, -+ cc_target_tag_tmp, &cc_target_tag_conf, -+ "euid", target_user_uid_str, -+ "uid", target_user_uid_str, -+ "USERID", target_user_uid_str, -+ "username", target_user, -+ NULL) != 0) { -+ com_err(prog_name, retval , _("while allocating memory for the " -+ "target ccache name")); -+ exit(1); -+ } -+ cc_target_tag_tmp[strcspn(cc_target_tag_tmp, ":")] = '\0'; -+ cc_target_switchable = krb5_cc_support_switch(ksu_context, -+ cc_target_tag_tmp); -+ free(cc_target_tag_tmp); -+ /* Try to avoid destroying a target ccache. */ -+ if (cc_target_switchable) { -+ snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%s", -+ cc_target_tag_conf); -+ } else { -+ do { -+ snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%s.%d", -+ cc_target_tag_conf, gen_sym()); -+ } while (krb5_ccache_name_is_initialized(ksu_context, -+ cc_target_tag)); -+ } -+ cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1; -+ krb5_free_string(ksu_context, cc_target_tag_conf); - } - - if (auth_debug){ --- -1.8.5.3 - diff --git a/0005-Be-more-careful-of-target-ccache-collections.patch b/0005-Be-more-careful-of-target-ccache-collections.patch deleted file mode 100644 index 5f9de36..0000000 --- a/0005-Be-more-careful-of-target-ccache-collections.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 5286fddf967af8952bd9d42d6d1ec1ddfcc159ad Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Wed, 30 Oct 2013 21:34:27 -0400 -Subject: [PATCH 5/6] Be more careful of target ccache collections - -When copying credentials to a cache collection, take care to avoid -generating multiple caches for a single client principal, but don't -change the primary out from anyone who might already be using the -target collection. ---- - src/clients/ksu/ccache.c | 62 ++++++++++++++++++++++++++++++++++++++++++------ - src/clients/ksu/ksu.h | 2 +- - src/clients/ksu/main.c | 11 +++++++-- - 3 files changed, 65 insertions(+), 10 deletions(-) - -diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c -index 90ba2f2..2a97893 100644 ---- a/src/clients/ksu/ccache.c -+++ b/src/clients/ksu/ccache.c -@@ -48,7 +48,7 @@ void show_credential(); - - krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - primary_principal, destroy_def, -- cc_out, stored, target_uid) -+ cc_out, stored, reused, target_uid) - /* IN */ - krb5_context context; - krb5_ccache cc_def; -@@ -59,10 +59,12 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - /* OUT */ - krb5_ccache *cc_out; - krb5_boolean *stored; -+ krb5_boolean *reused; - { - int i=0; - krb5_ccache * cc_other; - const char * cc_other_type; -+ char * saved_cc_default_name; - krb5_error_code retval=0; - krb5_creds ** cc_def_creds_arr = NULL; - krb5_creds ** cc_other_creds_arr = NULL; -@@ -99,9 +101,33 @@ krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, - return errno; - } - -- -- if ((retval = krb5_cc_initialize(context, *cc_other, primary_principal))){ -- return retval; -+ if (krb5_cc_support_switch(context, cc_other_type)) { -+ *reused = TRUE; -+ krb5_cc_close(context, *cc_other); -+ saved_cc_default_name = strdup(krb5_cc_default_name(context)); -+ krb5_cc_set_default_name(context, cc_other_tag); -+ if (krb5_cc_cache_match(context, primary_principal, cc_other) != 0) { -+ *reused = FALSE; -+ retval = krb5_cc_new_unique(context, cc_other_type, NULL, -+ cc_other); -+ if (retval) { -+ krb5_cc_set_default_name(context, saved_cc_default_name); -+ free(saved_cc_default_name); -+ return retval; -+ } -+ } -+ retval = krb5_cc_initialize(context, *cc_other, primary_principal); -+ krb5_cc_set_default_name(context, saved_cc_default_name); -+ free(saved_cc_default_name); -+ if (retval) { -+ return retval; -+ } -+ } else { -+ *reused = FALSE; -+ retval = krb5_cc_initialize(context, *cc_other, primary_principal); -+ if (retval) { -+ return retval; -+ } - } - - retval = krb5_store_all_creds(context, * cc_other, cc_def_creds_arr, -@@ -650,6 +676,7 @@ krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, - int i=0; - krb5_ccache * cc_other; - const char * cc_other_type; -+ char * saved_cc_default_name; - krb5_error_code retval=0; - krb5_creds ** cc_def_creds_arr = NULL; - krb5_creds ** cc_other_creds_arr = NULL; -@@ -677,9 +704,30 @@ krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, - return errno; - } - -- -- if ((retval = krb5_cc_initialize(context, *cc_other, prst))){ -- return retval; -+ if (krb5_cc_support_switch(context, cc_other_type)) { -+ krb5_cc_close(context, *cc_other); -+ saved_cc_default_name = strdup(krb5_cc_default_name(context)); -+ krb5_cc_set_default_name(context, cc_other_tag); -+ if (krb5_cc_cache_match(context, prst, cc_other) != 0) { -+ retval = krb5_cc_new_unique(context, cc_other_type, NULL, -+ cc_other); -+ if (retval) { -+ krb5_cc_set_default_name(context, saved_cc_default_name); -+ free(saved_cc_default_name); -+ return retval; -+ } -+ } -+ retval = krb5_cc_initialize(context, *cc_other, prst); -+ if (retval) { -+ return retval; -+ } -+ krb5_cc_set_default_name(context, saved_cc_default_name); -+ free(saved_cc_default_name); -+ } else { -+ retval = krb5_cc_initialize(context, *cc_other, prst); -+ if (retval) { -+ return retval; -+ } - } - - retval = krb5_store_some_creds(context, * cc_other, -diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h -index a195f52..b3ef7b9 100644 ---- a/src/clients/ksu/ksu.h -+++ b/src/clients/ksu/ksu.h -@@ -108,7 +108,7 @@ 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_ccache *, krb5_boolean *, uid_t); -+ krb5_boolean, krb5_ccache *, krb5_boolean *, krb5_boolean *, uid_t); - - 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 58df6a1..1c0c822 100644 ---- a/src/clients/ksu/main.c -+++ b/src/clients/ksu/main.c -@@ -117,6 +117,7 @@ main (argc, argv) - int pargc; - char ** pargv; - krb5_boolean stored = FALSE; -+ krb5_boolean reused = FALSE; - krb5_principal kdc_server; - krb5_boolean zero_password; - -@@ -523,7 +524,8 @@ main (argc, argv) - } else { - - retval = krb5_ccache_copy(ksu_context, cc_source, KRB5_TEMPORARY_CACHE, -- client, FALSE, &cc_tmp, &stored, 0); -+ client, FALSE, &cc_tmp, &stored, &reused, -+ 0); - if (retval) { - com_err(prog_name, retval, _("while copying cache %s to %s"), - krb5_cc_get_name(ksu_context, cc_source), -@@ -801,7 +803,7 @@ main (argc, argv) - - retval = krb5_ccache_copy(ksu_context, cc_tmp, cc_target_tag, - client, TRUE, &cc_target, &stored, -- target_pwd->pw_uid); -+ &reused, target_pwd->pw_uid); - if (retval) { - com_err(prog_name, retval, _("while copying cache %s to %s"), - krb5_cc_get_name(ksu_context, cc_tmp), cc_target_tag); -@@ -825,6 +827,11 @@ main (argc, argv) - sweep_up(ksu_context, cc_target); - exit(1); - } -+ if (reused && !keep_target_cache) { -+ print_status(_("Reusing cache %s, it will not be removed.\n"), -+ cc_target_tag); -+ keep_target_cache = TRUE; -+ } - krb5_free_string(ksu_context, cc_target_tag); - } else { - com_err(prog_name, retval, _("while reading cache name from %s"), --- -1.8.5.3 - diff --git a/0005-Copy-config-entries-to-the-ksu-target-ccache.patch b/0005-Copy-config-entries-to-the-ksu-target-ccache.patch new file mode 100644 index 0000000..e004136 --- /dev/null +++ b/0005-Copy-config-entries-to-the-ksu-target-ccache.patch @@ -0,0 +1,30 @@ +From 297496f0938955ba4aaf0ebecf4e393e527b8cbf Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Tue, 29 Oct 2013 16:27:20 -0400 +Subject: [PATCH 5/7] Copy config entries to the ksu target ccache + +When we try to screen out expired creds while reading them from one +ccache to eventually store in another, also keep configuration entries. + +ticket: 7986 (new) +--- + src/clients/ksu/ccache.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index 4693bd4..0f9e042 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -219,7 +219,8 @@ krb5_error_code krb5_get_nonexp_tkts(context, cc, creds_array) + + while (!(retval = krb5_cc_next_cred(context, cc, &cur, &creds))){ + +- if ((retval = krb5_check_exp(context, creds.times))){ ++ if (!krb5_is_config_principal(context, creds.server) && ++ (retval = krb5_check_exp(context, creds.times))){ + if (retval != KRB5KRB_AP_ERR_TKT_EXPIRED){ + return retval; + } +-- +2.0.4 + diff --git a/0006-Copy-config-entries-to-the-target-ccache.patch b/0006-Copy-config-entries-to-the-target-ccache.patch deleted file mode 100644 index e7d033c..0000000 --- a/0006-Copy-config-entries-to-the-target-ccache.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0d2a65745287238c5e5e2cc2fc68c40b358e68e4 Mon Sep 17 00:00:00 2001 -From: Nalin Dahyabhai -Date: Tue, 29 Oct 2013 16:27:20 -0400 -Subject: [PATCH 6/6] Copy config entries to the target ccache - -When we try to screen out expired creds while reading them from one -ccache to eventually store in another, also keep configuration entries. ---- - src/clients/ksu/ccache.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c -index 2a97893..83b5e46 100644 ---- a/src/clients/ksu/ccache.c -+++ b/src/clients/ksu/ccache.c -@@ -269,7 +269,8 @@ krb5_error_code krb5_get_nonexp_tkts(context, cc, creds_array) - - while (!(retval = krb5_cc_next_cred(context, cc, &cur, &creds))){ - -- if ((retval = krb5_check_exp(context, creds.times))){ -+ if (!krb5_is_config_principal(context, creds.server) && -+ (retval = krb5_check_exp(context, creds.times))){ - if (retval != KRB5KRB_AP_ERR_TKT_EXPIRED){ - return retval; - } --- -1.8.5.3 - diff --git a/0006-Use-more-randomness-for-ksu-secondary-cache-names.patch b/0006-Use-more-randomness-for-ksu-secondary-cache-names.patch new file mode 100644 index 0000000..da8a32a --- /dev/null +++ b/0006-Use-more-randomness-for-ksu-secondary-cache-names.patch @@ -0,0 +1,115 @@ +From 69c8e20b18577781e17c5959e23514134dfb5755 Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Thu, 24 Jul 2014 16:43:21 -0400 +Subject: [PATCH 6/7] Use more randomness for ksu secondary cache names + +When generating a suffix to append to a ccache name that will hold the +credentials for a ksu-invoked process, instead of using integers +counting up from 1, use the result of base64-encoding six randomly- +generated octets. Tweak the output alphabet just a bit to avoid using +'+' or '/' in the generated names, the latter of which could really +confuse things. +--- + src/clients/ksu/ccache.c | 27 +++++++++++++++++++++++---- + src/clients/ksu/ksu.h | 2 +- + src/clients/ksu/main.c | 16 ++++++++++++---- + 3 files changed, 36 insertions(+), 9 deletions(-) + +diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c +index 0f9e042..a0736f2 100644 +--- a/src/clients/ksu/ccache.c ++++ b/src/clients/ksu/ccache.c +@@ -27,6 +27,7 @@ + */ + + #include "ksu.h" ++#include "k5-base64.h" + #include "adm_proto.h" + #include + #include +@@ -504,10 +505,28 @@ show_credential(context, cred, cc) + free(sname); + } + +-int gen_sym(){ +- static int i = 0; +- i ++; +- return i; ++/* Create a random string suitable for a filename extension. */ ++krb5_error_code ++gen_sym(krb5_context context, char **sym_out) ++{ ++ krb5_error_code retval; ++ char bytes[6], *p, *sym; ++ krb5_data data = make_data(bytes, sizeof(bytes)); ++ ++ *sym_out = NULL; ++ retval = krb5_c_random_make_octets(context, &data); ++ if (retval) ++ return retval; ++ sym = k5_base64_encode(data.data, data.length); ++ if (sym == NULL) ++ return ENOMEM; ++ /* Tweak the output alphabet just a bit. */ ++ while ((p = strchr(sym, '/')) != NULL) ++ *p = '_'; ++ while ((p = strchr(sym, '+')) != NULL) ++ *p = '-'; ++ *sym_out = sym; ++ return 0; + } + + krb5_error_code krb5_ccache_overwrite(context, ccs, cct, primary_principal) +diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h +index fbbf217..5ba5ceb 100644 +--- a/src/clients/ksu/ksu.h ++++ b/src/clients/ksu/ksu.h +@@ -130,7 +130,7 @@ extern krb5_error_code krb5_get_login_princ + extern void show_credential + (krb5_context, krb5_creds *, krb5_ccache); + +-extern int gen_sym (void); ++krb5_error_code gen_sym(krb5_context context, char **sym); + + extern krb5_error_code krb5_ccache_overwrite + (krb5_context, krb5_ccache, krb5_ccache, krb5_principal); +diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c +index 41a3bf8..47fa820 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -856,7 +856,7 @@ resolve_target_cache(krb5_context context, krb5_principal princ, + krb5_error_code retval; + krb5_boolean switchable, reused = FALSE; + krb5_ccache ccache = NULL; +- char *sep, *ccname = NULL, *target; ++ char *sep, *ccname = NULL, *sym = NULL, *target; + + *ccache_out = NULL; + *ccache_reused = FALSE; +@@ -876,12 +876,20 @@ resolve_target_cache(krb5_context context, krb5_principal princ, + * the name of a cache that doesn't exist yet. */ + do { + free(ccname); +- if (asprintf(&ccname, "%s.%d", target, gen_sym()) < 0) { ++ retval = gen_sym(context, &sym); ++ if (retval) { ++ com_err(prog_name, retval, ++ _("while generating part of the target ccache name")); ++ return retval; ++ } ++ if (asprintf(&ccname, "%s.%s", target, sym) < 0) { + retval = ENOMEM; +- com_err(prog_name, ENOMEM, +- _("while allocating memory for target ccache name")); ++ free(sym); ++ com_err(prog_name, retval, _("while allocating memory for the " ++ "target ccache name")); + goto cleanup; + } ++ free(sym); + } while (ks_ccache_name_is_initialized(context, ccname)); + retval = krb5_cc_resolve(context, ccname, &ccache); + } else { +-- +2.0.4 + diff --git a/0007-Make-krb5_cc_new_unique-create-DIR-directories.patch b/0007-Make-krb5_cc_new_unique-create-DIR-directories.patch new file mode 100644 index 0000000..c0b8778 --- /dev/null +++ b/0007-Make-krb5_cc_new_unique-create-DIR-directories.patch @@ -0,0 +1,37 @@ +Context tweaked to apply to 1.12.1. + +From bca1191210eb582fe09e94486e2631d72b8a5ca5 Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Fri, 8 Aug 2014 16:58:03 -0400 +Subject: [PATCH 7/7] Make krb5_cc_new_unique create DIR: directories + +When we use krb5_cc_new_unique to create a new cache in a directory +cache collection, we will fail if the directory doesn't exist yet. + +Go ahead and preemptively create it, as we do during krb5_cc_resolve, +before attempting to create a new file under it. + +ticket: 7988 (new) +target_version: 1.13 +tags: pullup +--- + src/lib/krb5/ccache/cc_dir.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c +index d82f335..b00a6bb 100644 +--- a/src/lib/krb5/ccache/cc_dir.c ++++ b/src/lib/krb5/ccache/cc_dir.c +@@ -401,6 +401,9 @@ dcc_gen_new(krb5_context context, krb5_ccache *cache_out) + "collection")); + return KRB5_DCC_CANNOT_CREATE; + } ++ ret = verify_dir(context, dirname); ++ if (ret) ++ goto cleanup; + ret = k5_path_join(dirname, "tktXXXXXX", &template); + if (ret) + goto cleanup; +-- +2.0.4 + diff --git a/krb5-1.12.1-pam.patch b/krb5-1.12.1-pam.patch index 3bcdb34..5a8e65e 100644 --- a/krb5-1.12.1-pam.patch +++ b/krb5-1.12.1-pam.patch @@ -96,7 +96,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c +#include "autoconf.h" #include "ksu.h" #include "adm_proto.h" - #include "../../lib/krb5/os/os-proto.h" + #include @@ -33,6 +34,10 @@ #include #include @@ -115,8 +115,8 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c +int force_fork = 0; /***********/ - #define _DEF_CSH "/bin/csh" -@@ -586,6 +592,25 @@ main (argc, argv) + #define KS_TEMPORARY_CACHE "MEMORY:_ksu" +@@ -586,6 +592,23 @@ main (argc, argv) prog_name,target_user,client_name, source_user,ontty()); @@ -126,13 +126,11 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c + NULL, source_user, + ttyname(STDERR_FILENO)) != 0) { + fprintf(stderr, "Access denied for %s.\n", target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } + if (appl_pam_requires_chauthtok()) { + fprintf(stderr, "Password change required for %s.\n", + target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } + force_fork++; @@ -142,8 +140,8 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c /* Run authorization as target.*/ if (krb5_seteuid(target_uid)) { com_err(prog_name, errno, _("while switching to target for " -@@ -651,6 +676,26 @@ - sweep_up(ksu_context, cc_tmp); +@@ -651,6 +676,24 @@ + exit(1); } +#ifdef USE_PAM @@ -154,13 +152,11 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c + NULL, source_user, + ttyname(STDERR_FILENO)) != 0) { + fprintf(stderr, "Access denied for %s.\n", target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } + if (appl_pam_requires_chauthtok()) { + fprintf(stderr, "Password change required for %s.\n", + target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } + force_fork++; @@ -169,7 +165,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c } if( some_rest_copy){ -@@ -720,6 +745,32 @@ +@@ -720,6 +745,30 @@ exit(1); } @@ -177,7 +173,6 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c + if (appl_pam_enabled(ksu_context, "ksu")) { + if (appl_pam_session_open() != 0) { + fprintf(stderr, "Error opening session for %s.\n", target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } +#ifdef DEBUG @@ -188,7 +183,6 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c + if (appl_pam_cred_init()) { + fprintf(stderr, "Error initializing credentials for %s.\n", + target_user); -+ sweep_up(ksu_context, cc_tmp); + exit(1); + } +#ifdef DEBUG diff --git a/krb5.spec b/krb5.spec index 47da922..8279931 100644 --- a/krb5.spec +++ b/krb5.spec @@ -110,12 +110,13 @@ Patch148: krb5-gssapi-mech-doublefree.patch Patch149: krb5-gssapi-spnego-deref.patch Patch150: http://web.mit.edu/kerberos/advisories/2014-001-patch.txt Patch151: http://web.mit.edu/kerberos/advisories/2014-001-patch.txt.asc -Patch201: 0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch -Patch202: 0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch -Patch203: 0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch -Patch204: 0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch -Patch205: 0005-Be-more-careful-of-target-ccache-collections.patch -Patch206: 0006-Copy-config-entries-to-the-target-ccache.patch +Patch201: 0001-In-ksu-merge-krb5_ccache_copy-and-_restricted.patch +Patch202: 0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals.patch +Patch203: 0003-Use-an-intermediate-memory-cache-in-ksu.patch +Patch204: 0004-Make-ksu-respect-the-default_ccache_name-setting.patch +Patch205: 0005-Copy-config-entries-to-the-ksu-target-ccache.patch +Patch206: 0006-Use-more-randomness-for-ksu-secondary-cache-names.patch +Patch207: 0007-Make-krb5_cc_new_unique-create-DIR-directories.patch License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -318,14 +319,15 @@ certificate. %setup -q -a 3 -a 100 -a 102 ln -s NOTICE LICENSE -%patch1 -p1 -b .pwdch-fast +%patch201 -p1 -b .In-ksu-merge-krb5_ccache_copy-and-_restricted +%patch202 -p1 -b .In-ksu-don-t-stat-not-on-disk-ccache-residuals +%patch203 -p1 -b .Use-an-intermediate-memory-cache-in-ksu +%patch204 -p1 -b .Make-ksu-respect-the-default_ccache_name-setting +%patch205 -p1 -b .Copy-config-entries-to-the-ksu-target-ccache +%patch206 -p1 -b .Use-more-randomness-for-ksu-secondary-cache-names +%patch207 -p1 -b .Make-krb5_cc_new_unique-create-DIR-directories -%patch201 -p1 -b .Don-t-try-to-stat-not-on-disk-ccache-residuals -%patch202 -p1 -b .Use-an-in-memory-cache-until-we-need-the-target-s -%patch203 -p1 -b .Learn-to-destroy-the-ccache-we-re-copying-from -%patch204 -p1 -b .Try-to-use-the-default_ccache_name-d-as-the-target -%patch205 -p1 -b .Be-more-careful-of-target-ccache-collections -%patch206 -p1 -b .Copy-config-entries-to-the-target-ccache +%patch1 -p1 -b .pwdch-fast %patch60 -p1 -b .pam @@ -1043,6 +1045,10 @@ exit 0 %{_sbindir}/uuserver %changelog +* Fri Aug 15 2014 Nalin Dahyabhai +- replace older proposed changes for ksu with backports of the changes + after review and merging upstream (#1015559, #1026099, #1118347) + * Thu Aug 7 2014 Nalin Dahyabhai - 1.12.1-14 - incorporate fix for MITKRB5-SA-2014-001 (CVE-2014-4345) -- cgit