18267729 Delegating credentials in OpenSSH
authorTomas Kuthan <tomas.kuthan@oracle.com>
Fri, 21 Mar 2014 09:36:50 -0700
changeset 1783 d716b9b5961b
parent 1782 5aa8051aaa4b
child 1784 f4788333a58f
18267729 Delegating credentials in OpenSSH
components/openssh/patches/005-openssh_krb5_build_fix.patch
components/openssh/patches/010-gss_store_cred.patch
--- a/components/openssh/patches/005-openssh_krb5_build_fix.patch	Fri Mar 21 07:47:48 2014 -0700
+++ b/components/openssh/patches/005-openssh_krb5_build_fix.patch	Fri Mar 21 09:36:50 2014 -0700
@@ -117,26 +117,3 @@
  
  #ifdef SSH_AUDIT_EVENTS
  	audit_event(SSH_AUTH_SUCCESS);
---- old/gss-serv-krb5.c	2006-08-31 22:38:36.000000000 -0700
-+++ new/gss-serv-krb5.c	2012-10-25 03:09:36.080638790 -0700
[email protected]@ -126,6 +126,12 @@
- 		return;
- 	}
- 
-+#ifdef KRB5_BUILD_FIX
-+	/* currently unimplemented - print an error, but continue */
-+	error("Delegated credentials storing not implemented.");
-+	return;
-+#else
-+
- 	if (ssh_gssapi_krb5_init() == 0)
- 		return;
- 
[email protected]@ -182,6 +188,7 @@
- 	krb5_cc_close(krb_context, ccache);
- 
- 	return;
-+#endif /* KRB5_BUILD_FIX */
- }
- 
- ssh_gssapi_mech gssapi_kerberos_mech = {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openssh/patches/010-gss_store_cred.patch	Fri Mar 21 09:36:50 2014 -0700
@@ -0,0 +1,202 @@
+#
+# This patch modifies code for storing delegated GSS-API credentials to work
+# with Solaris Kerberos.
+#
+# Default credential cache is used instead of per-session credentials cache
+# because on Solaris gssd cannot use credentials from non-default cred store.
+# A downside of this solution is, that the default credential cache file
+# cannot be deleted upon logout and hence GSSAPICleanupCredentials is
+# unsupported for now.
+#
+# To store the credentials a standardized GSS-API function gss_store_cred() is
+# used instead of gss_krb5_copy_ccache(), because (unlike MIT Kerberos
+# libgssapi_krb5) Solaris Kerberos libgss does not have Kerberos mechanism
+# directly built in the library and this function is not directly accessible.
+#
+# The patch is implemented as Solaris-specific using USE_GSS_STORE_CRED 
+# and GSSAPI_STORECREDS_NEEDS_RUID macros.
+#
+diff -ur old/config.h.in new/config.h.in
+--- old/config.h.in	2012-04-19 22:03:32.000000000 -0700
++++ new/config.h.in	2014-03-12 06:47:38.667166593 -0700
[email protected]@ -1465,6 +1465,12 @@
+ /* Use btmp to log bad logins */
+ #undef USE_BTMP
+ 
++/* Store delegated credentials in default cred. store using gss_store_cred */
++#undef USE_GSS_STORE_CRED
++
++/* Set real uid prior to storing delegated credentials */
++#undef GSSAPI_STORECREDS_NEEDS_RUID
++
+ /* Use libedit for sftp */
+ #undef USE_LIBEDIT
+ 
+diff -ur old/configure new/configure
+--- old/configure	2014-03-12 04:01:33.320409426 -0700
++++ new/configure	2014-03-12 06:47:48.510155481 -0700
[email protected]@ -7201,6 +7201,9 @@
+ 
+ fi
+ 
++	$as_echo "#define USE_GSS_STORE_CRED 1" >>confdefs.h
++	$as_echo "#define GSSAPI_STORECREDS_NEEDS_RUID 1" >>confdefs.h
++
+ 	;;
+ *-*-sunos4*)
+ 	CPPFLAGS="$CPPFLAGS -DSUNOS4"
+diff -ur old/configure.ac new/configure.ac
+--- old/configure.ac	2014-03-12 04:01:33.310743659 -0700
++++ new/configure.ac	2014-03-12 06:47:59.218730468 -0700
[email protected]@ -802,6 +802,8 @@
+ 			SP_MSG="yes" ], )
+ 		],
+ 	)
++	AC_DEFINE([USE_GSS_STORE_CRED])
++	AC_DEFINE([GSSAPI_STORECREDS_NEEDS_RUID])
+ 	;;
+ *-*-sunos4*)
+ 	CPPFLAGS="$CPPFLAGS -DSUNOS4"
+diff -ur old/gss-serv-krb5.c new/gss-serv-krb5.c
+--- old/gss-serv-krb5.c	2006-08-31 22:38:36.000000000 -0700
++++ new/gss-serv-krb5.c	2014-03-17 06:25:36.218227736 -0700
[email protected]@ -109,6 +109,7 @@
+ }
+ 
+ 
++#ifndef USE_GSS_STORE_CRED
+ /* This writes out any forwarded credentials from the structure populated
+  * during userauth. Called after we have setuid to the user */
+ 
[email protected]@ -183,6 +184,7 @@
+ 
+ 	return;
+ }
++#endif	/* #ifndef USE_GSS_STORE_CRED */
+ 
+ ssh_gssapi_mech gssapi_kerberos_mech = {
+ 	"toWM5Slw5Ew8Mqkay+al2g==",
[email protected]@ -191,7 +193,11 @@
+ 	NULL,
+ 	&ssh_gssapi_krb5_userok,
+ 	NULL,
++#ifdef USE_GSS_STORE_CRED
++	NULL
++#else
+ 	&ssh_gssapi_krb5_storecreds
++#endif
+ };
+ 
+ #endif /* KRB5 */
+diff -ur old/gss-serv.c new/gss-serv.c
+--- old/gss-serv.c	2011-08-05 13:16:46.000000000 -0700
++++ new/gss-serv.c	2014-03-12 05:55:42.368676287 -0700
[email protected]@ -292,22 +292,66 @@
+ void
+ ssh_gssapi_cleanup_creds(void)
+ {
++#ifdef USE_GSS_STORE_CRED
++	debug("removing gssapi cred file not implemented");
++#else
+ 	if (gssapi_client.store.filename != NULL) {
+ 		/* Unlink probably isn't sufficient */
+ 		debug("removing gssapi cred file\"%s\"",
+ 		    gssapi_client.store.filename);
+ 		unlink(gssapi_client.store.filename);
+ 	}
++#endif /* USE_GSS_STORE_CRED */
+ }
+ 
+ /* As user */
+ void
+ ssh_gssapi_storecreds(void)
+ {
++#ifdef USE_GSS_STORE_CRED
++	OM_uint32 maj_status, min_status;
++
++	if (gssapi_client.creds == NULL) {
++		debug("No credentials stored");
++		return;
++	}
++
++	maj_status = gss_store_cred(&min_status, gssapi_client.creds,
++	    GSS_C_INITIATE, &gssapi_client.mech->oid, 1, 1, NULL, NULL);
++
++	if (GSS_ERROR(maj_status)) {
++		Buffer b;
++		gss_buffer_desc msg;
++		OM_uint32 lmin;
++		OM_uint32 more = 0;
++		buffer_init(&b);
++		/* GSS-API error */
++		do {
++			gss_display_status(&lmin, maj_status, GSS_C_GSS_CODE,
++			    GSS_C_NULL_OID, &more, &msg);
++			buffer_append(&b, msg.value, msg.length);
++			buffer_put_char(&b, '\n');
++			gss_release_buffer(&lmin, &msg);
++		} while (more != 0);
++		/* Mechanism specific error */
++		do {
++			gss_display_status(&lmin, min_status, GSS_C_MECH_CODE,
++			    &gssapi_client.mech->oid, &more, &msg);
++			buffer_append(&b, msg.value, msg.length);
++			buffer_put_char(&b, '\n');
++			gss_release_buffer(&lmin, &msg);
++		} while (more != 0);
++		buffer_put_char(&b, '\0');
++		error("GSS-API error while storing delegated credentials: %s",
++		    buffer_ptr(&b));
++		buffer_free(&b);
++	}
++#else	/* #ifdef USE_GSS_STORE_CRED */
+ 	if (gssapi_client.mech && gssapi_client.mech->storecreds) {
+ 		(*gssapi_client.mech->storecreds)(&gssapi_client);
+ 	} else
+ 		debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
++#endif	/* #ifdef USE_GSS_STORE_CRED */
+ }
+ 
+ /* This allows GSSAPI methods to do things to the childs environment based
+diff -ur old/servconf.c new/servconf.c
+--- old/servconf.c	2014-03-12 04:01:33.343205265 -0700
++++ new/servconf.c	2014-03-12 04:01:33.400368192 -0700
[email protected]@ -386,7 +386,11 @@
+ 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+ #ifdef GSSAPI
+ 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
++#ifdef USE_GSS_STORE_CRED
++	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
++#else	/* USE_GSS_STORE_CRED*/
+ 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
++#endif	/* USE_GSS_STORE_CRED*/
+ #else
+ 	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+ 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+diff -ur old/sshd.c new/sshd.c
+--- old/sshd.c	2014-03-12 04:01:33.321603394 -0700
++++ new/sshd.c	2014-03-12 06:48:16.296909610 -0700
[email protected]@ -2041,9 +2041,23 @@
+ 
+ #ifdef GSSAPI
+ 	if (options.gss_authentication) {
++#ifdef GSSAPI_STORECREDS_NEEDS_RUID
++		if (setreuid(authctxt->pw->pw_uid, -1) != 0) {
++			debug("setreuid %u: %.100s",
++			    (u_int) authctxt->pw->pw_uid, strerror(errno));
++			goto bail_storecred;
++		}
++#endif
+ 		temporarily_use_uid(authctxt->pw);
+ 		ssh_gssapi_storecreds();
+ 		restore_uid();
++#ifdef GSSAPI_STORECREDS_NEEDS_RUID
++		if (setuid(geteuid()) != 0) {
++			fatal("setuid %u: %.100s", (u_int) geteuid(),
++			    strerror(errno));
++		}
++ bail_storecred:
++#endif
+ 	}
+ #endif
+ #ifdef USE_PAM