#
# 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 -pur old/config.h.in new/config.h.in
--- old/config.h.in
+++ new/config.h.in
@@ -1623,6 +1623,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 -pur old/configure.ac new/configure.ac
--- old/configure.ac
+++ new/configure.ac
@@ -910,6 +910,8 @@ mips-sony-bsd|mips-sony-newsos4)
],
)
TEST_SHELL=$SHELL # let configure find us a capable shell
+ AC_DEFINE([USE_GSS_STORE_CRED])
+ AC_DEFINE([GSSAPI_STORECREDS_NEEDS_RUID])
;;
*-*-sunos4*)
CPPFLAGS="$CPPFLAGS -DSUNOS4"
diff -pur old/gss-serv-krb5.c new/gss-serv-krb5.c
@@ -110,7 +110,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
return retval;
}
-
+#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 */
@@ -196,6 +196,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
return;
}
+#endif /* #ifndef USE_GSS_STORE_CRED */
ssh_gssapi_mech gssapi_kerberos_mech = {
"toWM5Slw5Ew8Mqkay+al2g==",
@@ -204,7 +205,11 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
NULL,
&ssh_gssapi_krb5_userok,
NULL,
+#ifdef USE_GSS_STORE_CRED
+ NULL
+#else
&ssh_gssapi_krb5_storecreds
+#endif
};
#endif /* KRB5 */
diff -pur old/gss-serv.c new/gss-serv.c
--- old/gss-serv.c
+++ new/gss-serv.c
@@ -320,22 +320,66 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g
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\"",
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 -pur old/servconf.c new/servconf.c
--- old/servconf.c
+++ new/servconf.c
@@ -489,7 +489,11 @@ static struct {
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
- { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+#ifdef USE_GSS_STORE_CRED
+ { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+#else /* USE_GSS_STORE_CRED */
+ { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+#endif /* USE_GSS_STORE_CRED */
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
@@ -2264,7 +2268,9 @@ dump_config(ServerOptions *o)
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+#ifndef USE_GSS_STORE_CRED
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+#endif /* !USE_GSS_STORE_CRED */
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
diff -pur old/sshd.c new/sshd.c
--- old/sshd.c
+++ new/sshd.c
@@ -2228,9 +2228,23 @@ main(int ac, char **av)
#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