summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2014-02-05 14:53:25 -0500
committerNalin Dahyabhai <nalin@dahyabhai.net>2014-02-05 14:53:25 -0500
commit99444865b14d08eea4114601e02c767d39b26bc2 (patch)
tree326e062a0b2701107349dab3811da639ea52ced8
parent419c14d6ac987d39eb4b60194f10fc4f1bc6384b (diff)
downloadkrb5-99444865b14d08eea4114601e02c767d39b26bc2.tar.gz
krb5-99444865b14d08eea4114601e02c767d39b26bc2.tar.xz
krb5-99444865b14d08eea4114601e02c767d39b26bc2.zip
Add those proposed patcheskrb5-1.12.1-3.fc21
... as referenced by 9b18d26ce3864e6d502b76e1151f1dfc92569650
-rw-r--r--0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch316
-rw-r--r--0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch321
-rw-r--r--0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch95
-rw-r--r--0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch149
-rw-r--r--0005-Be-more-careful-of-target-ccache-collections.patch179
-rw-r--r--0006-Copy-config-entries-to-the-target-ccache.patch28
6 files changed, 1088 insertions, 0 deletions
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
new file mode 100644
index 0000000..ac6ce53
--- /dev/null
+++ b/0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch
@@ -0,0 +1,316 @@
+From 9f902f70a79ab864083078d104196a83943844ac Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@redhat.com>
+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/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
new file mode 100644
index 0000000..ef62793
--- /dev/null
+++ b/0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch
@@ -0,0 +1,321 @@
+From 5195c2b20593330192feff67dd5f271e88f562e7 Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@dahyabhai.net>
+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
new file mode 100644
index 0000000..ae96369
--- /dev/null
+++ b/0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch
@@ -0,0 +1,95 @@
+From 85ac175a62fcd629592c049f2318fff79949884b Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@redhat.com>
+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 <sys/types.h>
+ #include <sys/wait.h>
+ #include <signal.h>
+@@ -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/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
new file mode 100644
index 0000000..bd78d12
--- /dev/null
+++ b/0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch
@@ -0,0 +1,149 @@
+From acbb59cd4b1759afe492b8503cddb0a2f719e6c8 Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@dahyabhai.net>
+Date: Wed, 30 Oct 2013 21:47:14 -0400
+Subject: [PATCH 4/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
new file mode 100644
index 0000000..5f9de36
--- /dev/null
+++ b/0005-Be-more-careful-of-target-ccache-collections.patch
@@ -0,0 +1,179 @@
+From 5286fddf967af8952bd9d42d6d1ec1ddfcc159ad Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@dahyabhai.net>
+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/0006-Copy-config-entries-to-the-target-ccache.patch b/0006-Copy-config-entries-to-the-target-ccache.patch
new file mode 100644
index 0000000..e7d033c
--- /dev/null
+++ b/0006-Copy-config-entries-to-the-target-ccache.patch
@@ -0,0 +1,28 @@
+From 0d2a65745287238c5e5e2cc2fc68c40b358e68e4 Mon Sep 17 00:00:00 2001
+From: Nalin Dahyabhai <nalin@dahyabhai.net>
+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
+