[openssh] move kerberos cache to /run/user/<uid>/ by default (#848228) fix kerberos cache handling to allow su

plautrba plautrba at fedoraproject.org
Mon Jun 17 15:32:14 UTC 2013


commit aacd017a6da9be6de296b0e2bbc13f922e7011b8
Author: Petr Lautrbach <plautrba at redhat.com>
Date:   Mon Jun 17 17:29:55 2013 +0200

    move kerberos cache to /run/user/<uid>/ by default (#848228)
    fix kerberos cache handling to allow sucessful ticket forwarding

 openssh-6.2p1-gsskex.patch |  153 ++++++++++++++++++++++++++++++++------------
 1 files changed, 111 insertions(+), 42 deletions(-)
---
diff --git a/openssh-6.2p1-gsskex.patch b/openssh-6.2p1-gsskex.patch
index 3934dcf..d6f0810 100644
--- a/openssh-6.2p1-gsskex.patch
+++ b/openssh-6.2p1-gsskex.patch
@@ -105,56 +105,79 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
  #include <krb5.h>
  
  extern ServerOptions	 options;
-@@ -170,8 +171,13 @@ auth_krb5_password(Authctxt *authctxt, c
+@@ -77,6 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c
+ #endif
+ 	krb5_error_code problem;
+ 	krb5_ccache ccache = NULL;
++	const char *ccache_type;
+ 	int len;
+ 	char *client, *platform_client;
+ 
+@@ -166,12 +168,30 @@ auth_krb5_password(Authctxt *authctxt, c
+ 		goto out;
+ #endif
+ 
++	ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
+ 	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
  
- 	len = strlen(authctxt->krb5_ticket_file) + 6;
+-	len = strlen(authctxt->krb5_ticket_file) + 6;
++	if (authctxt->krb5_ticket_file[0] == ':')
++		authctxt->krb5_ticket_file++;
++
++	len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type);
  	authctxt->krb5_ccname = xmalloc(len);
 -	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
++
 +#ifdef USE_CCAPI
 +	snprintf(authctxt->krb5_ccname, len, "API:%s",
  	    authctxt->krb5_ticket_file);
 +#else
-+	snprintf(authctxt->krb5_ccname, len, "DIR:%s",
-+	    authctxt->krb5_ticket_file);
++	snprintf(authctxt->krb5_ccname, len, "%s:%s",
++	    ccache_type, authctxt->krb5_ticket_file);
 +#endif
++
++	if (strcmp(ccache_type, "DIR") == 0) {
++		char *p;
++		p = strrchr(authctxt->krb5_ccname, '/');
++		if (p)
++			*p = '\0';
++	}
++
  
  #ifdef USE_PAM
  	if (options.use_pam)
-@@ -208,10 +214,33 @@ auth_krb5_password(Authctxt *authctxt, c
+@@ -208,10 +228,30 @@ auth_krb5_password(Authctxt *authctxt, c
  void
  krb5_cleanup_proc(Authctxt *authctxt)
  {
 +	struct stat krb5_ccname_stat;
-+	char krb5_ccname[128], *krb5_ccname_dir_end;
++	char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
 +
  	debug("krb5_cleanup_proc called");
  	if (authctxt->krb5_fwd_ccache) {
  		krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
  		authctxt->krb5_fwd_ccache = NULL;
 +
-+		/* assume ticket cache type DIR - DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */
-+		strncpy(krb5_ccname, authctxt->krb5_ccname + strlen("DIR::"), sizeof(krb5_ccname) - 10);
++		strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
++		krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
++		strcat(krb5_ccname_dir_start, "/primary");
 +
-+		krb5_ccname_dir_end = strrchr(krb5_ccname, '/');
-+		if (krb5_ccname_dir_end != NULL) {
-+			strcpy(krb5_ccname_dir_end, "/primary");
-+
-+			if (stat(krb5_ccname, &krb5_ccname_stat) == 0) {
-+				if (unlink(krb5_ccname) == 0) {
-+					*krb5_ccname_dir_end = '\0';
-+					if (rmdir(krb5_ccname) == -1)
-+						debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno));
-+				}
-+				else
-+					debug("cache primary file '%s', remove failed: %s",
-+						krb5_ccname, strerror(errno)
-+					);
++		if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
++			if (unlink(krb5_ccname_dir_start) == 0) {
++				krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
++				*krb5_ccname_dir_end = '\0';
++				if (rmdir(krb5_ccname_dir_start) == -1)
++					debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno));
 +			}
++			else
++				debug("cache primary file '%s', remove failed: %s",
++					krb5_ccname_dir_start, strerror(errno)
++					);
 +		}
  	}
  	if (authctxt->krb5_user) {
  		krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
-@@ -226,31 +255,37 @@ krb5_cleanup_proc(Authctxt *authctxt)
+@@ -226,31 +266,45 @@ krb5_cleanup_proc(Authctxt *authctxt)
  #ifndef HEIMDAL
  krb5_error_code
  ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
@@ -162,17 +185,17 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
 -	char ccname[40];
 +	int ret, oerrno;
 +	char ccname[128];
- 	mode_t old_umask;
 +#ifdef USE_CCAPI
 +	char cctemplate[] = "API:krb5cc_%d";
 +#else
-+	char cctemplate[] = "DIR:/tmp/krb5cc_%d_XXXXXXXXXX";
+ 	mode_t old_umask;
++	char cctemplate[] = "DIR:/run/user/%d/krb5cc_XXXXXXXXXX";
 +	char *tmpdir;
 +#endif
  
- 	ret = snprintf(ccname, sizeof(ccname),
+-	ret = snprintf(ccname, sizeof(ccname),
 -	    "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
-+	    cctemplate, geteuid());
++	ret = snprintf(ccname, sizeof(ccname), cctemplate, geteuid());
  	if (ret < 0 || (size_t)ret >= sizeof(ccname))
  		return ENOMEM;
  
@@ -182,11 +205,20 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
 +	old_umask = umask(0077);
 +	tmpdir = mkdtemp(ccname + strlen("DIR:"));
  	oerrno = errno;
++	if (tmpdir == NULL && errno == ENOENT) {
++		/* /run/user/uid doesn't exist -> fallback to /tmp */
++		ret = snprintf(ccname, sizeof(ccname), "DIR:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
++		if (ret < 0 || (size_t)ret >= sizeof(ccname))
++			return ENOMEM;
++		tmpdir = mkdtemp(ccname + strlen("DIR:"));
++		oerrno = errno;
++	}
++
  	umask(old_umask);
 -	if (tmpfd == -1) {
 -		logit("mkstemp(): %.100s", strerror(oerrno));
 +	if (tmpdir == NULL) {
-+		logit("mkdtemp(): %.100s", strerror(oerrno));
++		logit("mkdtemp(): %s - %.100s", ccname, strerror(oerrno));
  		return oerrno;
  	}
  
@@ -195,7 +227,7 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
  		oerrno = errno;
 -		logit("fchmod(): %.100s", strerror(oerrno));
 -		close(tmpfd);
-+		logit("chmod(): %.100s", strerror(oerrno));
++		logit("chmod(): %s - %.100s", ccname, strerror(oerrno));
  		return oerrno;
  	}
 -	close(tmpfd);
@@ -934,7 +966,7 @@ diff -up openssh-6.2p1/gss-serv.c.gsskex openssh-6.2p1/gss-serv.c
  		    gssapi_client.store.filename);
  		unlink(gssapi_client.store.filename);
 +
-+		/* Ticket cache: DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */
++		/* Ticket cache: DIR::/run/user/13558/krb5cc_T9eDKSQvzb/tkt */
 +		/* same code as in auth-krb5.c:krb5_cleanup_proc */
 +		strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10);
 +		krb5_ccname_dir_end = strrchr(krb5_ccname, '/');
@@ -1087,19 +1119,21 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
-@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+@@ -119,7 +119,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ 	krb5_error_code problem;
  	krb5_principal princ;
  	OM_uint32 maj_status, min_status;
- 	int len;
-+	const char *new_ccname;
+-	int len;
++	const char *new_ccname, *new_cctype;
  
  	if (client->creds == NULL) {
  		debug("No credentials stored");
-@@ -168,11 +169,18 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+@@ -168,11 +168,25 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
  		return;
  	}
  
 -	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
++	new_cctype = krb5_cc_get_type(krb_context, ccache);
 +	new_ccname = krb5_cc_get_name(krb_context, ccache);
 +
  	client->store.envvar = "KRB5CCNAME";
@@ -1110,15 +1144,21 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
 +	xasprintf(&client->store.envval, "API:%s", new_ccname);
 +	client->store.filename = NULL;
 +#else
-+	xasprintf(&client->store.envval, "DIR:%s", new_ccname);
 +	if (new_ccname[0] == ':')
 +		new_ccname++;
++	xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
++	if (strcmp(new_cctype, "DIR") == 0) {
++		char *p;
++		p = strrchr(client->store.envval, '/');
++		if (p)
++			*p = '\0';
++	}
 +	client->store.filename = xstrdup(new_ccname);
 +#endif
  
  #ifdef USE_PAM
  	if (options.use_pam)
-@@ -184,6 +192,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+@@ -184,6 +198,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
  	return;
  }
  
@@ -1190,7 +1230,7 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
  ssh_gssapi_mech gssapi_kerberos_mech = {
  	"toWM5Slw5Ew8Mqkay+al2g==",
  	"Kerberos",
-@@ -191,7 +264,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
+@@ -191,7 +270,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
  	NULL,
  	&ssh_gssapi_krb5_userok,
  	NULL,
@@ -2273,7 +2313,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
  #endif
  	{ "fallbacktorsh", oDeprecated },
  	{ "usersh", oDeprecated },
-@@ -483,10 +494,30 @@ parse_flag:
+@@ -503,10 +514,30 @@ parse_flag:
  		intptr = &options->gss_authentication;
  		goto parse_flag;
  
@@ -2304,7 +2344,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
  	case oBatchMode:
  		intptr = &options->batch_mode;
  		goto parse_flag;
-@@ -1139,7 +1170,12 @@ initialize_options(Options * options)
+@@ -1158,7 +1189,12 @@ initialize_options(Options * options)
  	options->pubkey_authentication = -1;
  	options->challenge_response_authentication = -1;
  	options->gss_authentication = -1;
@@ -2317,7 +2357,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
  	options->password_authentication = -1;
  	options->kbd_interactive_authentication = -1;
  	options->kbd_interactive_devices = NULL;
-@@ -1239,8 +1275,14 @@ fill_default_options(Options * options)
+@@ -1258,8 +1294,14 @@ fill_default_options(Options * options)
  		options->challenge_response_authentication = 1;
  	if (options->gss_authentication == -1)
  		options->gss_authentication = 0;
@@ -2806,7 +2846,36 @@ diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c
  	/*
  	 * We don't want to listen forever unless the other side
  	 * successfully authenticates itself.  So we set up an alarm which is
-@@ -2466,6 +2527,48 @@ do_ssh2_kex(void)
+@@ -2139,14 +2200,6 @@ main(int ac, char **av)
+ #ifdef SSH_AUDIT_EVENTS
+ 	audit_event(SSH_AUTH_SUCCESS);
+ #endif
+-
+-#ifdef GSSAPI
+-	if (options.gss_authentication) {
+-		temporarily_use_uid(authctxt->pw);
+-		ssh_gssapi_storecreds();
+-		restore_uid();
+-	}
+-#endif
+ #ifdef WITH_SELINUX
+ 	ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
+ #endif
+@@ -2156,6 +2209,13 @@ main(int ac, char **av)
+ 		do_pam_session();
+ 	}
+ #endif
++#ifdef GSSAPI
++	if (options.gss_authentication) {
++		temporarily_use_uid(authctxt->pw);
++		ssh_gssapi_storecreds();
++		restore_uid();
++	}
++#endif
+ 
+ 	/*
+ 	 * In privilege separation, we fork another child and prepare
+@@ -2466,6 +2526,48 @@ do_ssh2_kex(void)
  
  	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
  
@@ -2855,7 +2924,7 @@ diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c
  	/* start key exchange */
  	kex = kex_setup(myproposal);
  	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
-@@ -2473,6 +2576,13 @@ do_ssh2_kex(void)
+@@ -2473,6 +2575,13 @@ do_ssh2_kex(void)
  	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
  	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
  	kex->kex[KEX_ECDH_SHA2] = kexecdh_server;


More information about the scm-commits mailing list