vishalmishra434 / rpms / openssh

Forked from rpms/openssh a month ago
Clone
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth2.c.expose-pam openssh-7.2p2/auth2.c
Jakub Jelen 209c7a
--- openssh-7.2p2/auth2.c.expose-pam	2016-07-18 12:30:12.064783302 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth2.c	2016-07-18 12:30:12.124783255 +0200
Jakub Jelen 209c7a
@@ -310,6 +310,7 @@ userauth_finish(Authctxt *authctxt, int
Jakub Jelen 209c7a
     const char *submethod)
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
 	char *methods;
Jakub Jelen 209c7a
+	char *prev_auth_details;
Jakub Jelen 209c7a
 	int partial = 0;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	if (!authctxt->valid && authenticated)
Jakub Jelen 209c7a
@@ -340,6 +341,18 @@ userauth_finish(Authctxt *authctxt, int
Jakub Jelen 209c7a
 	if (authctxt->postponed)
Jakub Jelen 209c7a
 		return;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (authenticated || partial) {
Jakub Jelen 209c7a
+		prev_auth_details = authctxt->auth_details;
Jakub Jelen 209c7a
+		xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
Jakub Jelen 209c7a
+		    prev_auth_details ? prev_auth_details : "",
Jakub Jelen 209c7a
+		    prev_auth_details ? ", " : "", method,
Jakub Jelen 209c7a
+		    authctxt->last_details ? ": " : "",
Jakub Jelen 209c7a
+		    authctxt->last_details ? authctxt->last_details : "");
Jakub Jelen 209c7a
+		free(prev_auth_details);
Jakub Jelen 209c7a
+	}
Jakub Jelen 209c7a
+	free(authctxt->last_details);
Jakub Jelen 209c7a
+	authctxt->last_details = NULL;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 #ifdef USE_PAM
Jakub Jelen 209c7a
 	if (options.use_pam && authenticated) {
Jakub Jelen 209c7a
 		if (!PRIVSEP(do_pam_account())) {
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth2-gss.c.expose-pam openssh-7.2p2/auth2-gss.c
Jakub Jelen 209c7a
--- openssh-7.2p2/auth2-gss.c.expose-pam	2016-07-18 12:30:12.123783256 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth2-gss.c	2016-07-18 12:32:08.034692086 +0200
Jakub Jelen 209c7a
@@ -276,6 +276,9 @@ input_gssapi_exchange_complete(int type,
Jakub Jelen 209c7a
 	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
Jakub Jelen 209c7a
 	    authctxt->pw));
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (authenticated)
Jakub Jelen 209c7a
+		authctxt->last_details = ssh_gssapi_get_displayname();
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	authctxt->postponed = 0;
Jakub Jelen 209c7a
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
Jakub Jelen 209c7a
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
Jakub Jelen 209c7a
@@ -322,6 +325,9 @@ input_gssapi_mic(int type, u_int32_t ple
Jakub Jelen 209c7a
 	else
Jakub Jelen 209c7a
 		logit("GSSAPI MIC check failed");
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (authenticated)
Jakub Jelen 209c7a
+		authctxt->last_details = ssh_gssapi_get_displayname();
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	buffer_free(&b);
Jakub Jelen 209c7a
 	if (micuser != authctxt->user)
Jakub Jelen 209c7a
 		free(micuser);
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth2-hostbased.c.expose-pam openssh-7.2p2/auth2-hostbased.c
Jakub Jelen 209c7a
--- openssh-7.2p2/auth2-hostbased.c.expose-pam	2016-07-18 12:30:12.027783331 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth2-hostbased.c	2016-07-18 12:30:12.124783255 +0200
Jakub Jelen 209c7a
@@ -60,7 +60,7 @@ userauth_hostbased(Authctxt *authctxt)
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
 	Buffer b;
Jakub Jelen 209c7a
 	Key *key = NULL;
Jakub Jelen 209c7a
-	char *pkalg, *cuser, *chost, *service;
Jakub Jelen 209c7a
+	char *pkalg, *cuser, *chost, *service, *pubkey;
Jakub Jelen 209c7a
 	u_char *pkblob, *sig;
Jakub Jelen 209c7a
 	u_int alen, blen, slen;
Jakub Jelen 209c7a
 	int pktype;
Jakub Jelen 209c7a
@@ -140,15 +140,21 @@ userauth_hostbased(Authctxt *authctxt)
Jakub Jelen 209c7a
 	buffer_dump(&b);
Jakub Jelen 209c7a
 #endif
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
-	pubkey_auth_info(authctxt, key,
Jakub Jelen 209c7a
-	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
Jakub Jelen 209c7a
+	pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
Jakub Jelen 209c7a
+	auth_info(authctxt,
Jakub Jelen 209c7a
+	    "%s, client user \"%.100s\", client host \"%.100s\"",
Jakub Jelen 209c7a
+	    pubkey, cuser, chost);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	/* test for allowed key and correct signature */
Jakub Jelen 209c7a
 	authenticated = 0;
Jakub Jelen 209c7a
 	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
Jakub Jelen 209c7a
 	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
Jakub Jelen 209c7a
-			buffer_len(&b))) == 1)
Jakub Jelen 209c7a
+			buffer_len(&b))) == 1) {
Jakub Jelen 209c7a
 		authenticated = 1;
Jakub Jelen 209c7a
+		authctxt->last_details = pubkey;
Jakub Jelen 209c7a
+	} else {
Jakub Jelen 209c7a
+		free(pubkey);
Jakub Jelen 209c7a
+	}
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	buffer_free(&b);
Jakub Jelen 209c7a
 done:
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth2-pubkey.c.expose-pam openssh-7.2p2/auth2-pubkey.c
Jakub Jelen 209c7a
--- openssh-7.2p2/auth2-pubkey.c.expose-pam	2016-07-18 12:30:12.039783322 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth2-pubkey.c	2016-07-18 12:30:12.124783255 +0200
Jakub Jelen 209c7a
@@ -79,7 +79,7 @@ userauth_pubkey(Authctxt *authctxt)
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
 	Buffer b;
Jakub Jelen 209c7a
 	Key *key = NULL;
Jakub Jelen 209c7a
-	char *pkalg, *userstyle, *fp = NULL;
Jakub Jelen 209c7a
+	char *pkalg, *userstyle, *pubkey, *fp = NULL;
Jakub Jelen 209c7a
 	u_char *pkblob, *sig;
Jakub Jelen 209c7a
 	u_int alen, blen, slen;
Jakub Jelen 209c7a
 	int have_sig, pktype;
Jakub Jelen 209c7a
@@ -173,7 +173,8 @@ userauth_pubkey(Authctxt *authctxt)
Jakub Jelen 209c7a
 #ifdef DEBUG_PK
Jakub Jelen 209c7a
 		buffer_dump(&b);
Jakub Jelen 209c7a
 #endif
Jakub Jelen 209c7a
-		pubkey_auth_info(authctxt, key, NULL);
Jakub Jelen 209c7a
+		pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
Jakub Jelen 209c7a
+		auth_info(authctxt, "%s", pubkey);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 		/* test for correct signature */
Jakub Jelen 209c7a
 		authenticated = 0;
Jakub Jelen 209c7a
@@ -181,9 +182,12 @@ userauth_pubkey(Authctxt *authctxt)
Jakub Jelen 209c7a
 		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
Jakub Jelen 209c7a
 		    buffer_len(&b))) == 1) {
Jakub Jelen 209c7a
 			authenticated = 1;
Jakub Jelen 209c7a
+			authctxt->last_details = pubkey;
Jakub Jelen 209c7a
 			/* Record the successful key to prevent reuse */
Jakub Jelen 209c7a
 			auth2_record_userkey(authctxt, key);
Jakub Jelen 209c7a
 			key = NULL; /* Don't free below */
Jakub Jelen 209c7a
+		} else {
Jakub Jelen 209c7a
+			free(pubkey);
Jakub Jelen 209c7a
 		}
Jakub Jelen 209c7a
 		buffer_free(&b);
Jakub Jelen 209c7a
 		free(sig);
Jakub Jelen 209c7a
@@ -224,7 +228,7 @@ done:
Jakub Jelen 209c7a
 void
Jakub Jelen 209c7a
 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
-	char *fp, *extra;
Jakub Jelen 209c7a
+	char *extra, *pubkey;
Jakub Jelen 209c7a
 	va_list ap;
Jakub Jelen 209c7a
 	int i;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -234,27 +238,13 @@ pubkey_auth_info(Authctxt *authctxt, con
Jakub Jelen 209c7a
 		i = vasprintf(&extra, fmt, ap);
Jakub Jelen 209c7a
 		va_end(ap);
Jakub Jelen 209c7a
 		if (i < 0 || extra == NULL)
Jakub Jelen 209c7a
-			fatal("%s: vasprintf failed", __func__);	
Jakub Jelen 209c7a
+			fatal("%s: vasprintf failed", __func__);
Jakub Jelen 209c7a
 	}
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
-	if (key_is_cert(key)) {
Jakub Jelen 209c7a
-		fp = sshkey_fingerprint(key->cert->signature_key,
Jakub Jelen 209c7a
-		    options.fingerprint_hash, SSH_FP_DEFAULT);
Jakub Jelen 209c7a
-		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
Jakub Jelen 209c7a
-		    key_type(key), key->cert->key_id,
Jakub Jelen 209c7a
-		    (unsigned long long)key->cert->serial,
Jakub Jelen 209c7a
-		    key_type(key->cert->signature_key),
Jakub Jelen 209c7a
-		    fp == NULL ? "(null)" : fp,
Jakub Jelen 209c7a
-		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
Jakub Jelen 209c7a
-		free(fp);
Jakub Jelen 209c7a
-	} else {
Jakub Jelen 209c7a
-		fp = sshkey_fingerprint(key, options.fingerprint_hash,
Jakub Jelen 209c7a
-		    SSH_FP_DEFAULT);
Jakub Jelen 209c7a
-		auth_info(authctxt, "%s %s%s%s", key_type(key),
Jakub Jelen 209c7a
-		    fp == NULL ? "(null)" : fp,
Jakub Jelen 209c7a
-		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
Jakub Jelen 209c7a
-		free(fp);
Jakub Jelen 209c7a
-	}
Jakub Jelen 209c7a
+	pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
Jakub Jelen 209c7a
+	auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ",
Jakub Jelen 209c7a
+	    extra == NULL ? "" : extra);
Jakub Jelen 209c7a
+	free(pubkey);
Jakub Jelen 209c7a
 	free(extra);
Jakub Jelen 209c7a
 }
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth.h.expose-pam openssh-7.2p2/auth.h
Jakub Jelen 209c7a
--- openssh-7.2p2/auth.h.expose-pam	2016-07-18 12:30:12.077783292 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth.h	2016-07-18 12:30:12.123783256 +0200
Jakub Jelen 209c7a
@@ -84,6 +84,9 @@ struct Authctxt {
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	struct sshkey	**prev_userkeys;
Jakub Jelen 209c7a
 	u_int		 nprev_userkeys;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
+	char		*last_details;
Jakub Jelen 209c7a
+	char		*auth_details;
Jakub Jelen 209c7a
 };
Jakub Jelen 209c7a
 /*
Jakub Jelen 209c7a
  * Every authentication method has to handle authentication requests for
Jakub Jelen 209c7a
diff -up openssh-7.2p2/auth-pam.c.expose-pam openssh-7.2p2/auth-pam.c
Jakub Jelen 209c7a
--- openssh-7.2p2/auth-pam.c.expose-pam	2016-07-18 12:30:12.026783332 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/auth-pam.c	2016-07-18 12:30:12.123783256 +0200
Jakub Jelen 209c7a
@@ -689,6 +689,11 @@ sshpam_init_ctx(Authctxt *authctxt)
Jakub Jelen 209c7a
 		return (NULL);
Jakub Jelen 209c7a
 	}
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	/* Notify PAM about any already successful auth methods */
Jakub Jelen 209c7a
+	if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMONLY &&
Jakub Jelen 209c7a
+			authctxt->auth_details)
Jakub Jelen 209c7a
+		do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details);
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	ctxt = xcalloc(1, sizeof *ctxt);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	/* Start the authentication thread */
Jakub Jelen 209c7a
diff -up openssh-7.2p2/gss-serv.c.expose-pam openssh-7.2p2/gss-serv.c
Jakub Jelen 209c7a
--- openssh-7.2p2/gss-serv.c.expose-pam	2016-07-18 12:30:12.124783255 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/gss-serv.c	2016-07-18 12:33:08.835644264 +0200
Jakub Jelen 209c7a
@@ -441,6 +441,16 @@ ssh_gssapi_do_child(char ***envp, u_int
Jakub Jelen 209c7a
 }
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 /* Privileged */
Jakub Jelen 209c7a
+char*
Jakub Jelen 209c7a
+ssh_gssapi_get_displayname(void)
Jakub Jelen 209c7a
+{
Jakub Jelen 209c7a
+	if (gssapi_client.displayname.length != 0 &&
Jakub Jelen 209c7a
+	    gssapi_client.displayname.value != NULL)
Jakub Jelen 209c7a
+		return strdup((char *)gssapi_client.displayname.value);
Jakub Jelen 209c7a
+	return NULL;
Jakub Jelen 209c7a
+}
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
+/* Privileged */
Jakub Jelen 209c7a
 int
Jakub Jelen 209c7a
 ssh_gssapi_userok(char *user, struct passwd *pw)
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
diff -up openssh-7.2p2/monitor.c.expose-pam openssh-7.2p2/monitor.c
Jakub Jelen 209c7a
--- openssh-7.2p2/monitor.c.expose-pam	2016-07-18 12:30:12.093783279 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/monitor.c	2016-07-18 12:30:12.124783255 +0200
Jakub Jelen 209c7a
@@ -349,6 +349,7 @@ monitor_child_preauth(Authctxt *_authctx
Jakub Jelen 209c7a
 {
Jakub Jelen 209c7a
 	struct mon_table *ent;
Jakub Jelen 209c7a
 	int authenticated = 0, partial = 0;
Jakub Jelen 209c7a
+	char *prev_auth_details;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	debug3("preauth child monitor started");
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -386,6 +387,18 @@ monitor_child_preauth(Authctxt *_authctx
Jakub Jelen 209c7a
 		auth_submethod = NULL;
Jakub Jelen 209c7a
 		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+		if (authenticated) {
Jakub Jelen 209c7a
+			prev_auth_details = authctxt->auth_details;
Jakub Jelen 209c7a
+			xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
Jakub Jelen 209c7a
+			    prev_auth_details ? prev_auth_details : "",
Jakub Jelen 209c7a
+			    prev_auth_details ? ", " : "", auth_method,
Jakub Jelen 209c7a
+			    authctxt->last_details ? ": " : "",
Jakub Jelen 209c7a
+			    authctxt->last_details ? authctxt->last_details : "");
Jakub Jelen 209c7a
+			free(prev_auth_details);
Jakub Jelen 209c7a
+		}
Jakub Jelen 209c7a
+		free(authctxt->last_details);
Jakub Jelen 209c7a
+		authctxt->last_details = NULL;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 		/* Special handling for multiple required authentications */
Jakub Jelen 209c7a
 		if (options.num_auth_methods != 0) {
Jakub Jelen 209c7a
 			if (!compat20)
Jakub Jelen 209c7a
@@ -1498,6 +1511,10 @@ mm_answer_keyverify(int sock, Buffer *m)
Jakub Jelen 209c7a
 	debug3("%s: key %p signature %s",
Jakub Jelen 209c7a
 	    __func__, key, (verified == 1) ? "verified" : "unverified");
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (verified == 1)
Jakub Jelen 209c7a
+		authctxt->last_details = sshkey_format_oneline(key,
Jakub Jelen 209c7a
+		    options.fingerprint_hash);
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	/* If auth was successful then record key to ensure it isn't reused */
Jakub Jelen 209c7a
 	if (verified == 1 && key_blobtype == MM_USERKEY)
Jakub Jelen 209c7a
 		auth2_record_userkey(authctxt, key);
Jakub Jelen 209c7a
@@ -2140,6 +2157,9 @@ mm_answer_gss_userok(int sock, Buffer *m
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	auth_method = "gssapi-with-mic";
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (authenticated)
Jakub Jelen 209c7a
+		authctxt->last_details = ssh_gssapi_get_displayname();
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	/* Monitor loop will terminate if authenticated */
Jakub Jelen 209c7a
 	return (authenticated);
Jakub Jelen 209c7a
 }
Jakub Jelen 209c7a
diff -up openssh-7.2p2/servconf.c.expose-pam openssh-7.2p2/servconf.c
Jakub Jelen 209c7a
--- openssh-7.2p2/servconf.c.expose-pam	2016-07-18 12:30:12.112783264 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/servconf.c	2016-07-18 12:34:38.170574004 +0200
Jakub Jelen 209c7a
@@ -176,6 +176,7 @@ initialize_server_options(ServerOptions
Jakub Jelen 209c7a
 	options->fingerprint_hash = -1;
Jakub Jelen 209c7a
 	options->use_kuserok = -1;
Jakub Jelen 209c7a
 	options->enable_k5users = -1;
Jakub Jelen 209c7a
+	options->expose_auth_methods = -1;
Jakub Jelen 209c7a
 }
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
Jakub Jelen 209c7a
@@ -374,6 +375,8 @@ fill_default_server_options(ServerOption
Jakub Jelen 209c7a
 		options->enable_k5users = 0;
Jakub Jelen 209c7a
 	if (options->use_kuserok == -1)
Jakub Jelen 209c7a
 		options->use_kuserok = 1;
Jakub Jelen 209c7a
+	if (options->expose_auth_methods == -1)
Jakub Jelen 209c7a
+		options->expose_auth_methods = EXPOSE_AUTHMETH_NEVER;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	assemble_algorithms(options);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -451,6 +454,7 @@ typedef enum {
Jakub Jelen 209c7a
 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
Jakub Jelen 209c7a
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
Jakub Jelen 209c7a
 	sAllowStreamLocalForwarding, sFingerprintHash,
Jakub Jelen 209c7a
+	sExposeAuthenticationMethods,
Jakub Jelen 209c7a
 	sDeprecated, sUnsupported
Jakub Jelen 209c7a
 } ServerOpCodes;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -606,6 +610,7 @@ static struct {
Jakub Jelen 209c7a
 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
Jakub Jelen 209c7a
 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
Jakub Jelen 209c7a
 	{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
Jakub Jelen 209c7a
+	{ "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_ALL },
Jakub Jelen 209c7a
 	{ NULL, sBadOption, 0 }
Jakub Jelen 209c7a
 };
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -994,6 +999,12 @@ static const struct multistate multistat
Jakub Jelen 209c7a
 	{ "local",			FORWARD_LOCAL },
Jakub Jelen 209c7a
 	{ NULL, -1 }
Jakub Jelen 209c7a
 };
Jakub Jelen 209c7a
+static const struct multistate multistate_exposeauthmeth[] = {
Jakub Jelen 209c7a
+	{ "never",			EXPOSE_AUTHMETH_NEVER },
Jakub Jelen 209c7a
+	{ "pam-only",			EXPOSE_AUTHMETH_PAMONLY },
Jakub Jelen 209c7a
+	{ "pam-and-env",		EXPOSE_AUTHMETH_PAMENV },
Jakub Jelen 209c7a
+	{ NULL, -1}
Jakub Jelen 209c7a
+};
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 int
Jakub Jelen 209c7a
 process_server_config_line(ServerOptions *options, char *line,
Jakub Jelen 209c7a
@@ -1918,6 +1929,11 @@ process_server_config_line(ServerOptions
Jakub Jelen 209c7a
 			options->fingerprint_hash = value;
Jakub Jelen 209c7a
 		break;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	case sExposeAuthenticationMethods:
Jakub Jelen 209c7a
+		intptr = &options->expose_auth_methods;
Jakub Jelen 209c7a
+		multistate_ptr = multistate_exposeauthmeth;
Jakub Jelen 209c7a
+		goto parse_multistate;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	case sDeprecated:
Jakub Jelen 209c7a
 		logit("%s line %d: Deprecated option %s",
Jakub Jelen 209c7a
 		    filename, linenum, arg);
Jakub Jelen 209c7a
@@ -2076,6 +2092,7 @@ copy_set_server_options(ServerOptions *d
Jakub Jelen 209c7a
 	M_CP_INTOPT(enable_k5users);
Jakub Jelen 209c7a
 	M_CP_INTOPT(rekey_limit);
Jakub Jelen 209c7a
 	M_CP_INTOPT(rekey_interval);
Jakub Jelen 209c7a
+	M_CP_INTOPT(expose_auth_methods);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
Jakub Jelen 209c7a
 #define M_CP_STROPT(n) do {\
Jakub Jelen 209c7a
@@ -2181,6 +2198,8 @@ fmt_intarg(ServerOpCodes code, int val)
Jakub Jelen 209c7a
 		return fmt_multistate_int(val, multistate_tcpfwd);
Jakub Jelen 209c7a
 	case sFingerprintHash:
Jakub Jelen 209c7a
 		return ssh_digest_alg_name(val);
Jakub Jelen 209c7a
+	case sExposeAuthenticationMethods:
Jakub Jelen 209c7a
+		return fmt_multistate_int(val, multistate_exposeauthmeth);
Jakub Jelen 209c7a
 	case sProtocol:
Jakub Jelen 209c7a
 		switch (val) {
Jakub Jelen 209c7a
 		case SSH_PROTO_1:
Jakub Jelen 209c7a
@@ -2374,6 +2393,7 @@ dump_config(ServerOptions *o)
Jakub Jelen 209c7a
 	dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
Jakub Jelen 209c7a
 	dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
Jakub Jelen 209c7a
 	dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users);
Jakub Jelen 209c7a
+	dump_cfg_fmtint(sExposeAuthenticationMethods, o->expose_auth_methods);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	/* string arguments */
Jakub Jelen 209c7a
 	dump_cfg_string(sPidFile, o->pid_file);
Jakub Jelen 209c7a
diff -up openssh-7.2p2/servconf.h.expose-pam openssh-7.2p2/servconf.h
Jakub Jelen 209c7a
--- openssh-7.2p2/servconf.h.expose-pam	2016-07-18 12:30:12.112783264 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/servconf.h	2016-07-18 12:30:12.125783254 +0200
Jakub Jelen 209c7a
@@ -48,6 +48,11 @@
Jakub Jelen 209c7a
 #define FORWARD_LOCAL		(1<<1)
Jakub Jelen 209c7a
 #define FORWARD_ALLOW		(FORWARD_REMOTE|FORWARD_LOCAL)
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+/* Expose AuthenticationMethods */
Jakub Jelen 209c7a
+#define EXPOSE_AUTHMETH_NEVER   0
Jakub Jelen 209c7a
+#define EXPOSE_AUTHMETH_PAMONLY 1
Jakub Jelen 209c7a
+#define EXPOSE_AUTHMETH_PAMENV  2
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 #define DEFAULT_AUTH_FAIL_MAX	6	/* Default for MaxAuthTries */
Jakub Jelen 209c7a
 #define DEFAULT_SESSIONS_MAX	10	/* Default for MaxSessions */
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -201,6 +206,8 @@ typedef struct {
Jakub Jelen 209c7a
 	char   *auth_methods[MAX_AUTH_METHODS];
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 	int	fingerprint_hash;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
+	int	expose_auth_methods; /* EXPOSE_AUTHMETH_* above */
Jakub Jelen 209c7a
 }       ServerOptions;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 /* Information about the incoming connection as used by Match */
Jakub Jelen 209c7a
diff -up openssh-7.2p2/session.c.expose-pam openssh-7.2p2/session.c
Jakub Jelen 209c7a
--- openssh-7.2p2/session.c.expose-pam	2016-07-18 12:30:12.120783258 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/session.c	2016-07-18 12:30:12.125783254 +0200
Jakub Jelen 209c7a
@@ -1180,6 +1180,12 @@ copy_environment(char **source, char ***
Jakub Jelen 209c7a
 		}
Jakub Jelen 209c7a
 		*var_val++ = '\0';
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+		if (options.expose_auth_methods < EXPOSE_AUTHMETH_PAMENV &&
Jakub Jelen 209c7a
+				strcmp(var_name, "SSH_USER_AUTH") == 0) {
Jakub Jelen 209c7a
+			free(var_name);
Jakub Jelen 209c7a
+			continue;
Jakub Jelen 209c7a
+		}
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 		debug3("Copy environment: %s=%s", var_name, var_val);
Jakub Jelen 209c7a
 		child_set_env(env, envsize, var_name, var_val);
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
@@ -1359,6 +1365,11 @@ do_setup_env(Session *s, const char *she
Jakub Jelen 209c7a
 	}
Jakub Jelen 209c7a
 #endif /* USE_PAM */
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMENV &&
Jakub Jelen 209c7a
+			s->authctxt->auth_details)
Jakub Jelen 209c7a
+		child_set_env(&env, &envsize, "SSH_USER_AUTH",
Jakub Jelen 209c7a
+		     s->authctxt->auth_details);
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 	if (auth_sock_name != NULL)
Jakub Jelen 209c7a
 		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
Jakub Jelen 209c7a
 		    auth_sock_name);
Jakub Jelen 209c7a
@@ -2798,6 +2809,9 @@ do_cleanup(Authctxt *authctxt)
Jakub Jelen 209c7a
 	if (authctxt == NULL)
Jakub Jelen 209c7a
 		return;
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+	free(authctxt->auth_details);
Jakub Jelen 209c7a
+	authctxt->auth_details = NULL;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 #ifdef USE_PAM
Jakub Jelen 209c7a
 	if (options.use_pam) {
Jakub Jelen 209c7a
 		sshpam_cleanup();
Jakub Jelen 209c7a
diff -up openssh-7.2p2/ssh.1.expose-pam openssh-7.2p2/ssh.1
Jakub Jelen 209c7a
--- openssh-7.2p2/ssh.1.expose-pam	2016-07-18 12:30:12.112783264 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/ssh.1	2016-07-18 12:30:12.126783253 +0200
Jakub Jelen 209c7a
@@ -1396,6 +1396,10 @@ server IP address, and server port numbe
Jakub Jelen 209c7a
 This variable contains the original command line if a forced command
Jakub Jelen 209c7a
 is executed.
Jakub Jelen 209c7a
 It can be used to extract the original arguments.
Jakub Jelen 209c7a
+.It Ev SSH_USER_AUTH
Jakub Jelen 209c7a
+This variable contains, for SSH2 only, a comma-separated list of authentication
Jakub Jelen 209c7a
+methods that were successfuly used to authenticate. When possible, these
Jakub Jelen 209c7a
+methods are extended with detailed information on the credential used.
Jakub Jelen 209c7a
 .It Ev SSH_TTY
Jakub Jelen 209c7a
 This is set to the name of the tty (path to the device) associated
Jakub Jelen 209c7a
 with the current shell or command.
Jakub Jelen 209c7a
diff -up openssh-7.2p2/sshd_config.5.expose-pam openssh-7.2p2/sshd_config.5
Jakub Jelen 209c7a
--- openssh-7.2p2/sshd_config.5.expose-pam	2016-07-18 12:30:12.113783263 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/sshd_config.5	2016-07-18 12:30:12.126783253 +0200
Jakub Jelen 209c7a
@@ -570,6 +570,21 @@ and finally
Jakub Jelen 209c7a
 See PATTERNS in
Jakub Jelen 209c7a
 .Xr ssh_config 5
Jakub Jelen 209c7a
 for more information on patterns.
Jakub Jelen 209c7a
+.It Cm ExposeAuthenticationMethods
Jakub Jelen 209c7a
+When using SSH2, this option controls the exposure of the list of
Jakub Jelen 209c7a
+successful authentication methods to PAM during the authentication
Jakub Jelen 209c7a
+and to the shell environment via the
Jakub Jelen 209c7a
+.Cm SSH_USER_AUTH
Jakub Jelen 209c7a
+variable. See the description of this variable for more details.
Jakub Jelen 209c7a
+Valid options are:
Jakub Jelen 209c7a
+.Dq never
Jakub Jelen 209c7a
+(Do not expose successful authentication methods),
Jakub Jelen 209c7a
+.Dq pam-only
Jakub Jelen 209c7a
+(Only expose them to PAM during authentication, not afterwards),
Jakub Jelen 209c7a
+.Dq pam-and-env
Jakub Jelen 209c7a
+(Expose them to PAM and keep them in the shell environment).
Jakub Jelen 209c7a
+The default is
Jakub Jelen 209c7a
+.Dq never .
Jakub Jelen 209c7a
 .It Cm FingerprintHash
Jakub Jelen 209c7a
 Specifies the hash algorithm used when logging key fingerprints.
Jakub Jelen 209c7a
 Valid options are:
Jakub Jelen 209c7a
diff -up openssh-7.2p2/ssh-gss.h.expose-pam openssh-7.2p2/ssh-gss.h
Jakub Jelen 209c7a
--- openssh-7.2p2/ssh-gss.h.expose-pam	2016-07-18 12:30:12.125783254 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/ssh-gss.h	2016-07-18 12:35:01.906555328 +0200
Jakub Jelen 209c7a
@@ -159,6 +159,7 @@ int ssh_gssapi_server_check_mech(Gssctxt
Jakub Jelen 209c7a
     const char *);
Jakub Jelen 209c7a
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
Jakub Jelen 209c7a
 int ssh_gssapi_userok(char *name, struct passwd *);
Jakub Jelen 209c7a
+char* ssh_gssapi_get_displayname(void);
Jakub Jelen 209c7a
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
Jakub Jelen 209c7a
 void ssh_gssapi_do_child(char ***, u_int *);
Jakub Jelen 209c7a
 void ssh_gssapi_cleanup_creds(void);
Jakub Jelen 209c7a
diff -up openssh-7.2p2/sshkey.c.expose-pam openssh-7.2p2/sshkey.c
Jakub Jelen 209c7a
--- openssh-7.2p2/sshkey.c.expose-pam	2016-07-18 12:30:12.071783296 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/sshkey.c	2016-07-18 12:30:12.126783253 +0200
Jakub Jelen 209c7a
@@ -58,6 +58,7 @@
Jakub Jelen 209c7a
 #define SSHKEY_INTERNAL
Jakub Jelen 209c7a
 #include "sshkey.h"
Jakub Jelen 209c7a
 #include "match.h"
Jakub Jelen 209c7a
+#include "xmalloc.h"
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
 /* openssh private key file format */
Jakub Jelen 209c7a
 #define MARK_BEGIN		"-----BEGIN OPENSSH PRIVATE KEY-----\n"
Jakub Jelen 209c7a
@@ -1190,6 +1191,30 @@ sshkey_fingerprint(const struct sshkey *
Jakub Jelen 209c7a
 	return retval;
Jakub Jelen 209c7a
 }
Jakub Jelen 209c7a
 
Jakub Jelen 209c7a
+char *
Jakub Jelen 209c7a
+sshkey_format_oneline(const struct sshkey *key, int dgst_alg)
Jakub Jelen 209c7a
+{
Jakub Jelen 209c7a
+	char *fp, *result;
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
+	if (sshkey_is_cert(key)) {
Jakub Jelen 209c7a
+		fp = sshkey_fingerprint(key->cert->signature_key, dgst_alg,
Jakub Jelen 209c7a
+		    SSH_FP_DEFAULT);
Jakub Jelen 209c7a
+		xasprintf(&result, "%s ID %s (serial %llu) CA %s %s",
Jakub Jelen 209c7a
+		    sshkey_type(key), key->cert->key_id,
Jakub Jelen 209c7a
+		    (unsigned long long)key->cert->serial,
Jakub Jelen 209c7a
+		    sshkey_type(key->cert->signature_key),
Jakub Jelen 209c7a
+		    fp == NULL ? "(null)" : fp);
Jakub Jelen 209c7a
+		free(fp);
Jakub Jelen 209c7a
+	} else {
Jakub Jelen 209c7a
+		fp = sshkey_fingerprint(key, dgst_alg, SSH_FP_DEFAULT);
Jakub Jelen 209c7a
+		xasprintf(&result, "%s %s", sshkey_type(key),
Jakub Jelen 209c7a
+		    fp == NULL ? "(null)" : fp);
Jakub Jelen 209c7a
+		free(fp);
Jakub Jelen 209c7a
+	}
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
+	return result;
Jakub Jelen 209c7a
+}
Jakub Jelen 209c7a
+
Jakub Jelen 209c7a
 #ifdef WITH_SSH1
Jakub Jelen 209c7a
 /*
Jakub Jelen 209c7a
  * Reads a multiple-precision integer in decimal from the buffer, and advances
Jakub Jelen 209c7a
diff -up openssh-7.2p2/sshkey.h.expose-pam openssh-7.2p2/sshkey.h
Jakub Jelen 209c7a
--- openssh-7.2p2/sshkey.h.expose-pam	2016-07-18 12:30:12.071783296 +0200
Jakub Jelen 209c7a
+++ openssh-7.2p2/sshkey.h	2016-07-18 12:30:12.127783252 +0200
Jakub Jelen 209c7a
@@ -124,6 +124,7 @@ char		*sshkey_fingerprint(const struct s
Jakub Jelen 209c7a
     int, enum sshkey_fp_rep);
Jakub Jelen 209c7a
 int		 sshkey_fingerprint_raw(const struct sshkey *k,
Jakub Jelen 209c7a
     int, u_char **retp, size_t *lenp);
Jakub Jelen 209c7a
+char		*sshkey_format_oneline(const struct sshkey *k, int dgst_alg);
Jakub Jelen 209c7a
 const char	*sshkey_type(const struct sshkey *);
Jakub Jelen 209c7a
 const char	*sshkey_cert_type(const struct sshkey *);
Jakub Jelen 209c7a
 int		 sshkey_write(const struct sshkey *, FILE *);