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