[krb5/f19] Drop call-access()-more patch for ksu

Nalin Dahyabhai nalin at fedoraproject.org
Fri Jan 31 21:56:02 UTC 2014


commit 414f99e0e8b86c8e3679a1cabcd8e17888bccea0
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date:   Fri Jan 31 16:25:49 2014 -0500

    Drop call-access()-more patch for ksu
    
    - drop patch to add additional access() checks to ksu - they add to
      breakage when non-FILE: caches are in use (#1026099), shouldn't be
      resulting in any benefit, and clash with proposed changes to fix its
      cache handling

 0000-ksu-intermediates.patch                       |   13 +
 ...-try-to-stat-not-on-disk-ccache-residuals.patch |  316 +++++++++++++++++++
 ...n-memory-cache-until-we-need-the-target-s.patch |  321 ++++++++++++++++++++
 ...-to-destroy-the-ccache-we-re-copying-from.patch |   95 ++++++
 ...e-the-default_ccache_name-d-as-the-target.patch |  149 +++++++++
 ...more-careful-of-target-ccache-collections.patch |  179 +++++++++++
 ...-Copy-config-entries-to-the-target-ccache.patch |   28 ++
 krb5-1.10-ksu-access.patch                         |   47 ---
 krb5-1.11-pam.patch                                |   19 +-
 krb5.spec                                          |   30 ++-
 10 files changed, 1138 insertions(+), 59 deletions(-)
---
diff --git a/0000-ksu-intermediates.patch b/0000-ksu-intermediates.patch
new file mode 100644
index 0000000..d567116
--- /dev/null
+++ b/0000-ksu-intermediates.patch
@@ -0,0 +1,13 @@
+Collect changes that prevent the ksu collections changes from being directly
+pullable from master (or, as of this writing, the proposed changes for master).
+--- krb5/src/clients/ksu/main.c
++++ krb5/src/clients/ksu/main.c
+@@ -706,7 +706,7 @@ main (argc, argv)
+     }
+ 
+     if(set_env_var( "HOME", target_pwd->pw_dir)){
+-        fprintf(stderr, _("ksu: couldn't set environment variable USER\n"));
++        fprintf(stderr, _("ksu: couldn't set environment variable HOME\n"));
+         sweep_up(ksu_context, cc_target);
+         exit(1);
+     }
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 at 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 at 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 at 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 at 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 at 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 at 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
+
diff --git a/krb5-1.11-pam.patch b/krb5-1.11-pam.patch
index 55c3ddf..9e1d516 100644
--- a/krb5-1.11-pam.patch
+++ b/krb5-1.11-pam.patch
@@ -9,7 +9,8 @@ section of /etc/krb5.conf.
 When enabled, ksu gains a dependency on libpam.
 
 Originally RT#5939, though it's changed since then to perform the account
-and session management before dropping privileges.
+and session management before dropping privileges, and to apply on top of
+changes we're proposing for how it handles cache collections.
 
 diff -up krb5-1.8/src/aclocal.m4.pam krb5-1.8/src/aclocal.m4
 --- krb5-1.8/src/aclocal.m4.pam	2009-11-22 12:00:45.000000000 -0500
@@ -95,7 +96,7 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/src/clients/ksu/main.c
 +#include "autoconf.h"
  #include "ksu.h"
  #include "adm_proto.h"
- #include <sys/types.h>
+ #include "../../lib/krb5/os/os-proto.h"
 @@ -33,6 +34,10 @@
  #include <signal.h>
  #include <grp.h>
@@ -125,13 +126,13 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/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_target);
++                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_target);
++                sweep_up(ksu_context, cc_tmp);
 +                exit(1);
 +            }
 +            force_fork++;
@@ -142,7 +143,7 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/src/clients/ksu/main.c
          if (krb5_seteuid(target_uid)) {
              com_err(prog_name, errno, _("while switching to target for "
 @@ -651,6 +676,26 @@
-             sweep_up(ksu_context, cc_target);
+             sweep_up(ksu_context, cc_tmp);
              exit(1);
          }
 +#ifdef USE_PAM
@@ -153,13 +154,13 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/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_target);
++                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_target);
++                sweep_up(ksu_context, cc_tmp);
 +                exit(1);
 +            }
 +            force_fork++;
@@ -176,7 +177,7 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/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_target);
++            sweep_up(ksu_context, cc_tmp);
 +            exit(1);
 +        }
 +#ifdef DEBUG
@@ -187,7 +188,7 @@ diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/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_target);
++            sweep_up(ksu_context, cc_tmp);
 +            exit(1);
 +        }
 +#ifdef DEBUG
diff --git a/krb5.spec b/krb5.spec
index 96a9688..daa9b0e 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -32,7 +32,7 @@
 Summary: The Kerberos network authentication system
 Name: krb5
 Version: 1.11.3
-Release: 19%{?dist}
+Release: 20%{?dist}
 # Maybe we should explode from the now-available-to-everybody tarball instead?
 # http://web.mit.edu/kerberos/dist/krb5/1.11/krb5-1.11.3-signed.tar
 Source0: krb5-%{version}.tar.gz
@@ -65,7 +65,6 @@ BuildRequires: cmake
 Source100: nss_wrapper-0.0-20130719153839Z.git6cb59864.bz2
 Source101: noport.c
 
-Patch5: krb5-1.10-ksu-access.patch
 Patch6: krb5-1.10-ksu-path.patch
 Patch12: krb5-1.7-ktany.patch
 Patch16: krb5-1.10-buildconf.patch
@@ -124,6 +123,15 @@ Patch201: krb5-1.11.2-keycheck.patch
 Patch202: krb5-1.11.2-otp.patch
 Patch203: krb5-1.11.3-otp2.patch
 
+# Patches to teach ksu about cache collections
+Patch300: 0000-ksu-intermediates.patch
+Patch301: 0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch
+Patch302: 0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch
+Patch303: 0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch
+Patch304: 0004-Try-to-use-the-default_ccache_name-d-as-the-target.patch
+Patch305: 0005-Be-more-careful-of-target-ccache-collections.patch
+Patch306: 0006-Copy-config-entries-to-the-target-ccache.patch
+
 License: MIT
 URL: http://web.mit.edu/kerberos/www/
 Group: System Environment/Libraries
@@ -318,11 +326,18 @@ certificate.
 %setup -q -n %{name}-%{version} -a 3 -a 100
 ln -s NOTICE LICENSE
 
+%patch300 -p1 -b .ksu-intermediates
+%patch301 -p1 -b .Don-t-try-to-stat-not-on-disk-ccache-residuals
+%patch302 -p1 -b .Use-an-in-memory-cache-until-we-need-the-target-s
+%patch303 -p1 -b .Learn-to-destroy-the-ccache-we-re-copying-from
+%patch304 -p1 -b .Try-to-use-the-default_ccache_name-d-as-the-target
+%patch305 -p1 -b .Be-more-careful-of-target-ccache-collections
+%patch306 -p1 -b .Copy-config-entries-to-the-target-ccache
+
 %patch60 -p1 -b .pam
 
 %patch63 -p1 -b .selinux-label
 
-%patch5  -p1 -b .ksu-access
 %patch6  -p1 -b .ksu-path
 %patch12 -p1 -b .ktany
 %patch16 -p1 -b .buildconf %{?_rawbuild}
@@ -967,6 +982,15 @@ exit 0
 %{_sbindir}/uuserver
 
 %changelog
+* Fri Jan 31 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.11.3-20
+- add currently-proposed changes to teach ksu about credential cache
+  collections and the default_ccache_name setting (#1015559,#1026099)
+
+* Fri Jan 31 2014 Nalin Dahyabhai <nalin at redhat.com>
+- drop patch to add additional access() checks to ksu - they add to breakage
+  when non-FILE: caches are in use (#1026099), shouldn't be resulting in any
+  benefit, and clash with proposed changes to fix its cache handling
+
 * Tue Jan 21 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.11.3-19
 - pull in and backport multiple changes to allow replay caches to be added to
   a GSS credential store as "rcache"-type credentials (RT#7818/#7819/#7836,


More information about the scm-commits mailing list