rcolebaugh / rpms / openssh

Forked from rpms/openssh 2 years ago
Clone

Blame SOURCES/openssh-6.6p1-expose-auth-information.patch

f8987c
diff -up openssh-6.6p1/auth2.c.expose-auth openssh-6.6p1/auth2.c
f8987c
--- openssh-6.6p1/auth2.c.expose-auth	2016-06-27 12:19:39.134443822 +0200
f8987c
+++ openssh-6.6p1/auth2.c	2016-06-27 12:19:39.178443747 +0200
f8987c
@@ -309,6 +309,7 @@ userauth_finish(Authctxt *authctxt, int
f8987c
     const char *submethod)
f8987c
 {
f8987c
 	char *methods;
f8987c
+	char *prev_auth_details;
f8987c
 	int partial = 0;
f8987c
 
f8987c
 	if (!authctxt->valid && authenticated)
f8987c
@@ -339,6 +340,18 @@ userauth_finish(Authctxt *authctxt, int
f8987c
 	if (authctxt->postponed)
f8987c
 		return;
f8987c
 
f8987c
+	if (authenticated || partial) {
f8987c
+		prev_auth_details = authctxt->auth_details;
f8987c
+		xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
f8987c
+		    prev_auth_details ? prev_auth_details : "",
f8987c
+		    prev_auth_details ? ", " : "", method,
f8987c
+		    authctxt->last_details ? ": " : "",
f8987c
+		    authctxt->last_details ? authctxt->last_details : "");
f8987c
+		free(authctxt->last_details);
f8987c
+		authctxt->last_details = NULL;
f8987c
+		free(prev_auth_details);
f8987c
+	}
f8987c
+
f8987c
 #ifdef USE_PAM
f8987c
 	if (options.use_pam && authenticated) {
f8987c
 		if (!PRIVSEP(do_pam_account())) {
f8987c
diff -up openssh-6.6p1/auth2-gss.c.expose-auth openssh-6.6p1/auth2-gss.c
f8987c
--- openssh-6.6p1/auth2-gss.c.expose-auth	2016-06-27 12:19:39.102443877 +0200
f8987c
+++ openssh-6.6p1/auth2-gss.c	2016-06-27 12:19:39.179443745 +0200
f8987c
@@ -272,6 +272,9 @@ input_gssapi_exchange_complete(int type,
f8987c
 	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
f8987c
 	    authctxt->pw));
f8987c
 
f8987c
+	if (authenticated)
f8987c
+		authctxt->last_details = ssh_gssapi_get_displayname();
f8987c
+
f8987c
 	authctxt->postponed = 0;
f8987c
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
f8987c
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
f8987c
@@ -317,6 +320,9 @@ input_gssapi_mic(int type, u_int32_t ple
f8987c
 	else
f8987c
 		logit("GSSAPI MIC check failed");
f8987c
 
f8987c
+	if (authenticated)
f8987c
+		authctxt->last_details = ssh_gssapi_get_displayname();
f8987c
+
f8987c
 	buffer_free(&b);
f8987c
 	if (micuser != authctxt->user)
f8987c
 		free(micuser);
f8987c
diff -up openssh-6.6p1/auth2-hostbased.c.expose-auth openssh-6.6p1/auth2-hostbased.c
f8987c
--- openssh-6.6p1/auth2-hostbased.c.expose-auth	2016-06-27 12:19:39.051443964 +0200
f8987c
+++ openssh-6.6p1/auth2-hostbased.c	2016-06-27 12:19:39.179443745 +0200
f8987c
@@ -58,7 +58,7 @@ userauth_hostbased(Authctxt *authctxt)
f8987c
 {
f8987c
 	Buffer b;
f8987c
 	Key *key = NULL;
f8987c
-	char *pkalg, *cuser, *chost, *service;
f8987c
+	char *pkalg, *cuser, *chost, *service, *pubkey;
f8987c
 	u_char *pkblob, *sig;
f8987c
 	u_int alen, blen, slen;
f8987c
 	int pktype;
f8987c
@@ -131,15 +131,21 @@ userauth_hostbased(Authctxt *authctxt)
f8987c
 	buffer_dump(&b);
f8987c
 #endif
f8987c
 
f8987c
-	pubkey_auth_info(authctxt, key,
f8987c
-	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
f8987c
+	pubkey = key_format_oneline(key);
f8987c
+	auth_info(authctxt,
f8987c
+	    "%s, client user \"%.100s\", client host \"%.100s\"",
f8987c
+	    pubkey, cuser, chost);
f8987c
 
f8987c
 	/* test for allowed key and correct signature */
f8987c
 	authenticated = 0;
f8987c
 	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
f8987c
 	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
f8987c
-			buffer_len(&b))) == 1)
f8987c
+			buffer_len(&b))) == 1) {
f8987c
 		authenticated = 1;
f8987c
+		authctxt->last_details = pubkey;
f8987c
+	} else {
f8987c
+		free(pubkey);
f8987c
+	}
f8987c
 
f8987c
 	buffer_free(&b);
f8987c
 done:
f8987c
diff -up openssh-6.6p1/auth2-pubkey.c.expose-auth openssh-6.6p1/auth2-pubkey.c
f8987c
--- openssh-6.6p1/auth2-pubkey.c.expose-auth	2016-06-27 12:19:39.068443935 +0200
f8987c
+++ openssh-6.6p1/auth2-pubkey.c	2016-06-27 12:19:39.179443745 +0200
f8987c
@@ -75,7 +75,7 @@ userauth_pubkey(Authctxt *authctxt)
f8987c
 {
f8987c
 	Buffer b;
f8987c
 	Key *key = NULL;
f8987c
-	char *pkalg, *userstyle;
f8987c
+	char *pkalg, *userstyle, *pubkey;
f8987c
 	u_char *pkblob, *sig;
f8987c
 	u_int alen, blen, slen;
f8987c
 	int have_sig, pktype;
f8987c
@@ -155,14 +155,19 @@ userauth_pubkey(Authctxt *authctxt)
f8987c
 #ifdef DEBUG_PK
f8987c
 		buffer_dump(&b);
f8987c
 #endif
f8987c
-		pubkey_auth_info(authctxt, key, NULL);
f8987c
+		pubkey = key_format_oneline(key);
f8987c
+		auth_info(authctxt, "%s", pubkey);
f8987c
 
f8987c
 		/* test for correct signature */
f8987c
 		authenticated = 0;
f8987c
 		if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
f8987c
 		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
f8987c
-		    buffer_len(&b))) == 1)
f8987c
+		    buffer_len(&b))) == 1) {
f8987c
+			authctxt->last_details = pubkey;
f8987c
 			authenticated = 1;
f8987c
+		} else {
f8987c
+			free(pubkey);
f8987c
+ 		}
f8987c
 		buffer_free(&b);
f8987c
 		free(sig);
f8987c
 	} else {
f8987c
@@ -200,7 +205,7 @@ done:
f8987c
 void
f8987c
 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
f8987c
 {
f8987c
-	char *fp, *extra;
f8987c
+	char *extra, *pubkey;
f8987c
 	va_list ap;
f8987c
 	int i;
f8987c
 
f8987c
@@ -210,24 +215,13 @@ pubkey_auth_info(Authctxt *authctxt, con
f8987c
 		i = vasprintf(&extra, fmt, ap);
f8987c
 		va_end(ap);
f8987c
 		if (i < 0 || extra == NULL)
f8987c
-			fatal("%s: vasprintf failed", __func__);	
f8987c
+			fatal("%s: vasprintf failed", __func__);
f8987c
 	}
f8987c
 
f8987c
-	if (key_is_cert(key)) {
f8987c
-		fp = key_fingerprint(key->cert->signature_key,
f8987c
-		    SSH_FP_MD5, SSH_FP_HEX);
f8987c
-		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
f8987c
-		    key_type(key), key->cert->key_id,
f8987c
-		    (unsigned long long)key->cert->serial,
f8987c
-		    key_type(key->cert->signature_key), fp,
f8987c
-		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
f8987c
-		free(fp);
f8987c
-	} else {
f8987c
-		fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
f8987c
-		auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
f8987c
-		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
f8987c
-		free(fp);
f8987c
-	}
f8987c
+	pubkey = key_format_oneline(key);
f8987c
+	auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ",
f8987c
+	    extra == NULL ? "" : extra);
f8987c
+	free(pubkey);
f8987c
 	free(extra);
f8987c
 }
f8987c
 
f8987c
diff -up openssh-6.6p1/auth.h.expose-auth openssh-6.6p1/auth.h
f8987c
--- openssh-6.6p1/auth.h.expose-auth	2016-06-27 12:19:39.144443805 +0200
f8987c
+++ openssh-6.6p1/auth.h	2016-06-27 12:19:39.179443745 +0200
f8987c
@@ -78,6 +78,9 @@ struct Authctxt {
f8987c
 #endif
f8987c
 	Buffer		*loginmsg;
f8987c
 	void		*methoddata;
f8987c
+
f8987c
+	char		*last_details;
f8987c
+	char		*auth_details;
f8987c
 };
f8987c
 /*
f8987c
  * Every authentication method has to handle authentication requests for
f8987c
diff -up openssh-6.6p1/auth-pam.c.expose-auth openssh-6.6p1/auth-pam.c
f8987c
--- openssh-6.6p1/auth-pam.c.expose-auth	2016-06-27 12:19:39.049443967 +0200
f8987c
+++ openssh-6.6p1/auth-pam.c	2016-06-27 12:19:39.179443745 +0200
f8987c
@@ -688,6 +688,11 @@ sshpam_init_ctx(Authctxt *authctxt)
f8987c
 		return (NULL);
f8987c
 	}
f8987c
 
f8987c
+	/* Notify PAM about any already successful auth methods */
f8987c
+	if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMONLY &&
f8987c
+			authctxt->auth_details)
f8987c
+		do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details);
f8987c
+
f8987c
 	ctxt = xcalloc(1, sizeof *ctxt);
f8987c
 
f8987c
 	/* Start the authentication thread */
f8987c
diff -up openssh-6.6p1/gss-serv.c.expose-auth openssh-6.6p1/gss-serv.c
f8987c
--- openssh-6.6p1/gss-serv.c.expose-auth	2016-06-27 12:19:39.160443778 +0200
f8987c
+++ openssh-6.6p1/gss-serv.c	2016-06-27 12:19:39.180443743 +0200
f8987c
@@ -471,6 +471,16 @@ ssh_gssapi_userok(char *user, struct pas
f8987c
 	return (0);
f8987c
 }
f8987c
 
f8987c
+/* Privileged */
f8987c
+char*
f8987c
+ssh_gssapi_get_displayname(void)
f8987c
+{
f8987c
+	if (gssapi_client.displayname.length != 0 &&
f8987c
+	    gssapi_client.displayname.value != NULL)
f8987c
+		return strdup((char *)gssapi_client.displayname.value);
f8987c
+	return NULL;
f8987c
+}
f8987c
+
f8987c
 /* These bits are only used for rekeying. The unpriviledged child is running 
f8987c
  * as the user, the monitor is root.
f8987c
  *
f8987c
diff -up openssh-6.6p1/key.c.expose-auth openssh-6.6p1/key.c
f8987c
--- openssh-6.6p1/key.c.expose-auth	2016-06-27 12:19:39.105443872 +0200
f8987c
+++ openssh-6.6p1/key.c	2016-06-27 12:19:39.180443743 +0200
f8987c
@@ -57,6 +57,7 @@
f8987c
 #include "misc.h"
f8987c
 #include "ssh2.h"
f8987c
 #include "digest.h"
f8987c
+#include "xmalloc.h"
f8987c
 
f8987c
 static int to_blob(const Key *, u_char **, u_int *, int);
f8987c
 static Key *key_from_blob2(const u_char *, u_int, int);
f8987c
@@ -628,6 +629,30 @@ key_fingerprint(const Key *k, enum fp_ty
f8987c
 	return retval;
f8987c
 }
f8987c
 
f8987c
+char *
f8987c
+key_format_oneline(const Key *key)
f8987c
+{
f8987c
+	char *fp, *result;
f8987c
+
f8987c
+	if (key_is_cert(key)) {
f8987c
+		fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5,
f8987c
+		    SSH_FP_HEX);
f8987c
+		xasprintf(&result, "%s ID %s (serial %llu) CA %s %s",
f8987c
+		    key_type(key), key->cert->key_id,
f8987c
+		    (unsigned long long)key->cert->serial,
f8987c
+		    key_type(key->cert->signature_key),
f8987c
+		    fp == NULL ? "(null)" : fp);
f8987c
+		free(fp);
f8987c
+	} else {
f8987c
+		fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
f8987c
+		xasprintf(&result, "%s %s", key_type(key),
f8987c
+		    fp == NULL ? "(null)" : fp);
f8987c
+		free(fp);
f8987c
+	}
f8987c
+
f8987c
+	return result;
f8987c
+}
f8987c
+
f8987c
 enum fp_type
f8987c
 key_fingerprint_selection(void)
f8987c
 {
f8987c
diff -up openssh-6.6p1/key.h.expose-auth openssh-6.6p1/key.h
f8987c
--- openssh-6.6p1/key.h.expose-auth	2016-06-27 12:19:43.322436657 +0200
f8987c
+++ openssh-6.6p1/key.h	2016-06-27 12:20:25.898363835 +0200
f8987c
@@ -108,6 +108,7 @@ u_char		*key_fingerprint_raw(const Key *
f8987c
 enum fp_type	 key_fingerprint_selection(void);
f8987c
 char		*key_selected_fingerprint(Key *, enum fp_rep);
f8987c
 char		*key_fingerprint_prefix(void);
f8987c
+char		*key_format_oneline(const Key *k);
f8987c
 const char	*key_type(const Key *);
f8987c
 const char	*key_cert_type(const Key *);
f8987c
 int		 key_write(const Key *, FILE *);
f8987c
diff -up openssh-6.6p1/monitor.c.expose-auth openssh-6.6p1/monitor.c
f8987c
--- openssh-6.6p1/monitor.c.expose-auth	2016-06-27 12:19:39.165443769 +0200
f8987c
+++ openssh-6.6p1/monitor.c	2016-06-27 12:19:39.180443743 +0200
f8987c
@@ -357,6 +357,7 @@ monitor_child_preauth(Authctxt *_authctx
f8987c
 {
f8987c
 	struct mon_table *ent;
f8987c
 	int authenticated = 0, partial = 0;
f8987c
+	char *prev_auth_details;
f8987c
 
f8987c
 	debug3("preauth child monitor started");
f8987c
 
f8987c
@@ -394,6 +395,18 @@ monitor_child_preauth(Authctxt *_authctx
f8987c
 		auth_submethod = NULL;
f8987c
 		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
f8987c
 
f8987c
+		if (authenticated) {
f8987c
+			prev_auth_details = authctxt->auth_details;
f8987c
+			xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
f8987c
+			    prev_auth_details ? prev_auth_details : "",
f8987c
+			    prev_auth_details ? ", " : "", auth_method,
f8987c
+			    authctxt->last_details ? ": " : "",
f8987c
+			    authctxt->last_details ? authctxt->last_details : "");
f8987c
+			free(authctxt->last_details);
f8987c
+			authctxt->last_details = NULL;
f8987c
+			free(prev_auth_details);
f8987c
+		}
f8987c
+
f8987c
 		/* Special handling for multiple required authentications */
f8987c
 		if (options.num_auth_methods != 0) {
f8987c
 			if (!compat20)
f8987c
@@ -1432,6 +1445,9 @@ mm_answer_keyverify(int sock, Buffer *m)
f8987c
 	debug3("%s: key %p signature %s",
f8987c
 	    __func__, key, (verified == 1) ? "verified" : "unverified");
f8987c
 
f8987c
+	if (verified == 1)
f8987c
+		authctxt->last_details = key_format_oneline(key);
f8987c
+
f8987c
 	key_free(key);
f8987c
 	free(blob);
f8987c
 	free(signature);
f8987c
@@ -2224,6 +2240,9 @@ mm_answer_gss_userok(int sock, Buffer *m
f8987c
 
f8987c
 	auth_method = "gssapi-with-mic";
f8987c
 
f8987c
+	if (authenticated)
f8987c
+		authctxt->last_details = ssh_gssapi_get_displayname();
f8987c
+
f8987c
 	/* Monitor loop will terminate if authenticated */
f8987c
 	return (authenticated);
f8987c
 }
f8987c
diff -up openssh-6.6p1/servconf.c.expose-auth openssh-6.6p1/servconf.c
f8987c
--- openssh-6.6p1/servconf.c.expose-auth	2016-06-27 12:19:39.177443748 +0200
f8987c
+++ openssh-6.6p1/servconf.c	2016-06-27 12:19:39.181443742 +0200
f8987c
@@ -161,6 +161,7 @@ initialize_server_options(ServerOptions
f8987c
 	options->version_addendum = NULL;
f8987c
 	options->use_kuserok = -1;
f8987c
 	options->enable_k5users = -1;
f8987c
+	options->expose_auth_methods = -1;
f8987c
 }
f8987c
 
f8987c
 void
f8987c
@@ -322,6 +323,8 @@ fill_default_server_options(ServerOption
f8987c
 		options->use_kuserok = 1;
f8987c
 	if (options->enable_k5users == -1)
f8987c
 		options->enable_k5users = 0;
f8987c
+	if (options->expose_auth_methods == -1)
f8987c
+		options->expose_auth_methods = EXPOSE_AUTHMETH_NEVER;
f8987c
 
f8987c
 	/* Turn privilege separation on by default */
f8987c
 	if (use_privsep == -1)
f8987c
@@ -380,6 +383,7 @@ typedef enum {
f8987c
 	sKexAlgorithms, sIPQoS, sVersionAddendum,
f8987c
 	sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
f8987c
 	sAuthenticationMethods, sHostKeyAgent,
f8987c
+	sExposeAuthenticationMethods,
f8987c
 	sDeprecated, sUnsupported
f8987c
 } ServerOpCodes;
f8987c
 
f8987c
@@ -523,6 +527,7 @@ static struct {
f8987c
 	{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
f8987c
 	{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
f8987c
 	{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
f8987c
+	{ "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_ALL },
f8987c
 	{ NULL, sBadOption, 0 }
f8987c
 };
f8987c
 
f8987c
@@ -869,6 +874,12 @@ static const struct multistate multistat
f8987c
 	{ "local",			FORWARD_LOCAL },
f8987c
 	{ NULL, -1 }
f8987c
 };
f8987c
+static const struct multistate multistate_exposeauthmeth[] = {
f8987c
+	{ "never",			EXPOSE_AUTHMETH_NEVER },
f8987c
+	{ "pam-only",			EXPOSE_AUTHMETH_PAMONLY },
f8987c
+	{ "pam-and-env",		EXPOSE_AUTHMETH_PAMENV },
f8987c
+	{ NULL, -1}
f8987c
+};
f8987c
 
f8987c
 int
f8987c
 process_server_config_line(ServerOptions *options, char *line,
f8987c
@@ -1727,6 +1738,11 @@ process_server_config_line(ServerOptions
f8987c
 		}
f8987c
 		return 0;
f8987c
 
f8987c
+	case sExposeAuthenticationMethods:
f8987c
+		intptr = &options->expose_auth_methods;
f8987c
+		multistate_ptr = multistate_exposeauthmeth;
f8987c
+		goto parse_multistate;
f8987c
+
f8987c
 	case sDeprecated:
f8987c
 		logit("%s line %d: Deprecated option %s",
f8987c
 		    filename, linenum, arg);
f8987c
@@ -1883,6 +1899,7 @@ copy_set_server_options(ServerOptions *d
f8987c
 	M_CP_INTOPT(enable_k5users);
f8987c
 	M_CP_INTOPT(rekey_limit);
f8987c
 	M_CP_INTOPT(rekey_interval);
f8987c
+	M_CP_INTOPT(expose_auth_methods);
f8987c
 
f8987c
 	/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
f8987c
 #define M_CP_STROPT(n) do {\
f8987c
@@ -1971,6 +1988,8 @@ fmt_intarg(ServerOpCodes code, int val)
f8987c
 		return fmt_multistate_int(val, multistate_privsep);
f8987c
 	case sAllowTcpForwarding:
f8987c
 		return fmt_multistate_int(val, multistate_tcpfwd);
f8987c
+	case sExposeAuthenticationMethods:
f8987c
+		return fmt_multistate_int(val, multistate_exposeauthmeth);
f8987c
 	case sProtocol:
f8987c
 		switch (val) {
f8987c
 		case SSH_PROTO_1:
f8987c
@@ -2182,6 +2201,7 @@ dump_config(ServerOptions *o)
f8987c
 	dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
f8987c
 	dump_cfg_strarray_oneline(sAuthenticationMethods,
f8987c
 	    o->num_auth_methods, o->auth_methods);
f8987c
+	dump_cfg_fmtint(sExposeAuthenticationMethods, o->expose_auth_methods);
f8987c
 
f8987c
 	/* other arguments */
f8987c
 	for (i = 0; i < o->num_subsystems; i++)
f8987c
diff -up openssh-6.6p1/servconf.h.expose-auth openssh-6.6p1/servconf.h
f8987c
--- openssh-6.6p1/servconf.h.expose-auth	2016-06-27 12:19:39.162443774 +0200
f8987c
+++ openssh-6.6p1/servconf.h	2016-06-27 12:19:39.181443742 +0200
f8987c
@@ -48,6 +48,11 @@
f8987c
 #define FORWARD_LOCAL		(1<<1)
f8987c
 #define FORWARD_ALLOW		(FORWARD_REMOTE|FORWARD_LOCAL)
f8987c
 
f8987c
+/* Expose AuthenticationMethods */
f8987c
+#define EXPOSE_AUTHMETH_NEVER   0
f8987c
+#define EXPOSE_AUTHMETH_PAMONLY 1
f8987c
+#define EXPOSE_AUTHMETH_PAMENV  2
f8987c
+
f8987c
 #define DEFAULT_AUTH_FAIL_MAX	6	/* Default for MaxAuthTries */
f8987c
 #define DEFAULT_SESSIONS_MAX	10	/* Default for MaxSessions */
f8987c
 
f8987c
@@ -190,6 +195,8 @@ typedef struct {
f8987c
 
f8987c
 	u_int	num_auth_methods;
f8987c
 	char   *auth_methods[MAX_AUTH_METHODS];
f8987c
+
f8987c
+	int	expose_auth_methods; /* EXPOSE_AUTHMETH_* above */
f8987c
 }       ServerOptions;
f8987c
 
f8987c
 /* Information about the incoming connection as used by Match */
f8987c
diff -up openssh-6.6p1/session.c.expose-auth openssh-6.6p1/session.c
f8987c
--- openssh-6.6p1/session.c.expose-auth	2016-06-27 12:19:39.171443759 +0200
f8987c
+++ openssh-6.6p1/session.c	2016-06-27 12:19:39.181443742 +0200
f8987c
@@ -1196,6 +1196,12 @@ copy_environment(char **source, char ***
f8987c
 		}
f8987c
 		*var_val++ = '\0';
f8987c
 
f8987c
+		if (options.expose_auth_methods < EXPOSE_AUTHMETH_PAMENV &&
f8987c
+				strcmp(var_name, "SSH_USER_AUTH") == 0) {
f8987c
+			free(var_name);
f8987c
+			continue;
f8987c
+		}
f8987c
+
f8987c
 		debug3("Copy environment: %s=%s", var_name, var_val);
f8987c
 		child_set_env(env, envsize, var_name, var_val);
f8987c
 
f8987c
@@ -1375,6 +1381,11 @@ do_setup_env(Session *s, const char *she
f8987c
 	}
f8987c
 #endif /* USE_PAM */
f8987c
 
f8987c
+	if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMENV &&
f8987c
+			s->authctxt->auth_details)
f8987c
+		child_set_env(&env, &envsize, "SSH_USER_AUTH",
f8987c
+		     s->authctxt->auth_details);
f8987c
+
f8987c
 	if (auth_sock_name != NULL)
f8987c
 		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
f8987c
 		    auth_sock_name);
f8987c
@@ -2805,6 +2816,9 @@ do_cleanup(Authctxt *authctxt)
f8987c
 	if (authctxt == NULL)
f8987c
 		return;
f8987c
 
f8987c
+	free(authctxt->auth_details);
f8987c
+	authctxt->auth_details = NULL;
f8987c
+
f8987c
 #ifdef USE_PAM
f8987c
 	if (options.use_pam) {
f8987c
 		sshpam_cleanup();
f8987c
diff -up openssh-6.6p1/ssh.1.expose-auth openssh-6.6p1/ssh.1
f8987c
--- openssh-6.6p1/ssh.1.expose-auth	2016-06-27 12:19:39.163443772 +0200
f8987c
+++ openssh-6.6p1/ssh.1	2016-06-27 12:19:39.181443742 +0200
f8987c
@@ -1289,6 +1289,10 @@ server IP address, and server port numbe
f8987c
 This variable contains the original command line if a forced command
f8987c
 is executed.
f8987c
 It can be used to extract the original arguments.
f8987c
+.It Ev SSH_USER_AUTH
f8987c
+This variable contains, for SSH2 only, a comma-separated list of authentication
f8987c
+methods that were successfuly used to authenticate. When possible, these
f8987c
+methods are extended with detailed information on the credential used.
f8987c
 .It Ev SSH_TTY
f8987c
 This is set to the name of the tty (path to the device) associated
f8987c
 with the current shell or command.
f8987c
diff -up openssh-6.6p1/sshd_config.5.expose-auth openssh-6.6p1/sshd_config.5
f8987c
--- openssh-6.6p1/sshd_config.5.expose-auth	2016-06-27 12:19:39.177443748 +0200
f8987c
+++ openssh-6.6p1/sshd_config.5	2016-06-27 12:19:39.182443740 +0200
f8987c
@@ -466,6 +466,21 @@ is allowed to log in.
f8987c
 See PATTERNS in
f8987c
 .Xr ssh_config 5
f8987c
 for more information on patterns.
f8987c
+.It Cm ExposeAuthenticationMethods
f8987c
+When using SSH2, this option controls the exposure of the list of
f8987c
+successful authentication methods to PAM during the authentication
f8987c
+and to the shell environment via the
f8987c
+.Cm SSH_USER_AUTH
f8987c
+variable. See the description of this variable for more details.
f8987c
+Valid options are:
f8987c
+.Dq never
f8987c
+(Do not expose successful authentication methods),
f8987c
+.Dq pam-only
f8987c
+(Only expose them to PAM during authentication, not afterwards),
f8987c
+.Dq pam-and-env
f8987c
+(Expose them to PAM and keep them in the shell environment).
f8987c
+The default is
f8987c
+.Dq never .
f8987c
 .It Cm ForceCommand
f8987c
 Forces the execution of the command specified by
f8987c
 .Cm ForceCommand ,
f8987c
diff -up openssh-6.6p1/ssh-gss.h.expose-auth openssh-6.6p1/ssh-gss.h
f8987c
--- openssh-6.6p1/ssh-gss.h.expose-auth	2016-06-27 12:19:39.163443772 +0200
f8987c
+++ openssh-6.6p1/ssh-gss.h	2016-06-27 12:19:39.182443740 +0200
f8987c
@@ -160,6 +160,7 @@ int ssh_gssapi_server_check_mech(Gssctxt
f8987c
     const char *);
f8987c
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
f8987c
 int ssh_gssapi_userok(char *name, struct passwd *);
f8987c
+char* ssh_gssapi_get_displayname(void);
f8987c
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
f8987c
 void ssh_gssapi_do_child(char ***, u_int *);
f8987c
 void ssh_gssapi_cleanup_creds(void);