summaryrefslogtreecommitdiffstats
path: root/0003-Use-an-intermediate-memory-cache-in-ksu.patch
diff options
context:
space:
mode:
Diffstat (limited to '0003-Use-an-intermediate-memory-cache-in-ksu.patch')
-rw-r--r--0003-Use-an-intermediate-memory-cache-in-ksu.patch417
1 files changed, 417 insertions, 0 deletions
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
+