[krb5] Add those proposed patches

Nalin Dahyabhai nalin at fedoraproject.org
Wed Feb 5 19:53:41 UTC 2014


commit 99444865b14d08eea4114601e02c767d39b26bc2
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date:   Wed Feb 5 14:53:25 2014 -0500

    Add those proposed patches
    
    ... as referenced by 9b18d26ce3864e6d502b76e1151f1dfc92569650

 ...-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 ++
 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 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
+


More information about the scm-commits mailing list