vishalmishra434 / rpms / openssh

Forked from rpms/openssh a month ago
Clone
Jakub Jelen 5b55d0
diff -up openssh/auth2.c.gsskex openssh/auth2.c
Jakub Jelen bbf61d
--- openssh/auth2.c.gsskex	2018-08-22 11:47:33.260216045 +0200
Jakub Jelen bbf61d
+++ openssh/auth2.c	2018-08-22 11:47:33.307216424 +0200
Jakub Jelen bbf61d
@@ -74,6 +74,7 @@ extern Authmethod method_passwd;
Jakub Jelen 535d34
 extern Authmethod method_kbdint;
Jakub Jelen 535d34
 extern Authmethod method_hostbased;
Jakub Jelen 535d34
 #ifdef GSSAPI
Jakub Jelen 535d34
+extern Authmethod method_gsskeyex;
Jakub Jelen 535d34
 extern Authmethod method_gssapi;
Jakub Jelen 535d34
 #endif
Jakub Jelen 535d34
 
Jakub Jelen bbf61d
@@ -81,6 +82,7 @@ Authmethod *authmethods[] = {
Jakub Jelen 535d34
 	&method_none,
Jakub Jelen 535d34
 	&method_pubkey,
Jakub Jelen 535d34
 #ifdef GSSAPI
Jakub Jelen 535d34
+	&method_gsskeyex,
Jakub Jelen 535d34
 	&method_gssapi,
Jakub Jelen 535d34
 #endif
Jakub Jelen 535d34
 	&method_passwd,
Jakub Jelen 5b55d0
diff -up openssh/auth2-gss.c.gsskex openssh/auth2-gss.c
Jakub Jelen bbf61d
--- openssh/auth2-gss.c.gsskex	2018-08-22 11:47:33.260216045 +0200
Jakub Jelen bbf61d
+++ openssh/auth2-gss.c	2018-08-22 13:00:48.722680124 +0200
Jakub Jelen 580f98
@@ -31,6 +31,7 @@
Jakub Jelen 580f98
 #include <sys/types.h>
Jakub Jelen 580f98
 
Jakub Jelen 580f98
 #include <stdarg.h>
Jakub Jelen 580f98
+#include <string.h>
Jakub Jelen 580f98
 
Jakub Jelen 580f98
 #include "xmalloc.h"
Jakub Jelen bbf61d
 #include "sshkey.h"
Jakub Jelen 90edc0
@@ -54,6 +55,44 @@ static int input_gssapi_mic(int type, u_
Jakub Jelen 5b55d0
 static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);
Jakub Jelen 5b55d0
 static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
Petr Lautrbach 84822b
 
Petr Lautrbach 84822b
+/* 
Petr Lautrbach 84822b
+ * The 'gssapi_keyex' userauth mechanism.
Petr Lautrbach 84822b
+ */
Petr Lautrbach 84822b
+static int
Jakub Jelen 5b55d0
+userauth_gsskeyex(struct ssh *ssh)
Petr Lautrbach 84822b
+{
Jakub Jelen 5b55d0
+	Authctxt *authctxt = ssh->authctxt;
Petr Lautrbach 84822b
+	int authenticated = 0;
Jakub Jelen bbf61d
+	struct sshbuf *b = NULL;
Petr Lautrbach 84822b
+	gss_buffer_desc mic, gssbuf;
Petr Lautrbach 84822b
+	u_int len;
Petr Lautrbach 51ca3b
+
Petr Lautrbach 84822b
+	mic.value = packet_get_string(&len;;
Petr Lautrbach 84822b
+	mic.length = len;
Petr Lautrbach 51ca3b
+
Petr Lautrbach 84822b
+	packet_check_eom();
Petr Lautrbach 51ca3b
+
Jakub Jelen 90edc0
+	if ((b = sshbuf_new()) == NULL)
Jakub Jelen 90edc0
+		fatal("%s: sshbuf_new failed", __func__);
Jakub Jelen 90edc0
+
Jakub Jelen bbf61d
+	ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
Petr Lautrbach 84822b
+	    "gssapi-keyex");
Petr Lautrbach 51ca3b
+
Jakub Jelen bbf61d
+	gssbuf.value = sshbuf_mutable_ptr(b);
Jakub Jelen bbf61d
+	gssbuf.length = sshbuf_len(b);
Petr Lautrbach 5039c7
+
Petr Lautrbach 84822b
+	/* gss_kex_context is NULL with privsep, so we can't check it here */
Petr Lautrbach 84822b
+	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
Petr Lautrbach 84822b
+	    &gssbuf, &mic))))
Petr Lautrbach 84822b
+		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
Petr Lautrbach 84822b
+		    authctxt->pw));
Petr Lautrbach 84822b
+	
Jakub Jelen bbf61d
+	sshbuf_free(b);
Petr Lautrbach 84822b
+	free(mic.value);
Petr Lautrbach 5039c7
+
Petr Lautrbach 84822b
+	return (authenticated);
Petr Lautrbach 84822b
+}
Petr Lautrbach 5039c7
+
Petr Lautrbach 84822b
 /*
Petr Lautrbach 84822b
  * We only support those mechanisms that we know about (ie ones that we know
Petr Lautrbach 84822b
  * how to check local user kuserok and the like)
Jakub Jelen bbf61d
@@ -260,7 +296,8 @@ input_gssapi_exchange_complete(int type,
Jakub Jelen bbf61d
 	if ((r = sshpkt_get_end(ssh)) != 0)
Jakub Jelen bbf61d
 		fatal("%s: %s", __func__, ssh_err(r));
Petr Lautrbach 84822b
 
Petr Lautrbach 84822b
-	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
Petr Lautrbach 84822b
+	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
Petr Lautrbach 84822b
+	    authctxt->pw));
Petr Lautrbach 84822b
 
Jakub Jelen 5b55d0
 	if ((!use_privsep || mm_is_monitor()) &&
Jakub Jelen 5b55d0
 	    (displayname = ssh_gssapi_displayname()) != NULL)
Jakub Jelen bbf61d
@@ -313,7 +350,8 @@ input_gssapi_mic(int type, u_int32_t ple
Jakub Jelen bbf61d
 	gssbuf.length = sshbuf_len(b);
Petr Lautrbach 84822b
 
Petr Lautrbach 84822b
 	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
Petr Lautrbach 84822b
-		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
Petr Lautrbach 84822b
+		authenticated = 
Petr Lautrbach 84822b
+		    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
Petr Lautrbach 84822b
 	else
Petr Lautrbach 84822b
 		logit("GSSAPI MIC check failed");
Petr Lautrbach 84822b
 
Jakub Jelen bbf61d
@@ -335,6 +373,12 @@ input_gssapi_mic(int type, u_int32_t ple
Jakub Jelen 132f8f
 	return 0;
Petr Lautrbach 84822b
 }
Petr Lautrbach 84822b
 
Petr Lautrbach 84822b
+Authmethod method_gsskeyex = {
Petr Lautrbach 84822b
+	"gssapi-keyex",
Petr Lautrbach 84822b
+	userauth_gsskeyex,
Petr Lautrbach 84822b
+	&options.gss_authentication
Petr Lautrbach 84822b
+};
Petr Lautrbach 5039c7
+
Petr Lautrbach 84822b
 Authmethod method_gssapi = {
Petr Lautrbach 84822b
 	"gssapi-with-mic",
Petr Lautrbach 84822b
 	userauth_gssapi,
Jakub Jelen 5b55d0
diff -up openssh/auth.c.gsskex openssh/auth.c
Jakub Jelen bbf61d
--- openssh/auth.c.gsskex	2018-08-22 11:47:33.274216158 +0200
Jakub Jelen bbf61d
+++ openssh/auth.c	2018-08-22 11:47:33.308216432 +0200
Jakub Jelen bbf61d
@@ -395,6 +395,7 @@ auth_root_allowed(struct ssh *ssh, const
Jakub Jelen 5b55d0
 	case PERMIT_NO_PASSWD:
Jakub Jelen 5b55d0
 		if (strcmp(method, "publickey") == 0 ||
Jakub Jelen 5b55d0
 		    strcmp(method, "hostbased") == 0 ||
Jakub Jelen 5b55d0
+		    strcmp(method, "gssapi-keyex") == 0 ||
Jakub Jelen 5b55d0
 		    strcmp(method, "gssapi-with-mic") == 0)
Jakub Jelen 5b55d0
 			return 1;
Jakub Jelen 5b55d0
 		break;
Jakub Jelen 5b55d0
diff -up openssh/clientloop.c.gsskex openssh/clientloop.c
Jakub Jelen bbf61d
--- openssh/clientloop.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/clientloop.c	2018-08-22 11:47:33.309216441 +0200
Jakub Jelen 5b55d0
@@ -112,6 +112,10 @@
Jakub Jelen 132f8f
 #include "ssherr.h"
Jakub Jelen 132f8f
 #include "hostfile.h"
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+#include "ssh-gss.h"
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 /* import options */
Jan F. Chadima 69dd72
 extern Options options;
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
@@ -1357,9 +1361,18 @@ client_loop(struct ssh *ssh, int have_pt
Jakub Jelen 13073f
 			break;
Jakub Jelen 13073f
 
Jan F. Chadima 69dd72
 		/* Do channel operations unless rekeying in progress. */
Jakub Jelen 5b55d0
-		if (!ssh_packet_is_rekeying(ssh))
Jakub Jelen 5b55d0
+		if (!ssh_packet_is_rekeying(ssh)) {
Jakub Jelen 5b55d0
 			channel_after_select(ssh, readset, writeset);
Jakub Jelen 13073f
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+			if (options.gss_renewal_rekey &&
Jakub Jelen 6cf9b8
+			    ssh_gssapi_credentials_updated(NULL)) {
Jan F. Chadima 69dd72
+				debug("credentials updated - forcing rekey");
Jan F. Chadima 69dd72
+				need_rekeying = 1;
Jan F. Chadima 69dd72
+			}
Jan F. Chadima 69dd72
+#endif
Jakub Jelen 13073f
+		}
Jan F. Chadima 69dd72
+
Jakub Jelen 13073f
 		/* Buffer input from the connection.  */
Jakub Jelen 13073f
 		client_process_net_input(readset);
Jakub Jelen 13073f
 
Jakub Jelen 5b55d0
diff -up openssh/configure.ac.gsskex openssh/configure.ac
Jakub Jelen bbf61d
--- openssh/configure.ac.gsskex	2018-08-22 11:47:33.296216335 +0200
Jakub Jelen bbf61d
+++ openssh/configure.ac	2018-08-22 11:47:33.309216441 +0200
Jakub Jelen bbf61d
@@ -673,6 +673,30 @@ main() { if (NSVersionOfRunTimeLibrary("
Jan F. Chadima 69dd72
 	    [Use tunnel device compatibility to OpenBSD])
Jan F. Chadima 69dd72
 	AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
Jan F. Chadima 69dd72
 	    [Prepend the address family to IP tunnel traffic])
Jan F. Chadima 69dd72
+	AC_MSG_CHECKING(if we have the Security Authorization Session API)
Jan F. Chadima 69dd72
+	AC_TRY_COMPILE([#include <Security/AuthSession.h>],
Jan F. Chadima 69dd72
+		[SessionCreate(0, 0);],
Jan F. Chadima 69dd72
+		[ac_cv_use_security_session_api="yes"
Jan F. Chadima 69dd72
+		 AC_DEFINE(USE_SECURITY_SESSION_API, 1, 
Jan F. Chadima 69dd72
+			[platform has the Security Authorization Session API])
Jan F. Chadima 69dd72
+		 LIBS="$LIBS -framework Security"
Jan F. Chadima 69dd72
+		 AC_MSG_RESULT(yes)],
Jan F. Chadima 69dd72
+		[ac_cv_use_security_session_api="no"
Jan F. Chadima 69dd72
+		 AC_MSG_RESULT(no)])
Jan F. Chadima 69dd72
+	AC_MSG_CHECKING(if we have an in-memory credentials cache)
Jan F. Chadima 69dd72
+	AC_TRY_COMPILE(
Jan F. Chadima 69dd72
+		[#include <Kerberos/Kerberos.h>],
Jan F. Chadima 69dd72
+		[cc_context_t c;
Jan F. Chadima 69dd72
+		 (void) cc_initialize (&c, 0, NULL, NULL);],
Jan F. Chadima 69dd72
+		[AC_DEFINE(USE_CCAPI, 1, 
Jan F. Chadima 69dd72
+			[platform uses an in-memory credentials cache])
Jan F. Chadima 69dd72
+		 LIBS="$LIBS -framework Security"
Jan F. Chadima 69dd72
+		 AC_MSG_RESULT(yes)
Jan F. Chadima 69dd72
+		 if test "x$ac_cv_use_security_session_api" = "xno"; then
Jan F. Chadima 69dd72
+			AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
Jan F. Chadima 69dd72
+		fi],
Jan F. Chadima 69dd72
+		[AC_MSG_RESULT(no)]
Jan F. Chadima 69dd72
+	)
Jan F. Chadima 69dd72
 	m4_pattern_allow([AU_IPv])
Jakub Jelen 5878eb
 	AC_CHECK_DECL([AU_IPv4], [],
Jan F. Chadima 69dd72
 	    AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
Jakub Jelen 5b55d0
diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c
Jakub Jelen bbf61d
--- openssh/gss-genr.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/gss-genr.c	2018-08-22 13:18:47.444383602 +0200
Jakub Jelen eaa7af
@@ -35,18 +35,179 @@
Jakub Jelen bbf61d
 #include <string.h>
Jakub Jelen bbf61d
 #include <signal.h>
Jakub Jelen bbf61d
 #include <unistd.h>
Jakub Jelen bbf61d
+#include <openssl/evp.h>
Jakub Jelen bbf61d
 
Jakub Jelen bbf61d
 #include "xmalloc.h"
Jakub Jelen bbf61d
 #include "ssherr.h"
Jakub Jelen bbf61d
 #include "sshbuf.h"
Jan F. Chadima 69dd72
 #include "log.h"
Jan F. Chadima 69dd72
 #include "ssh2.h"
Jan F. Chadima 69dd72
+#include "cipher.h"
Jakub Jelen bbf61d
+#include "sshkey.h"
Jan F. Chadima 69dd72
+#include "kex.h"
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #include "ssh-gss.h"
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 extern u_char *session_id2;
Jan F. Chadima 69dd72
 extern u_int session_id2_len;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+typedef struct {
Jan F. Chadima 69dd72
+	char *encoded;
Jan F. Chadima 69dd72
+	gss_OID oid;
Jan F. Chadima 69dd72
+} ssh_gss_kex_mapping;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+/*
Jan F. Chadima 69dd72
+ * XXX - It would be nice to find a more elegant way of handling the
Jan F. Chadima 69dd72
+ * XXX   passing of the key exchange context to the userauth routines
Jan F. Chadima 69dd72
+ */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+Gssctxt *gss_kex_context = NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+int 
Jan F. Chadima 69dd72
+ssh_gssapi_oid_table_ok() {
Jan F. Chadima 69dd72
+	return (gss_enc2oid != NULL);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+/*
Jan F. Chadima 69dd72
+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * We test mechanisms to ensure that we can use them, to avoid starting
Jan F. Chadima 69dd72
+ * a key exchange with a bad mechanism
Jan F. Chadima 69dd72
+ */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+char *
Jan F. Chadima 69dd72
+ssh_gssapi_client_mechanisms(const char *host, const char *client) {
Jan F. Chadima 69dd72
+	gss_OID_set gss_supported;
Jan F. Chadima 69dd72
+	OM_uint32 min_status;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
Jan F. Chadima 69dd72
+		return NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
Jan F. Chadima 69dd72
+	    host, client));
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+char *
Jan F. Chadima 69dd72
+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
Jan F. Chadima 69dd72
+    const char *host, const char *client) {
Jakub Jelen bbf61d
+	struct sshbuf *buf;
Jan F. Chadima 69dd72
+	size_t i;
Jakub Jelen bbf61d
+	int oidpos, enclen, r;
Jan F. Chadima 69dd72
+	char *mechs, *encoded;
Jan F. Chadima 69dd72
+	u_char digest[EVP_MAX_MD_SIZE];
Jan F. Chadima 69dd72
+	char deroid[2];
Jan F. Chadima 69dd72
+	const EVP_MD *evp_md = EVP_md5();
Jakub Jelen eaa7af
+	EVP_MD_CTX *md;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss_enc2oid != NULL) {
Jan F. Chadima 69dd72
+		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
Petr Lautrbach 84822b
+			free(gss_enc2oid[i].encoded);
Petr Lautrbach 84822b
+		free(gss_enc2oid);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
Jan F. Chadima 69dd72
+	    (gss_supported->count + 1));
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((buf = sshbuf_new()) == NULL)
Jakub Jelen bbf61d
+		fatal("%s: sshbuf_new failed", __func__);
Jan F. Chadima 69dd72
+
Jakub Jelen eaa7af
+	md = EVP_MD_CTX_new();
Jan F. Chadima 69dd72
+	oidpos = 0;
Jan F. Chadima 69dd72
+	for (i = 0; i < gss_supported->count; i++) {
Jan F. Chadima 69dd72
+		if (gss_supported->elements[i].length < 128 &&
Jan F. Chadima 69dd72
+		    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			deroid[0] = SSH_GSS_OIDTYPE;
Jan F. Chadima 69dd72
+			deroid[1] = gss_supported->elements[i].length;
Jan F. Chadima 69dd72
+
Jakub Jelen eaa7af
+			EVP_DigestInit(md, evp_md);
Jakub Jelen eaa7af
+			EVP_DigestUpdate(md, deroid, 2);
Jakub Jelen eaa7af
+			EVP_DigestUpdate(md,
Jan F. Chadima 69dd72
+			    gss_supported->elements[i].elements,
Jan F. Chadima 69dd72
+			    gss_supported->elements[i].length);
Jakub Jelen eaa7af
+			EVP_DigestFinal(md, digest, NULL);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			encoded = xmalloc(EVP_MD_size(evp_md) * 2);
Jan F. Chadima 69dd72
+			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
Jan F. Chadima 69dd72
+			    encoded, EVP_MD_size(evp_md) * 2);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			if (oidpos != 0)
Jakub Jelen bbf61d
+				if ((r = sshbuf_put_u8(buf, ',')) != 0)
Jakub Jelen bbf61d
+					fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jakub Jelen bbf61d
+
Jakub Jelen bbf61d
+			if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,
Jakub Jelen bbf61d
+			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put_u8(buf, ',')) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, 
Jakub Jelen bbf61d
+			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put_u8(buf, ',')) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,
Jakub Jelen bbf61d
+			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||
Jakub Jelen bbf61d
+			    (r = sshbuf_put(buf, encoded, enclen)) != 0)
Jakub Jelen bbf61d
+		 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
Jan F. Chadima 69dd72
+			gss_enc2oid[oidpos].encoded = encoded;
Jan F. Chadima 69dd72
+			oidpos++;
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+	}
Jakub Jelen eaa7af
+	EVP_MD_CTX_free(md);
Jan F. Chadima 69dd72
+	gss_enc2oid[oidpos].oid = NULL;
Jan F. Chadima 69dd72
+	gss_enc2oid[oidpos].encoded = NULL;
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_put_u8(buf, '\0')) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	mechs = xmalloc(sshbuf_len(buf));
Jakub Jelen bbf61d
+	sshbuf_get(buf, mechs, sshbuf_len(buf));
Jakub Jelen bbf61d
+	sshbuf_free(buf);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (strlen(mechs) == 0) {
Petr Lautrbach 84822b
+		free(mechs);
Jan F. Chadima 69dd72
+		mechs = NULL;
Jan F. Chadima 69dd72
+	}
Jakub Jelen bbf61d
+
Jan F. Chadima 69dd72
+	return (mechs);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+gss_OID
Jan F. Chadima 69dd72
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
Jan F. Chadima 69dd72
+	int i = 0;
Jan F. Chadima 69dd72
+	
Jan F. Chadima 69dd72
+	switch (kex_type) {
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP1_SHA1:
Jan F. Chadima 69dd72
+		if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
Jan F. Chadima 69dd72
+			return GSS_C_NO_OID;
Jan F. Chadima 69dd72
+		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP14_SHA1:
Jan F. Chadima 69dd72
+		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
Jan F. Chadima 69dd72
+			return GSS_C_NO_OID;
Jan F. Chadima 69dd72
+		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GEX_SHA1:
Jan F. Chadima 69dd72
+		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
Jan F. Chadima 69dd72
+			return GSS_C_NO_OID;
Jan F. Chadima 69dd72
+		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	default:
Jan F. Chadima 69dd72
+		return GSS_C_NO_OID;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	while (gss_enc2oid[i].encoded != NULL &&
Jan F. Chadima 69dd72
+	    strcmp(name, gss_enc2oid[i].encoded) != 0)
Jan F. Chadima 69dd72
+		i++;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss_enc2oid[i].oid != NULL && ctx != NULL)
Jan F. Chadima 69dd72
+		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return gss_enc2oid[i].oid;
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
 /* sshbuf_get for gss_buffer_desc */
Jan F. Chadima 69dd72
 int
Jakub Jelen bbf61d
 ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g)
Jakub Jelen bbf61d
@@ -218,7 +373,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	ctx->major = gss_init_sec_context(&ctx->minor,
Jan F. Chadima 69dd72
-	    GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
Jan F. Chadima 69dd72
+	    ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
Jan F. Chadima 69dd72
 	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
Jan F. Chadima 69dd72
 	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
@@ -248,8 +403,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 OM_uint32
Jan F. Chadima 69dd72
+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	gss_buffer_desc gssbuf;
Jan F. Chadima 69dd72
+	gss_name_t gssname;
Jan F. Chadima 69dd72
+	OM_uint32 status;
Jan F. Chadima 69dd72
+	gss_OID_set oidset;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gssbuf.value = (void *) name;
Jan F. Chadima 69dd72
+	gssbuf.length = strlen(gssbuf.value);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gss_create_empty_oid_set(&status, &oidset);
Jan F. Chadima 69dd72
+	gss_add_oid_set_member(&status, ctx->oid, &oidset);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	ctx->major = gss_import_name(&ctx->minor, &gssbuf,
Jan F. Chadima 69dd72
+	    GSS_C_NT_USER_NAME, &gssname);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (!ctx->major)
Jan F. Chadima 69dd72
+		ctx->major = gss_acquire_cred(&ctx->minor, 
Jan F. Chadima 69dd72
+		    gssname, 0, oidset, GSS_C_INITIATE, 
Jan F. Chadima 69dd72
+		    &ctx->client_creds, NULL, NULL);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gss_release_name(&status, &gssname);
Jan F. Chadima 69dd72
+	gss_release_oid_set(&status, &oidset);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (ctx->major)
Jan F. Chadima 69dd72
+		ssh_gssapi_error(ctx);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return(ctx->major);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+OM_uint32
Jan F. Chadima 69dd72
 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
Jan F. Chadima 69dd72
 {
Jan F. Chadima 69dd72
+	if (ctx == NULL) 
Jan F. Chadima 69dd72
+		return -1;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
Jan F. Chadima 69dd72
 	    GSS_C_QOP_DEFAULT, buffer, hash)))
Jan F. Chadima 69dd72
 		ssh_gssapi_error(ctx);
Jakub Jelen bbf61d
@@ -257,6 +446,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer
Jan F. Chadima 69dd72
 	return (ctx->major);
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+/* Priviledged when used by server */
Jan F. Chadima 69dd72
+OM_uint32
Jan F. Chadima 69dd72
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	if (ctx == NULL)
Jan F. Chadima 69dd72
+		return -1;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
Jan F. Chadima 69dd72
+	    gssbuf, gssmic, NULL);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return (ctx->major);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 void
Jakub Jelen bbf61d
 ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,
Jan F. Chadima 69dd72
     const char *context)
Jakub Jelen bbf61d
@@ -273,11 +475,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 int
Jan F. Chadima 69dd72
-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
Jan F. Chadima 69dd72
+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
Jan F. Chadima 69dd72
+    const char *client)
Jan F. Chadima 69dd72
 {
Jan F. Chadima 69dd72
 	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
 	OM_uint32 major, minor;
Jan F. Chadima 69dd72
 	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
Jan F. Chadima 69dd72
+	Gssctxt *intctx = NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (ctx == NULL)
Jan F. Chadima 69dd72
+		ctx = &intct;;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	/* RFC 4462 says we MUST NOT do SPNEGO */
Jan F. Chadima 69dd72
 	if (oid->length == spnego_oid.length && 
Jakub Jelen bbf61d
@@ -287,6 +494,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx
Jan F. Chadima 69dd72
 	ssh_gssapi_build_ctx(ctx);
Jan F. Chadima 69dd72
 	ssh_gssapi_set_oid(*ctx, oid);
Jan F. Chadima 69dd72
 	major = ssh_gssapi_import_name(*ctx, host);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (!GSS_ERROR(major) && client)
Jan F. Chadima 69dd72
+		major = ssh_gssapi_client_identity(*ctx, client);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	if (!GSS_ERROR(major)) {
Jan F. Chadima 69dd72
 		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
Jan F. Chadima 69dd72
 		    NULL);
Jakub Jelen bbf61d
@@ -296,10 +507,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx
Jan F. Chadima 69dd72
 			    GSS_C_NO_BUFFER);
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
-	if (GSS_ERROR(major)) 
Jan F. Chadima 69dd72
+	if (GSS_ERROR(major) || intctx != NULL) 
Jan F. Chadima 69dd72
 		ssh_gssapi_delete_ctx(ctx);
Jan F. Chadima 69dd72
 
Petr Lautrbach 84822b
 	return (!GSS_ERROR(major));
Petr Lautrbach 84822b
 }
Petr Lautrbach 84822b
 
Petr Lautrbach 84822b
+int
Petr Lautrbach 84822b
+ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
Petr Lautrbach 84822b
+	static gss_name_t saved_name = GSS_C_NO_NAME;
Petr Lautrbach 84822b
+	static OM_uint32 saved_lifetime = 0;
Petr Lautrbach 84822b
+	static gss_OID saved_mech = GSS_C_NO_OID;
Petr Lautrbach 84822b
+	static gss_name_t name;
Petr Lautrbach 84822b
+	static OM_uint32 last_call = 0;
Petr Lautrbach 84822b
+	OM_uint32 lifetime, now, major, minor;
Petr Lautrbach 84822b
+	int equal;
Petr Lautrbach 84822b
+	
Petr Lautrbach 84822b
+	now = time(NULL);
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	if (ctxt) {
Petr Lautrbach 84822b
+		debug("Rekey has happened - updating saved versions");
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+		if (saved_name != GSS_C_NO_NAME)
Petr Lautrbach 84822b
+			gss_release_name(&minor, &saved_name);
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+		major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
Petr Lautrbach 84822b
+		    &saved_name, &saved_lifetime, NULL, NULL);
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+		if (!GSS_ERROR(major)) {
Petr Lautrbach 84822b
+			saved_mech = ctxt->oid;
Petr Lautrbach 84822b
+		        saved_lifetime+= now;
Petr Lautrbach 84822b
+		} else {
Petr Lautrbach 84822b
+			/* Handle the error */
Petr Lautrbach 84822b
+		}
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+	}
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	if (now - last_call < 10)
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	last_call = now;
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	if (saved_mech == GSS_C_NO_OID)
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+	
Petr Lautrbach 84822b
+	major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
Petr Lautrbach 84822b
+	    &name, &lifetime, NULL, NULL);
Petr Lautrbach 84822b
+	if (major == GSS_S_CREDENTIALS_EXPIRED)
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+	else if (GSS_ERROR(major))
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	major = gss_compare_name(&minor, saved_name, name, &equal);
Petr Lautrbach 84822b
+	gss_release_name(&minor, &name);
Petr Lautrbach 84822b
+	if (GSS_ERROR(major))
Petr Lautrbach 84822b
+		return 0;
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	if (equal && (saved_lifetime < lifetime + now - 10))
Petr Lautrbach 84822b
+		return 1;
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
+	return 0;
Petr Lautrbach 84822b
+}
Petr Lautrbach 84822b
+
Petr Lautrbach 84822b
 #endif /* GSSAPI */
Jakub Jelen 5b55d0
diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c
Jakub Jelen bbf61d
--- openssh/gss-serv.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/gss-serv.c	2018-08-22 11:47:33.310216448 +0200
Jakub Jelen bbf61d
@@ -44,17 +44,19 @@
Jan F. Chadima 69dd72
 #include "session.h"
Jan F. Chadima 69dd72
 #include "misc.h"
Jakub Jelen 535d34
 #include "servconf.h"
Jan F. Chadima 69dd72
+#include "uidswap.h"
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #include "ssh-gss.h"
Jan F. Chadima 69dd72
+#include "monitor_wrap.h"
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 extern ServerOptions options;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 static ssh_gssapi_client gssapi_client =
Jakub Jelen 6cf9b8
-    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
Petr Lautrbach 84822b
-    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
Jakub Jelen 6cf9b8
+    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,
Jakub Jelen 117678
+    GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL}, 0, 0};
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 ssh_gssapi_mech gssapi_null_mech =
Jan F. Chadima 69dd72
-    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
Jan F. Chadima 69dd72
+    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #ifdef KRB5
Jan F. Chadima 69dd72
 extern ssh_gssapi_mech gssapi_kerberos_mech;
Jakub Jelen bbf61d
@@ -141,6 +143,28 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 /* Unprivileged */
Jan F. Chadima 69dd72
+char *
Jan F. Chadima 69dd72
+ssh_gssapi_server_mechanisms() {
Jakub Jelen 4189ce
+	if (supported_oids == NULL)
Jakub Jelen 4189ce
+		ssh_gssapi_prepare_supported_oids();
Jakub Jelen 4189ce
+	return (ssh_gssapi_kex_mechs(supported_oids,
Jakub Jelen 4189ce
+	    &ssh_gssapi_server_check_mech, NULL, NULL));
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+/* Unprivileged */
Jan F. Chadima 69dd72
+int
Jan F. Chadima 69dd72
+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
Jan F. Chadima 69dd72
+    const char *dummy) {
Jan F. Chadima 69dd72
+	Gssctxt *ctx = NULL;
Jan F. Chadima 69dd72
+	int res;
Jan F. Chadima 69dd72
+ 
Jan F. Chadima 69dd72
+	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
Jan F. Chadima 69dd72
+	ssh_gssapi_delete_ctx(&ctx;;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return (res);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+/* Unprivileged */
Jan F. Chadima 69dd72
 void
Jan F. Chadima 69dd72
 ssh_gssapi_supported_oids(gss_OID_set *oidset)
Jan F. Chadima 69dd72
 {
Jakub Jelen bbf61d
@@ -150,7 +174,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o
Jan F. Chadima 69dd72
 	gss_OID_set supported;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	gss_create_empty_oid_set(&min_status, oidset);
Jan F. Chadima 69dd72
-	gss_indicate_mechs(&min_status, &supported);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
Jan F. Chadima 69dd72
+		return;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	while (supported_mechs[i]->name != NULL) {
Jan F. Chadima 69dd72
 		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
Jakub Jelen bbf61d
@@ -276,8 +302,48 @@ OM_uint32
Jan F. Chadima 69dd72
 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
Jan F. Chadima 69dd72
 {
Jan F. Chadima 69dd72
 	int i = 0;
Jan F. Chadima 69dd72
+	int equal = 0;
Jan F. Chadima 69dd72
+	gss_name_t new_name = GSS_C_NO_NAME;
Jan F. Chadima 69dd72
+	gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (options.gss_store_rekey && client->used && ctx->client_creds) {
Jan F. Chadima 69dd72
+		if (client->mech->oid.length != ctx->oid->length ||
Jan F. Chadima 69dd72
+		    (memcmp(client->mech->oid.elements,
Jan F. Chadima 69dd72
+		     ctx->oid->elements, ctx->oid->length) !=0)) {
Jan F. Chadima 69dd72
+			debug("Rekeyed credentials have different mechanism");
Jan F. Chadima 69dd72
+			return GSS_S_COMPLETE;
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
Jan F. Chadima 69dd72
+		    ctx->client_creds, ctx->oid, &new_name, 
Jan F. Chadima 69dd72
+		    NULL, NULL, NULL))) {
Jan F. Chadima 69dd72
+			ssh_gssapi_error(ctx);
Jan F. Chadima 69dd72
+			return (ctx->major);
Jan F. Chadima 69dd72
+		}
Jakub Jelen 5b55d0
+
Jan F. Chadima 69dd72
+		ctx->major = gss_compare_name(&ctx->minor, client->name, 
Jan F. Chadima 69dd72
+		    new_name, &equal);
Petr Lautrbach 190035
+
Jan F. Chadima 69dd72
+		if (GSS_ERROR(ctx->major)) {
Jan F. Chadima 69dd72
+			ssh_gssapi_error(ctx);
Jan F. Chadima 69dd72
+			return (ctx->major);
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+ 
Jan F. Chadima 69dd72
+		if (!equal) {
Jan F. Chadima 69dd72
+			debug("Rekeyed credentials have different name");
Jan F. Chadima 69dd72
+			return GSS_S_COMPLETE;
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		debug("Marking rekeyed credentials for export");
Jakub Jelen 5b55d0
 
Jakub Jelen 5b55d0
-	gss_buffer_desc ename;
Jan F. Chadima 69dd72
+		gss_release_name(&ctx->minor, &client->name);
Jan F. Chadima 69dd72
+		gss_release_cred(&ctx->minor, &client->creds);
Jan F. Chadima 69dd72
+		client->name = new_name;
Jan F. Chadima 69dd72
+		client->creds = ctx->client_creds;
Jan F. Chadima 69dd72
+        	ctx->client_creds = GSS_C_NO_CREDENTIAL;
Jan F. Chadima 69dd72
+		client->updated = 1;
Jan F. Chadima 69dd72
+		return GSS_S_COMPLETE;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	client->mech = NULL;
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
@@ -292,6 +358,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g
Jan F. Chadima 69dd72
 	if (client->mech == NULL)
Jan F. Chadima 69dd72
 		return GSS_S_FAILURE;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	if (ctx->client_creds &&
Jan F. Chadima 69dd72
+	    (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
Jan F. Chadima 69dd72
+	     ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
Jan F. Chadima 69dd72
+		ssh_gssapi_error(ctx);
Jan F. Chadima 69dd72
+		return (ctx->major);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
Jan F. Chadima 69dd72
 	    &client->displayname, NULL))) {
Jan F. Chadima 69dd72
 		ssh_gssapi_error(ctx);
Jakub Jelen bbf61d
@@ -309,6 +382,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g
Jan F. Chadima 69dd72
 		return (ctx->major);
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	gss_release_buffer(&ctx->minor, &ename);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	/* We can't copy this structure, so we just move the pointer to it */
Jan F. Chadima 69dd72
 	client->creds = ctx->client_creds;
Jan F. Chadima 69dd72
 	ctx->client_creds = GSS_C_NO_CREDENTIAL;
Jakub Jelen bbf61d
@@ -319,11 +394,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g
Petr Lautrbach 51ca3b
 void
Petr Lautrbach 51ca3b
 ssh_gssapi_cleanup_creds(void)
Petr Lautrbach 51ca3b
 {
Petr Lautrbach 99076b
-	if (gssapi_client.store.filename != NULL) {
Petr Lautrbach 99076b
-		/* Unlink probably isn't sufficient */
Petr Lautrbach 99076b
-		debug("removing gssapi cred file\"%s\"",
Petr Lautrbach 99076b
-		    gssapi_client.store.filename);
Petr Lautrbach 99076b
-		unlink(gssapi_client.store.filename);
Petr Lautrbach 99076b
+	krb5_ccache ccache = NULL;
Petr Lautrbach 99076b
+	krb5_error_code problem;
Petr Lautrbach 99076b
+
Petr Lautrbach 99076b
+	if (gssapi_client.store.data != NULL) {
Petr Lautrbach 99076b
+		if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) {
Petr Lautrbach 99076b
+			debug("%s: krb5_cc_resolve(): %.100s", __func__,
Petr Lautrbach 99076b
+				krb5_get_err_text(gssapi_client.store.data, problem));
Petr Lautrbach 99076b
+		} else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) {
Petr Lautrbach 99076b
+			debug("%s: krb5_cc_resolve(): %.100s", __func__,
Petr Lautrbach 99076b
+				krb5_get_err_text(gssapi_client.store.data, problem));
Petr Lautrbach 99076b
+		} else {
Petr Lautrbach 99076b
+			krb5_free_context(gssapi_client.store.data);
Petr Lautrbach 99076b
+			gssapi_client.store.data = NULL;
Petr Lautrbach 51ca3b
+		}
Petr Lautrbach 51ca3b
 	}
Petr Lautrbach 51ca3b
 }
Petr Lautrbach 51ca3b
 
Jakub Jelen bbf61d
@@ -356,7 +440,7 @@ ssh_gssapi_do_child(char ***envp, u_int
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 /* Privileged */
Jan F. Chadima 69dd72
 int
Jan F. Chadima 69dd72
-ssh_gssapi_userok(char *user)
Jan F. Chadima 69dd72
+ssh_gssapi_userok(char *user, struct passwd *pw)
Jan F. Chadima 69dd72
 {
Jan F. Chadima 69dd72
 	OM_uint32 lmin;
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
@@ -366,9 +450,11 @@ ssh_gssapi_userok(char *user)
Jan F. Chadima 69dd72
 		return 0;
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
 	if (gssapi_client.mech && gssapi_client.mech->userok)
Jan F. Chadima 69dd72
-		if ((*gssapi_client.mech->userok)(&gssapi_client, user))
Jan F. Chadima 69dd72
+		if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
Jan F. Chadima 69dd72
+			gssapi_client.used = 1;
Jan F. Chadima 69dd72
+			gssapi_client.store.owner = pw;
Jan F. Chadima 69dd72
 			return 1;
Jan F. Chadima 69dd72
-		else {
Jan F. Chadima 69dd72
+		} else {
Jan F. Chadima 69dd72
 			/* Destroy delegated credentials if userok fails */
Jan F. Chadima 69dd72
 			gss_release_buffer(&lmin, &gssapi_client.displayname);
Jan F. Chadima 69dd72
 			gss_release_buffer(&lmin, &gssapi_client.exportedname);
Jakub Jelen bbf61d
@@ -382,14 +468,89 @@ ssh_gssapi_userok(char *user)
Jan F. Chadima 69dd72
 	return (0);
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
-/* Privileged */
Jan F. Chadima 69dd72
-OM_uint32
Jan F. Chadima 69dd72
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
Jan F. Chadima 69dd72
+/* These bits are only used for rekeying. The unpriviledged child is running 
Jan F. Chadima 69dd72
+ * as the user, the monitor is root.
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * In the child, we want to :
Jan F. Chadima 69dd72
+ *    *) Ask the monitor to store our credentials into the store we specify
Jan F. Chadima 69dd72
+ *    *) If it succeeds, maybe do a PAM update
Jan F. Chadima 69dd72
+ */
Jan F. Chadima 69dd72
+
Petr Lautrbach d9e618
+/* Stuff for PAM */
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+#ifdef USE_PAM
Petr Lautrbach d9e618
+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
Petr Lautrbach d9e618
+    struct pam_response **resp, void *data)
Petr Lautrbach d9e618
 {
Petr Lautrbach d9e618
-	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
Petr Lautrbach d9e618
-	    gssbuf, gssmic, NULL);
Petr Lautrbach d9e618
+	return (PAM_CONV_ERR);
Petr Lautrbach d9e618
+}
Petr Lautrbach d9e618
+#endif
Petr Lautrbach d9e618
 
Petr Lautrbach d9e618
-	return (ctx->major);
Petr Lautrbach d9e618
+void
Petr Lautrbach d9e618
+ssh_gssapi_rekey_creds() {
Petr Lautrbach d9e618
+	int ok;
Petr Lautrbach d9e618
+	int ret;
Petr Lautrbach d9e618
+#ifdef USE_PAM
Petr Lautrbach d9e618
+	pam_handle_t *pamh = NULL;
Petr Lautrbach d9e618
+	struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
Petr Lautrbach d9e618
+	char *envstr;
Petr Lautrbach d9e618
+#endif
Petr Lautrbach d9e618
+
Jakub Jelen 117678
+	if (gssapi_client.store.envval == NULL &&
Petr Lautrbach d9e618
+	    gssapi_client.store.envvar == NULL)
Petr Lautrbach d9e618
+		return;
Petr Lautrbach d9e618
+ 
Petr Lautrbach d9e618
+	ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	if (!ok)
Petr Lautrbach d9e618
+		return;
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	debug("Rekeyed credentials stored successfully");
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	/* Actually managing to play with the ssh pam stack from here will
Petr Lautrbach d9e618
+	 * be next to impossible. In any case, we may want different options
Petr Lautrbach d9e618
+	 * for rekeying. So, use our own :)
Petr Lautrbach d9e618
+	 */
Petr Lautrbach d9e618
+#ifdef USE_PAM	
Petr Lautrbach d9e618
+	if (!use_privsep) {
Petr Lautrbach d9e618
+		debug("Not even going to try and do PAM with privsep disabled");
Petr Lautrbach d9e618
+		return;
Petr Lautrbach d9e618
+	}
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
Petr Lautrbach d9e618
+ 	    &pamconv, &pamh);
Petr Lautrbach d9e618
+	if (ret)
Petr Lautrbach d9e618
+		return;
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
Petr Lautrbach d9e618
+	    gssapi_client.store.envval);
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	ret = pam_putenv(pamh, envstr);
Petr Lautrbach d9e618
+	if (!ret)
Petr Lautrbach d9e618
+		pam_setcred(pamh, PAM_REINITIALIZE_CRED);
Petr Lautrbach d9e618
+	pam_end(pamh, PAM_SUCCESS);
Petr Lautrbach d9e618
+#endif
Petr Lautrbach d9e618
+}
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+int 
Petr Lautrbach d9e618
+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
Petr Lautrbach d9e618
+	int ok = 0;
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	/* Check we've got credentials to store */
Petr Lautrbach d9e618
+	if (!gssapi_client.updated)
Petr Lautrbach d9e618
+		return 0;
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	gssapi_client.updated = 0;
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	temporarily_use_uid(gssapi_client.store.owner);
Petr Lautrbach d9e618
+	if (gssapi_client.mech && gssapi_client.mech->updatecreds)
Petr Lautrbach d9e618
+		ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
Petr Lautrbach d9e618
+	else
Petr Lautrbach d9e618
+		debug("No update function for this mechanism");
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	restore_uid();
Petr Lautrbach d9e618
+
Petr Lautrbach d9e618
+	return ok;
Petr Lautrbach d9e618
 }
Petr Lautrbach d9e618
 
Jakub Jelen 5b55d0
 /* Privileged */
Jakub Jelen 5b55d0
diff -up openssh/gss-serv-krb5.c.gsskex openssh/gss-serv-krb5.c
Jakub Jelen bbf61d
--- openssh/gss-serv-krb5.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/gss-serv-krb5.c	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen bbf61d
@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
Jakub Jelen 535d34
 	krb5_error_code problem;
Jakub Jelen 535d34
 	krb5_principal princ;
Jakub Jelen 535d34
 	OM_uint32 maj_status, min_status;
Jakub Jelen 535d34
-	int len;
Jakub Jelen 535d34
+	const char *new_ccname, *new_cctype;
Jakub Jelen 535d34
 	const char *errmsg;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 	if (client->creds == NULL) {
Jakub Jelen bbf61d
@@ -180,11 +180,23 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
Jakub Jelen 535d34
 		return;
Jakub Jelen 535d34
 	}
Jakub Jelen 535d34
 
Jakub Jelen 535d34
-	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
Jakub Jelen 535d34
+	new_cctype = krb5_cc_get_type(krb_context, ccache);
Jakub Jelen 535d34
+	new_ccname = krb5_cc_get_name(krb_context, ccache);
Jakub Jelen 535d34
+
Jakub Jelen 535d34
 	client->store.envvar = "KRB5CCNAME";
Jakub Jelen 535d34
-	len = strlen(client->store.filename) + 6;
Jakub Jelen 535d34
-	client->store.envval = xmalloc(len);
Jakub Jelen 535d34
-	snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
Jakub Jelen 535d34
+#ifdef USE_CCAPI
Jakub Jelen 535d34
+	xasprintf(&client->store.envval, "API:%s", new_ccname);
Jakub Jelen 535d34
+#else
Jakub Jelen 535d34
+	if (new_ccname[0] == ':')
Jakub Jelen 535d34
+		new_ccname++;
Jakub Jelen 535d34
+	xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
Jakub Jelen 535d34
+	if (strcmp(new_cctype, "DIR") == 0) {
Jakub Jelen 535d34
+		char *p;
Jakub Jelen 535d34
+		p = strrchr(client->store.envval, '/');
Jakub Jelen 535d34
+		if (p)
Jakub Jelen 535d34
+			*p = '\0';
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+#endif
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 #ifdef USE_PAM
Jakub Jelen 535d34
 	if (options.use_pam)
Jakub Jelen bbf61d
@@ -193,9 +205,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 	krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
 
Jakub Jelen 535d34
+	client->store.data = krb_context;
Jakub Jelen 535d34
+
Jakub Jelen 535d34
 	return;
Jakub Jelen 535d34
 }
Jakub Jelen 535d34
 
Jakub Jelen 535d34
+int
Jakub Jelen 535d34
+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
Jakub Jelen 535d34
+    ssh_gssapi_client *client)
Jakub Jelen 535d34
+{
Jakub Jelen 535d34
+	krb5_ccache ccache = NULL;
Jakub Jelen 535d34
+	krb5_principal principal = NULL;
Jakub Jelen 535d34
+	char *name = NULL;
Jakub Jelen 535d34
+	krb5_error_code problem;
Jakub Jelen 535d34
+	OM_uint32 maj_status, min_status;
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+   	if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
Jakub Jelen 535d34
+                logit("krb5_cc_resolve(): %.100s",
Jakub Jelen 535d34
+                    krb5_get_err_text(krb_context, problem));
Jakub Jelen 535d34
+                return 0;
Jakub Jelen 535d34
+       	}
Jakub Jelen 535d34
+	
Jakub Jelen 535d34
+	/* Find out who the principal in this cache is */
Jakub Jelen 535d34
+	if ((problem = krb5_cc_get_principal(krb_context, ccache, 
Jakub Jelen 535d34
+	    &principal))) {
Jakub Jelen 535d34
+		logit("krb5_cc_get_principal(): %.100s",
Jakub Jelen 535d34
+		    krb5_get_err_text(krb_context, problem));
Jakub Jelen 535d34
+		krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
+		return 0;
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
Jakub Jelen 535d34
+		logit("krb5_unparse_name(): %.100s",
Jakub Jelen 535d34
+		    krb5_get_err_text(krb_context, problem));
Jakub Jelen 535d34
+		krb5_free_principal(krb_context, principal);
Jakub Jelen 535d34
+		krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
+		return 0;
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	if (strcmp(name,client->exportedname.value)!=0) {
Jakub Jelen 535d34
+		debug("Name in local credentials cache differs. Not storing");
Jakub Jelen 535d34
+		krb5_free_principal(krb_context, principal);
Jakub Jelen 535d34
+		krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
+		krb5_free_unparsed_name(krb_context, name);
Jakub Jelen 535d34
+		return 0;
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+	krb5_free_unparsed_name(krb_context, name);
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	/* Name matches, so lets get on with it! */
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
Jakub Jelen 535d34
+		logit("krb5_cc_initialize(): %.100s",
Jakub Jelen 535d34
+		    krb5_get_err_text(krb_context, problem));
Jakub Jelen 535d34
+		krb5_free_principal(krb_context, principal);
Jakub Jelen 535d34
+		krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
+		return 0;
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	krb5_free_principal(krb_context, principal);
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
Jakub Jelen 535d34
+	    ccache))) {
Jakub Jelen 535d34
+		logit("gss_krb5_copy_ccache() failed. Sorry!");
Jakub Jelen 535d34
+		krb5_cc_close(krb_context, ccache);
Jakub Jelen 535d34
+		return 0;
Jakub Jelen 535d34
+	}
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+	return 1;
Jakub Jelen 535d34
+}
Jakub Jelen 535d34
+
Jakub Jelen 535d34
 ssh_gssapi_mech gssapi_kerberos_mech = {
Jakub Jelen 535d34
 	"toWM5Slw5Ew8Mqkay+al2g==",
Jakub Jelen 535d34
 	"Kerberos",
Jakub Jelen bbf61d
@@ -203,7 +282,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
Jakub Jelen 535d34
 	NULL,
Jakub Jelen 535d34
 	&ssh_gssapi_krb5_userok,
Jakub Jelen 535d34
 	NULL,
Jakub Jelen 535d34
-	&ssh_gssapi_krb5_storecreds
Jakub Jelen 535d34
+	&ssh_gssapi_krb5_storecreds,
Jakub Jelen 535d34
+	&ssh_gssapi_krb5_updatecreds
Jakub Jelen 535d34
 };
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 #endif /* KRB5 */
Jakub Jelen 5b55d0
diff -up openssh/kex.c.gsskex openssh/kex.c
Jakub Jelen bbf61d
--- openssh/kex.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/kex.c	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen 13073f
@@ -54,6 +54,10 @@
Jakub Jelen 132f8f
 #include "sshbuf.h"
Petr Lautrbach 3e1dd6
 #include "digest.h"
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+#include "ssh-gss.h"
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jakub Jelen 5b55d0
 /* prototype */
Jakub Jelen 5b55d0
 static int kex_choose_conf(struct ssh *);
Jakub Jelen 5b55d0
 static int kex_input_newkeys(int, u_int32_t, struct ssh *);
Jakub Jelen 5b55d0
@@ -103,6 +107,11 @@ static const struct kexalg kexalgs[] = {
Petr Lautrbach 3e1dd6
 	{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
Jakub Jelen 6cf9b8
 	{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
Jakub Jelen 132f8f
 #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
Petr Lautrbach 383448
+#ifdef GSSAPI
Petr Lautrbach 3e1dd6
+	{ KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
Petr Lautrbach 3e1dd6
+	{ KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
Petr Lautrbach 3e1dd6
+	{ KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
Petr Lautrbach 383448
+#endif
Petr Lautrbach 3e1dd6
 	{ NULL, -1, -1, -1},
Petr Lautrbach 84822b
 };
Petr Lautrbach 84822b
 
Jakub Jelen 5b55d0
@@ -136,6 +145,12 @@ kex_alg_by_name(const char *name)
Petr Lautrbach 383448
 	for (k = kexalgs; k->name != NULL; k++) {
Petr Lautrbach 383448
 		if (strcmp(k->name, name) == 0)
Petr Lautrbach 383448
 			return k;
Petr Lautrbach 383448
+#ifdef GSSAPI
Petr Lautrbach 383448
+		if (strncmp(name, "gss-", 4) == 0) {
Petr Lautrbach 383448
+			if (strncmp(k->name, name, strlen(k->name)) == 0)
Petr Lautrbach 383448
+				return k;
Petr Lautrbach 383448
+		}
Petr Lautrbach 383448
+#endif
Petr Lautrbach 383448
 	}
Petr Lautrbach 383448
 	return NULL;
Petr Lautrbach 383448
 }
Jakub Jelen 5b55d0
diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c
Jakub Jelen bbf61d
--- openssh/kexgssc.c.gsskex	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen bbf61d
+++ openssh/kexgssc.c	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen eaa7af
@@ -0,0 +1,341 @@
Jan F. Chadima 69dd72
+/*
Jan F. Chadima 69dd72
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * Redistribution and use in source and binary forms, with or without
Jan F. Chadima 69dd72
+ * modification, are permitted provided that the following conditions
Jan F. Chadima 69dd72
+ * are met:
Jan F. Chadima 69dd72
+ * 1. Redistributions of source code must retain the above copyright
Jan F. Chadima 69dd72
+ *    notice, this list of conditions and the following disclaimer.
Jan F. Chadima 69dd72
+ * 2. Redistributions in binary form must reproduce the above copyright
Jan F. Chadima 69dd72
+ *    notice, this list of conditions and the following disclaimer in the
Jan F. Chadima 69dd72
+ *    documentation and/or other materials provided with the distribution.
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
Jan F. Chadima 69dd72
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Jan F. Chadima 69dd72
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Jan F. Chadima 69dd72
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Jan F. Chadima 69dd72
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Jan F. Chadima 69dd72
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Jan F. Chadima 69dd72
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Jan F. Chadima 69dd72
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Jan F. Chadima 69dd72
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Jan F. Chadima 69dd72
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Jan F. Chadima 69dd72
+ */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "includes.h"
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "includes.h"
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include <openssl/crypto.h>
Jan F. Chadima 69dd72
+#include <openssl/bn.h>
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include <string.h>
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "xmalloc.h"
Jakub Jelen bbf61d
+#include "sshbuf.h"
Jan F. Chadima 69dd72
+#include "ssh2.h"
Jakub Jelen bbf61d
+#include "sshkey.h"
Jan F. Chadima 69dd72
+#include "cipher.h"
Jan F. Chadima 69dd72
+#include "kex.h"
Jan F. Chadima 69dd72
+#include "log.h"
Jan F. Chadima 69dd72
+#include "packet.h"
Jan F. Chadima 69dd72
+#include "dh.h"
Jakub Jelen 132f8f
+#include "digest.h"
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "ssh-gss.h"
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+int
Jakub Jelen 132f8f
+kexgss_client(struct ssh *ssh) {
Jan F. Chadima 69dd72
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
+	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
Jan F. Chadima 69dd72
+	Gssctxt *ctxt;
Jan F. Chadima 69dd72
+	OM_uint32 maj_status, min_status, ret_flags;
Jakub Jelen 132f8f
+	u_int klen, kout, slen = 0, strlen;
Jan F. Chadima 69dd72
+	DH *dh; 
Jan F. Chadima 69dd72
+	BIGNUM *dh_server_pub = NULL;
Jan F. Chadima 69dd72
+	BIGNUM *shared_secret = NULL;
Jan F. Chadima 69dd72
+	BIGNUM *p = NULL;
Jan F. Chadima 69dd72
+	BIGNUM *g = NULL;	
Jakub Jelen eaa7af
+	const BIGNUM *pub_key, *p1, *g1;
Jakub Jelen 132f8f
+	u_char *kbuf;
Jan F. Chadima 69dd72
+	u_char *serverhostkey = NULL;
Jan F. Chadima 69dd72
+	u_char *empty = "";
Jan F. Chadima 69dd72
+	char *msg;
Jan F. Chadima 69dd72
+	char *lang;
Jan F. Chadima 69dd72
+	int type = 0;
Jan F. Chadima 69dd72
+	int first = 1;
Jan F. Chadima 69dd72
+	int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
Jakub Jelen 132f8f
+	u_char hash[SSH_DIGEST_MAX_LENGTH];
Jakub Jelen 132f8f
+	size_t hashlen;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Initialise our GSSAPI world */	
Jan F. Chadima 69dd72
+	ssh_gssapi_build_ctx(&ctxt);
Jakub Jelen 132f8f
+	if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) 
Jan F. Chadima 69dd72
+	    == GSS_C_NO_OID)
Jan F. Chadima 69dd72
+		fatal("Couldn't identify host exchange");
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host))
Jan F. Chadima 69dd72
+		fatal("Couldn't import hostname");
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	if (ssh->kex->gss_client && 
Jakub Jelen 132f8f
+	    ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client))
Jan F. Chadima 69dd72
+		fatal("Couldn't acquire client credentials");
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	switch (ssh->kex->kex_type) {
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP1_SHA1:
Jan F. Chadima 69dd72
+		dh = dh_new_group1();
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP14_SHA1:
Jan F. Chadima 69dd72
+		dh = dh_new_group14();
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GEX_SHA1:
Jan F. Chadima 69dd72
+		debug("Doing group exchange\n");
Jakub Jelen 132f8f
+		nbits = dh_estimate(ssh->kex->we_need * 8);
Jan F. Chadima 69dd72
+		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
Jan F. Chadima 69dd72
+		packet_put_int(min);
Jan F. Chadima 69dd72
+		packet_put_int(nbits);
Jan F. Chadima 69dd72
+		packet_put_int(max);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		packet_send();
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if ((p = BN_new()) == NULL)
Jan F. Chadima 69dd72
+			fatal("BN_new() failed");
Jan F. Chadima 69dd72
+		packet_get_bignum2(p);
Jan F. Chadima 69dd72
+		if ((g = BN_new()) == NULL)
Jan F. Chadima 69dd72
+			fatal("BN_new() failed");
Jan F. Chadima 69dd72
+		packet_get_bignum2(g);
Jan F. Chadima 69dd72
+		packet_check_eom();
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if (BN_num_bits(p) < min || BN_num_bits(p) > max)
Jan F. Chadima 69dd72
+			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
Jan F. Chadima 69dd72
+			    min, BN_num_bits(p), max);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		dh = dh_new_group(g, p);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	default:
Jakub Jelen 132f8f
+		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+	
Jakub Jelen eaa7af
+	/* Step 1 - e is pub_key */
Jakub Jelen 132f8f
+	dh_gen_key(dh, ssh->kex->we_need * 8);
Jakub Jelen eaa7af
+	DH_get0_key(dh, &pub_key, NULL);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* This is f, we initialise it now to make life easier */
Jan F. Chadima 69dd72
+	dh_server_pub = BN_new();
Jan F. Chadima 69dd72
+	if (dh_server_pub == NULL)
Jan F. Chadima 69dd72
+		fatal("dh_server_pub == NULL");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	token_ptr = GSS_C_NO_BUFFER;
Jan F. Chadima 69dd72
+			 
Jan F. Chadima 69dd72
+	do {
Jan F. Chadima 69dd72
+		debug("Calling gss_init_sec_context");
Jan F. Chadima 69dd72
+		
Jan F. Chadima 69dd72
+		maj_status = ssh_gssapi_init_ctx(ctxt,
Jakub Jelen 132f8f
+		    ssh->kex->gss_deleg_creds, token_ptr, &send_tok,
Jan F. Chadima 69dd72
+		    &ret_flags);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if (GSS_ERROR(maj_status)) {
Jan F. Chadima 69dd72
+			if (send_tok.length != 0) {
Jan F. Chadima 69dd72
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
Jan F. Chadima 69dd72
+				packet_put_string(send_tok.value,
Jan F. Chadima 69dd72
+				    send_tok.length);
Jan F. Chadima 69dd72
+			}
Jan F. Chadima 69dd72
+			fatal("gss_init_context failed");
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		/* If we've got an old receive buffer get rid of it */
Jan F. Chadima 69dd72
+		if (token_ptr != GSS_C_NO_BUFFER)
Petr Lautrbach 84822b
+			free(recv_tok.value);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if (maj_status == GSS_S_COMPLETE) {
Jan F. Chadima 69dd72
+			/* If mutual state flag is not true, kex fails */
Jan F. Chadima 69dd72
+			if (!(ret_flags & GSS_C_MUTUAL_FLAG))
Jan F. Chadima 69dd72
+				fatal("Mutual authentication failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			/* If integ avail flag is not true kex fails */
Jan F. Chadima 69dd72
+			if (!(ret_flags & GSS_C_INTEG_FLAG))
Jan F. Chadima 69dd72
+				fatal("Integrity check failed");
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		/* 
Jan F. Chadima 69dd72
+		 * If we have data to send, then the last message that we
Jan F. Chadima 69dd72
+		 * received cannot have been a 'complete'. 
Jan F. Chadima 69dd72
+		 */
Jan F. Chadima 69dd72
+		if (send_tok.length != 0) {
Jan F. Chadima 69dd72
+			if (first) {
Jan F. Chadima 69dd72
+				packet_start(SSH2_MSG_KEXGSS_INIT);
Jan F. Chadima 69dd72
+				packet_put_string(send_tok.value,
Jan F. Chadima 69dd72
+				    send_tok.length);
Jakub Jelen eaa7af
+				packet_put_bignum2((BIGNUM *)pub_key);
Jan F. Chadima 69dd72
+				first = 0;
Jan F. Chadima 69dd72
+			} else {
Jan F. Chadima 69dd72
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
Jan F. Chadima 69dd72
+				packet_put_string(send_tok.value,
Jan F. Chadima 69dd72
+				    send_tok.length);
Jan F. Chadima 69dd72
+			}
Jan F. Chadima 69dd72
+			packet_send();
Jan F. Chadima 69dd72
+			gss_release_buffer(&min_status, &send_tok);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			/* If we've sent them data, they should reply */
Jan F. Chadima 69dd72
+			do {	
Jan F. Chadima 69dd72
+				type = packet_read();
Jan F. Chadima 69dd72
+				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
Jan F. Chadima 69dd72
+					debug("Received KEXGSS_HOSTKEY");
Jan F. Chadima 69dd72
+					if (serverhostkey)
Jan F. Chadima 69dd72
+						fatal("Server host key received more than once");
Jan F. Chadima 69dd72
+					serverhostkey = 
Jan F. Chadima 69dd72
+					    packet_get_string(&slen);
Jan F. Chadima 69dd72
+				}
Jan F. Chadima 69dd72
+			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			switch (type) {
Jan F. Chadima 69dd72
+			case SSH2_MSG_KEXGSS_CONTINUE:
Jan F. Chadima 69dd72
+				debug("Received GSSAPI_CONTINUE");
Jan F. Chadima 69dd72
+				if (maj_status == GSS_S_COMPLETE) 
Jan F. Chadima 69dd72
+					fatal("GSSAPI Continue received from server when complete");
Jan F. Chadima 69dd72
+				recv_tok.value = packet_get_string(&strlen);
Jan F. Chadima 69dd72
+				recv_tok.length = strlen; 
Jan F. Chadima 69dd72
+				break;
Jan F. Chadima 69dd72
+			case SSH2_MSG_KEXGSS_COMPLETE:
Jan F. Chadima 69dd72
+				debug("Received GSSAPI_COMPLETE");
Jan F. Chadima 69dd72
+				packet_get_bignum2(dh_server_pub);
Jan F. Chadima 69dd72
+				msg_tok.value =  packet_get_string(&strlen);
Jan F. Chadima 69dd72
+				msg_tok.length = strlen; 
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+				/* Is there a token included? */
Jan F. Chadima 69dd72
+				if (packet_get_char()) {
Jan F. Chadima 69dd72
+					recv_tok.value=
Jan F. Chadima 69dd72
+					    packet_get_string(&strlen);
Jan F. Chadima 69dd72
+					recv_tok.length = strlen;
Jan F. Chadima 69dd72
+					/* If we're already complete - protocol error */
Jan F. Chadima 69dd72
+					if (maj_status == GSS_S_COMPLETE)
Jan F. Chadima 69dd72
+						packet_disconnect("Protocol error: received token when complete");
Jan F. Chadima 69dd72
+					} else {
Jan F. Chadima 69dd72
+						/* No token included */
Jan F. Chadima 69dd72
+						if (maj_status != GSS_S_COMPLETE)
Jan F. Chadima 69dd72
+							packet_disconnect("Protocol error: did not receive final token");
Jan F. Chadima 69dd72
+				}
Jan F. Chadima 69dd72
+				break;
Jan F. Chadima 69dd72
+			case SSH2_MSG_KEXGSS_ERROR:
Jan F. Chadima 69dd72
+				debug("Received Error");
Jan F. Chadima 69dd72
+				maj_status = packet_get_int();
Jan F. Chadima 69dd72
+				min_status = packet_get_int();
Jan F. Chadima 69dd72
+				msg = packet_get_string(NULL);
Jan F. Chadima 69dd72
+				lang = packet_get_string(NULL);
Jan F. Chadima 69dd72
+				fatal("GSSAPI Error: \n%.400s",msg);
Jan F. Chadima 69dd72
+			default:
Jan F. Chadima 69dd72
+				packet_disconnect("Protocol error: didn't expect packet type %d",
Jan F. Chadima 69dd72
+		    		type);
Jan F. Chadima 69dd72
+			}
Jan F. Chadima 69dd72
+			token_ptr = &recv_tok;
Jan F. Chadima 69dd72
+		} else {
Jan F. Chadima 69dd72
+			/* No data, and not complete */
Jan F. Chadima 69dd72
+			if (maj_status != GSS_S_COMPLETE)
Jan F. Chadima 69dd72
+				fatal("Not complete, and no token output");
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+	} while (maj_status & GSS_S_CONTINUE_NEEDED);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* 
Jan F. Chadima 69dd72
+	 * We _must_ have received a COMPLETE message in reply from the 
Jan F. Chadima 69dd72
+	 * server, which will have set dh_server_pub and msg_tok 
Jan F. Chadima 69dd72
+	 */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (type != SSH2_MSG_KEXGSS_COMPLETE)
Jan F. Chadima 69dd72
+		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Check f in range [1, p-1] */
Jan F. Chadima 69dd72
+	if (!dh_pub_is_valid(dh, dh_server_pub))
Jan F. Chadima 69dd72
+		packet_disconnect("bad server public DH value");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* compute K=f^x mod p */
Jan F. Chadima 69dd72
+	klen = DH_size(dh);
Jan F. Chadima 69dd72
+	kbuf = xmalloc(klen);
Jan F. Chadima 69dd72
+	kout = DH_compute_key(kbuf, dh_server_pub, dh);
Jan F. Chadima 3b545b
+	if ((int)kout < 0)
Jan F. Chadima 69dd72
+		fatal("DH_compute_key: failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	shared_secret = BN_new();
Jan F. Chadima 69dd72
+	if (shared_secret == NULL)
Jan F. Chadima 69dd72
+		fatal("kexgss_client: BN_new failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
Jan F. Chadima 69dd72
+		fatal("kexdh_client: BN_bin2bn failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	memset(kbuf, 0, klen);
Petr Lautrbach 84822b
+	free(kbuf);
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	hashlen = sizeof(hash);
Jakub Jelen 132f8f
+	switch (ssh->kex->kex_type) {
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP1_SHA1:
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP14_SHA1:
Jakub Jelen b487a6
+		kex_dh_hash(ssh->kex->hash_alg, ssh->kex->client_version_string, 
Jakub Jelen 132f8f
+		    ssh->kex->server_version_string,
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),
Jan F. Chadima 69dd72
+		    (serverhostkey ? serverhostkey : empty), slen,
Jakub Jelen eaa7af
+		    pub_key,		/* e */
Jan F. Chadima 69dd72
+		    dh_server_pub,	/* f */
Jan F. Chadima 69dd72
+		    shared_secret,	/* K */
Jakub Jelen 132f8f
+		    hash, &hashlen
Jan F. Chadima 69dd72
+		);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GEX_SHA1:
Jakub Jelen eaa7af
+		DH_get0_pqg(dh, &p1, NULL, &g1;;
Jan F. Chadima 69dd72
+		kexgex_hash(
Jakub Jelen 132f8f
+		    ssh->kex->hash_alg,
Jakub Jelen 132f8f
+		    ssh->kex->client_version_string,
Jakub Jelen 132f8f
+		    ssh->kex->server_version_string,
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),
Jan F. Chadima 69dd72
+		    (serverhostkey ? serverhostkey : empty), slen,
Jan F. Chadima 69dd72
+ 		    min, nbits, max,
Jakub Jelen eaa7af
+		    p, g,
Jakub Jelen eaa7af
+		    pub_key,
Jan F. Chadima 69dd72
+		    dh_server_pub,
Jan F. Chadima 69dd72
+		    shared_secret,
Jakub Jelen 132f8f
+		    hash, &hashlen
Jan F. Chadima 69dd72
+		);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	default:
Jakub Jelen 132f8f
+		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gssbuf.value = hash;
Jan F. Chadima 69dd72
+	gssbuf.length = hashlen;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Verify that the hash matches the MIC we just got. */
Jan F. Chadima 69dd72
+	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
Jan F. Chadima 69dd72
+		packet_disconnect("Hash's MIC didn't verify");
Jan F. Chadima 69dd72
+
Petr Lautrbach 84822b
+	free(msg_tok.value);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	DH_free(dh);
Jan F. Chadima 69dd72
+	if (serverhostkey)
Petr Lautrbach 84822b
+		free(serverhostkey);
Jan F. Chadima 69dd72
+	BN_clear_free(dh_server_pub);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* save session id */
Jakub Jelen 132f8f
+	if (ssh->kex->session_id == NULL) {
Jakub Jelen 132f8f
+		ssh->kex->session_id_len = hashlen;
Jakub Jelen 132f8f
+		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);
Jakub Jelen 132f8f
+		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	if (ssh->kex->gss_deleg_creds)
Jan F. Chadima 69dd72
+		ssh_gssapi_credentials_updated(ctxt);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss_kex_context == NULL)
Jan F. Chadima 69dd72
+		gss_kex_context = ctxt;
Jan F. Chadima 69dd72
+	else
Jan F. Chadima 69dd72
+		ssh_gssapi_delete_ctx(&ctxt);
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);
Jan F. Chadima 69dd72
+	BN_clear_free(shared_secret);
Jakub Jelen 132f8f
+	return kex_send_newkeys(ssh);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#endif /* GSSAPI */
Jakub Jelen 5b55d0
diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c
Jakub Jelen bbf61d
--- openssh/kexgsss.c.gsskex	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen bbf61d
+++ openssh/kexgsss.c	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen eaa7af
@@ -0,0 +1,300 @@
Jan F. Chadima 69dd72
+/*
Jan F. Chadima 69dd72
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * Redistribution and use in source and binary forms, with or without
Jan F. Chadima 69dd72
+ * modification, are permitted provided that the following conditions
Jan F. Chadima 69dd72
+ * are met:
Jan F. Chadima 69dd72
+ * 1. Redistributions of source code must retain the above copyright
Jan F. Chadima 69dd72
+ *    notice, this list of conditions and the following disclaimer.
Jan F. Chadima 69dd72
+ * 2. Redistributions in binary form must reproduce the above copyright
Jan F. Chadima 69dd72
+ *    notice, this list of conditions and the following disclaimer in the
Jan F. Chadima 69dd72
+ *    documentation and/or other materials provided with the distribution.
Jan F. Chadima 69dd72
+ *
Jan F. Chadima 69dd72
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
Jan F. Chadima 69dd72
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Jan F. Chadima 69dd72
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Jan F. Chadima 69dd72
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Jan F. Chadima 69dd72
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Jan F. Chadima 69dd72
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Jan F. Chadima 69dd72
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Jan F. Chadima 69dd72
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Jan F. Chadima 69dd72
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Jan F. Chadima 69dd72
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Jan F. Chadima 69dd72
+ */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "includes.h"
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include <string.h>
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include <openssl/crypto.h>
Jan F. Chadima 69dd72
+#include <openssl/bn.h>
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+#include "xmalloc.h"
Jakub Jelen bbf61d
+#include "sshbuf.h"
Jan F. Chadima 69dd72
+#include "ssh2.h"
Jakub Jelen bbf61d
+#include "sshkey.h"
Jan F. Chadima 69dd72
+#include "cipher.h"
Jan F. Chadima 69dd72
+#include "kex.h"
Jan F. Chadima 69dd72
+#include "log.h"
Jan F. Chadima 69dd72
+#include "packet.h"
Jan F. Chadima 69dd72
+#include "dh.h"
Jan F. Chadima 69dd72
+#include "ssh-gss.h"
Jan F. Chadima 69dd72
+#include "monitor_wrap.h"
Petr Lautrbach 190035
+#include "misc.h"      /* servconf.h needs misc.h for struct ForwardOptions */
Jan F. Chadima 69dd72
+#include "servconf.h"
Jakub Jelen 580f98
+#include "ssh-gss.h"
Jakub Jelen 132f8f
+#include "digest.h"
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+extern ServerOptions options;
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+int
Jakub Jelen 132f8f
+kexgss_server(struct ssh *ssh)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	OM_uint32 maj_status, min_status;
Jan F. Chadima 69dd72
+	
Jan F. Chadima 69dd72
+	/* 
Jan F. Chadima 69dd72
+	 * Some GSSAPI implementations use the input value of ret_flags (an
Jan F. Chadima 69dd72
+ 	 * output variable) as a means of triggering mechanism specific 
Jan F. Chadima 69dd72
+ 	 * features. Initializing it to zero avoids inadvertently 
Jan F. Chadima 69dd72
+ 	 * activating this non-standard behaviour.
Jan F. Chadima 69dd72
+	 */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	OM_uint32 ret_flags = 0;
Jan F. Chadima 69dd72
+	gss_buffer_desc gssbuf, recv_tok, msg_tok;
Jan F. Chadima 69dd72
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
+	Gssctxt *ctxt = NULL;
Jakub Jelen 132f8f
+	u_int slen, klen, kout;
Jakub Jelen 132f8f
+	u_char *kbuf;
Jan F. Chadima 69dd72
+	DH *dh;
Jan F. Chadima 69dd72
+	int min = -1, max = -1, nbits = -1;
Jakub Jelen 5878eb
+	int cmin = -1, cmax = -1; /* client proposal */
Jan F. Chadima 69dd72
+	BIGNUM *shared_secret = NULL;
Jan F. Chadima 69dd72
+	BIGNUM *dh_client_pub = NULL;
Jan F. Chadima 69dd72
+	int type = 0;
Jan F. Chadima 69dd72
+	gss_OID oid;
Jan F. Chadima 69dd72
+	char *mechs;
Jakub Jelen 132f8f
+	u_char hash[SSH_DIGEST_MAX_LENGTH];
Jakub Jelen 132f8f
+	size_t hashlen;
Jakub Jelen eaa7af
+	const BIGNUM *p, *g, *pub_key;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Initialise GSSAPI */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* If we're rekeying, privsep means that some of the private structures
Jan F. Chadima 69dd72
+	 * in the GSSAPI code are no longer available. This kludges them back
Jan F. Chadima 69dd72
+	 * into life
Jan F. Chadima 69dd72
+	 */
Jan F. Chadima 69dd72
+	if (!ssh_gssapi_oid_table_ok()) 
Jan F. Chadima 69dd72
+		if ((mechs = ssh_gssapi_server_mechanisms()))
Petr Lautrbach 84822b
+			free(mechs);
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	debug2("%s: Identifying %s", __func__, ssh->kex->name);
Jakub Jelen 132f8f
+	oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type);
Jan F. Chadima 69dd72
+	if (oid == GSS_C_NO_OID)
Jan F. Chadima 69dd72
+	   fatal("Unknown gssapi mechanism");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	debug2("%s: Acquiring credentials", __func__);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
Jan F. Chadima 69dd72
+		fatal("Unable to acquire credentials for the server");
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	switch (ssh->kex->kex_type) {
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP1_SHA1:
Jan F. Chadima 69dd72
+		dh = dh_new_group1();
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP14_SHA1:
Jan F. Chadima 69dd72
+		dh = dh_new_group14();
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GEX_SHA1:
Jan F. Chadima 69dd72
+		debug("Doing group exchange");
Jan F. Chadima 69dd72
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
Jakub Jelen 5878eb
+		/* store client proposal to provide valid signature */
Jakub Jelen 5878eb
+		cmin = packet_get_int();
Jan F. Chadima 69dd72
+		nbits = packet_get_int();
Jakub Jelen 5878eb
+		cmax = packet_get_int();
Jakub Jelen 5878eb
+		min = MAX(DH_GRP_MIN, cmin);
Jakub Jelen 5878eb
+		max = MIN(DH_GRP_MAX, cmax);
Jan F. Chadima 69dd72
+		packet_check_eom();
Jan F. Chadima 69dd72
+		if (max < min || nbits < min || max < nbits)
Jan F. Chadima 69dd72
+			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
Jan F. Chadima 69dd72
+			    min, nbits, max);
Jan F. Chadima 69dd72
+		dh = PRIVSEP(choose_dh(min, nbits, max));
Jan F. Chadima 69dd72
+		if (dh == NULL)
Jan F. Chadima 69dd72
+			packet_disconnect("Protocol error: no matching group found");
Jan F. Chadima 69dd72
+
Jakub Jelen eaa7af
+		DH_get0_pqg(dh, &p, NULL, &g);
Jan F. Chadima 69dd72
+		packet_start(SSH2_MSG_KEXGSS_GROUP);
Jakub Jelen eaa7af
+		packet_put_bignum2((BIGNUM *)p);
Jakub Jelen eaa7af
+		packet_put_bignum2((BIGNUM *)g);
Jan F. Chadima 69dd72
+		packet_send();
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		packet_write_wait();
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	default:
Jakub Jelen 132f8f
+		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	dh_gen_key(dh, ssh->kex->we_need * 8);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	do {
Jan F. Chadima 69dd72
+		debug("Wait SSH2_MSG_GSSAPI_INIT");
Jan F. Chadima 69dd72
+		type = packet_read();
Jan F. Chadima 69dd72
+		switch(type) {
Jan F. Chadima 69dd72
+		case SSH2_MSG_KEXGSS_INIT:
Jan F. Chadima 69dd72
+			if (dh_client_pub != NULL) 
Jan F. Chadima 69dd72
+				fatal("Received KEXGSS_INIT after initialising");
Jan F. Chadima 69dd72
+			recv_tok.value = packet_get_string(&slen);
Jan F. Chadima 69dd72
+			recv_tok.length = slen; 
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			if ((dh_client_pub = BN_new()) == NULL)
Jan F. Chadima 69dd72
+				fatal("dh_client_pub == NULL");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			packet_get_bignum2(dh_client_pub);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
Jan F. Chadima 69dd72
+			break;
Jan F. Chadima 69dd72
+		case SSH2_MSG_KEXGSS_CONTINUE:
Jan F. Chadima 69dd72
+			recv_tok.value = packet_get_string(&slen);
Jan F. Chadima 69dd72
+			recv_tok.length = slen; 
Jan F. Chadima 69dd72
+			break;
Jan F. Chadima 69dd72
+		default:
Jan F. Chadima 69dd72
+			packet_disconnect(
Jan F. Chadima 69dd72
+			    "Protocol error: didn't expect packet type %d",
Jan F. Chadima 69dd72
+			    type);
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
Jan F. Chadima 69dd72
+		    &send_tok, &ret_flags));
Jan F. Chadima 69dd72
+
Petr Lautrbach 84822b
+		free(recv_tok.value);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
Jan F. Chadima 69dd72
+			fatal("Zero length token output when incomplete");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		if (dh_client_pub == NULL)
Jan F. Chadima 69dd72
+			fatal("No client public key");
Jan F. Chadima 69dd72
+		
Jan F. Chadima 69dd72
+		if (maj_status & GSS_S_CONTINUE_NEEDED) {
Jan F. Chadima 69dd72
+			debug("Sending GSSAPI_CONTINUE");
Jan F. Chadima 69dd72
+			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
Jan F. Chadima 69dd72
+			packet_put_string(send_tok.value, send_tok.length);
Jan F. Chadima 69dd72
+			packet_send();
Jan F. Chadima 69dd72
+			gss_release_buffer(&min_status, &send_tok);
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+	} while (maj_status & GSS_S_CONTINUE_NEEDED);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(maj_status)) {
Jan F. Chadima 69dd72
+		if (send_tok.length > 0) {
Jan F. Chadima 69dd72
+			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
Jan F. Chadima 69dd72
+			packet_put_string(send_tok.value, send_tok.length);
Jan F. Chadima 69dd72
+			packet_send();
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+		fatal("accept_ctx died");
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
Jan F. Chadima 69dd72
+		fatal("Mutual Authentication flag wasn't set");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (!(ret_flags & GSS_C_INTEG_FLAG))
Jan F. Chadima 69dd72
+		fatal("Integrity flag wasn't set");
Jan F. Chadima 69dd72
+	
Jan F. Chadima 69dd72
+	if (!dh_pub_is_valid(dh, dh_client_pub))
Jan F. Chadima 69dd72
+		packet_disconnect("bad client public DH value");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	klen = DH_size(dh);
Jan F. Chadima 69dd72
+	kbuf = xmalloc(klen); 
Jan F. Chadima 69dd72
+	kout = DH_compute_key(kbuf, dh_client_pub, dh);
Jan F. Chadima 3b545b
+	if ((int)kout < 0)
Jan F. Chadima 69dd72
+		fatal("DH_compute_key: failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	shared_secret = BN_new();
Jan F. Chadima 69dd72
+	if (shared_secret == NULL)
Jan F. Chadima 69dd72
+		fatal("kexgss_server: BN_new failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
Jan F. Chadima 69dd72
+		fatal("kexgss_server: BN_bin2bn failed");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	memset(kbuf, 0, klen);
Petr Lautrbach 84822b
+	free(kbuf);
Jan F. Chadima 69dd72
+
Jakub Jelen eaa7af
+	DH_get0_key(dh, &pub_key, NULL);
Jakub Jelen 132f8f
+	hashlen = sizeof(hash);
Jakub Jelen 132f8f
+	switch (ssh->kex->kex_type) {
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP1_SHA1:
Jan F. Chadima 69dd72
+	case KEX_GSS_GRP14_SHA1:
Jakub Jelen b487a6
+		kex_dh_hash(ssh->kex->hash_alg,
Jakub Jelen 132f8f
+		    ssh->kex->client_version_string, ssh->kex->server_version_string,
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),
Jan F. Chadima 69dd72
+		    NULL, 0, /* Change this if we start sending host keys */
Jakub Jelen eaa7af
+		    dh_client_pub, pub_key, shared_secret,
Jakub Jelen 132f8f
+		    hash, &hashlen
Jan F. Chadima 69dd72
+		);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	case KEX_GSS_GEX_SHA1:
Jan F. Chadima 69dd72
+		kexgex_hash(
Jakub Jelen 132f8f
+		    ssh->kex->hash_alg,
Jakub Jelen 132f8f
+		    ssh->kex->client_version_string, ssh->kex->server_version_string,
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),
Jakub Jelen bbf61d
+		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),
Jan F. Chadima 69dd72
+		    NULL, 0,
Jakub Jelen 5878eb
+		    cmin, nbits, cmax,
Jakub Jelen eaa7af
+		    p, g,
Jan F. Chadima 69dd72
+		    dh_client_pub,
Jakub Jelen eaa7af
+		    pub_key,
Jan F. Chadima 69dd72
+		    shared_secret,
Jakub Jelen 132f8f
+		    hash, &hashlen
Jan F. Chadima 69dd72
+		);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+	default:
Jakub Jelen 132f8f
+		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	BN_clear_free(dh_client_pub);
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	if (ssh->kex->session_id == NULL) {
Jakub Jelen 132f8f
+		ssh->kex->session_id_len = hashlen;
Jakub Jelen 132f8f
+		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);
Jakub Jelen 132f8f
+		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gssbuf.value = hash;
Jan F. Chadima 69dd72
+	gssbuf.length = hashlen;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
Jan F. Chadima 69dd72
+		fatal("Couldn't get MIC");
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
Jakub Jelen eaa7af
+	packet_put_bignum2(pub_key);
Jan F. Chadima 69dd72
+	packet_put_string(msg_tok.value,msg_tok.length);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (send_tok.length != 0) {
Jan F. Chadima 69dd72
+		packet_put_char(1); /* true */
Jan F. Chadima 69dd72
+		packet_put_string(send_tok.value, send_tok.length);
Jan F. Chadima 69dd72
+	} else {
Jan F. Chadima 69dd72
+		packet_put_char(0); /* false */
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+	packet_send();
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gss_release_buffer(&min_status, &send_tok);
Jan F. Chadima 69dd72
+	gss_release_buffer(&min_status, &msg_tok);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss_kex_context == NULL)
Jan F. Chadima 69dd72
+		gss_kex_context = ctxt;
Jan F. Chadima 69dd72
+	else 
Jan F. Chadima 69dd72
+		ssh_gssapi_delete_ctx(&ctxt);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	DH_free(dh);
Jan F. Chadima 69dd72
+
Jakub Jelen 132f8f
+	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);
Jan F. Chadima 69dd72
+	BN_clear_free(shared_secret);
Jakub Jelen 132f8f
+	kex_send_newkeys(ssh);
Jan F. Chadima 69dd72
+
Petr Lautrbach d9e618
+	/* If this was a rekey, then save out any delegated credentials we
Petr Lautrbach d9e618
+	 * just exchanged.  */
Petr Lautrbach d9e618
+	if (options.gss_store_rekey)
Petr Lautrbach d9e618
+		ssh_gssapi_rekey_creds();
Jakub Jelen 132f8f
+	return 0;
Petr Lautrbach d9e618
+}
Petr Lautrbach d9e618
+#endif /* GSSAPI */
Jakub Jelen 5b55d0
diff -up openssh/kex.h.gsskex openssh/kex.h
Jakub Jelen bbf61d
--- openssh/kex.h.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/kex.h	2018-08-22 11:47:33.311216457 +0200
Jakub Jelen bbf61d
@@ -100,6 +100,11 @@ enum kex_exchange {
Jakub Jelen 535d34
 	KEX_DH_GEX_SHA256,
Jakub Jelen 535d34
 	KEX_ECDH_SHA2,
Jakub Jelen 535d34
 	KEX_C25519_SHA256,
Jakub Jelen 535d34
+#ifdef GSSAPI
Jakub Jelen 535d34
+	KEX_GSS_GRP1_SHA1,
Jakub Jelen 535d34
+	KEX_GSS_GRP14_SHA1,
Jakub Jelen 535d34
+	KEX_GSS_GEX_SHA1,
Jakub Jelen 535d34
+#endif
Jakub Jelen 535d34
 	KEX_MAX
Jakub Jelen 535d34
 };
Jakub Jelen 535d34
 
Jakub Jelen bbf61d
@@ -148,6 +153,12 @@ struct kex {
Jakub Jelen 535d34
 	u_int	flags;
Jakub Jelen 535d34
 	int	hash_alg;
Jakub Jelen 535d34
 	int	ec_nid;
Jakub Jelen 535d34
+#ifdef GSSAPI
Jakub Jelen 535d34
+	int	gss_deleg_creds;
Jakub Jelen 535d34
+	int	gss_trust_dns;
Jakub Jelen 535d34
+	char    *gss_host;
Jakub Jelen 535d34
+	char	*gss_client;
Jakub Jelen 535d34
+#endif
Jakub Jelen 535d34
 	char	*client_version_string;
Jakub Jelen 535d34
 	char	*server_version_string;
Jakub Jelen 3f5513
 	char	*failed_choice;
Jakub Jelen bbf61d
@@ -197,6 +208,10 @@ int	 kexecdh_client(struct ssh *);
Jakub Jelen 535d34
 int	 kexecdh_server(struct ssh *);
Jakub Jelen 535d34
 int	 kexc25519_client(struct ssh *);
Jakub Jelen 535d34
 int	 kexc25519_server(struct ssh *);
Jakub Jelen 535d34
+#ifdef GSSAPI
Jakub Jelen 535d34
+int	 kexgss_client(struct ssh *);
Jakub Jelen 535d34
+int	 kexgss_server(struct ssh *);
Jakub Jelen 535d34
+#endif
Jakub Jelen 535d34
 
Jakub Jelen 5878eb
 int	 kex_dh_hash(int, const char *, const char *,
Jakub Jelen 535d34
     const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
Jakub Jelen 5b55d0
diff -up openssh/Makefile.in.gsskex openssh/Makefile.in
Jakub Jelen bbf61d
--- openssh/Makefile.in.gsskex	2018-08-22 11:47:33.312216465 +0200
Jakub Jelen bbf61d
+++ openssh/Makefile.in	2018-08-22 13:19:54.955928277 +0200
Jakub Jelen bbf61d
@@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
Jakub Jelen 5b55d0
 	readpass.o ttymodes.o xmalloc.o addrmatch.o \
Jakub Jelen bbf61d
 	atomicio.o dispatch.o mac.o uuencode.o misc.o utf8.o \
Jakub Jelen 535d34
 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
Jakub Jelen 535d34
+	kexgssc.o \
Jakub Jelen 535d34
 	msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
Jakub Jelen 535d34
 	ssh-pkcs11.o smult_curve25519_ref.o \
Jakub Jelen 535d34
 	poly1305.o chacha.o cipher-chachapoly.o \
Jakub Jelen bbf61d
@@ -121,7 +122,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
Jakub Jelen bbf61d
 	auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
Jakub Jelen 535d34
 	auth2-none.o auth2-passwd.o auth2-pubkey.o \
Jakub Jelen 6cf9b8
 	monitor.o monitor_wrap.o auth-krb5.o \
Jakub Jelen 535d34
-	auth2-gss.o gss-serv.o gss-serv-krb5.o \
Jakub Jelen 6cf9b8
+	auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \
Jakub Jelen 535d34
 	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
Jakub Jelen 535d34
 	sftp-server.o sftp-common.o \
Jakub Jelen 13073f
 	sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
Jakub Jelen 5b55d0
diff -up openssh/monitor.c.gsskex openssh/monitor.c
Jakub Jelen bbf61d
--- openssh/monitor.c.gsskex	2018-08-22 11:47:33.263216069 +0200
Jakub Jelen bbf61d
+++ openssh/monitor.c	2018-08-22 13:22:19.589095240 +0200
Jakub Jelen bbf61d
@@ -146,6 +146,8 @@ int mm_answer_gss_setup_ctx(int, struct
Jakub Jelen bbf61d
 int mm_answer_gss_accept_ctx(int, struct sshbuf *);
Jakub Jelen bbf61d
 int mm_answer_gss_userok(int, struct sshbuf *);
Jakub Jelen bbf61d
 int mm_answer_gss_checkmic(int, struct sshbuf *);
Jakub Jelen bbf61d
+int mm_answer_gss_sign(int, struct sshbuf *);
Jakub Jelen bbf61d
+int mm_answer_gss_updatecreds(int, struct sshbuf *);
Jan F. Chadima 69dd72
 #endif
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #ifdef SSH_AUDIT_EVENTS
Jakub Jelen bbf61d
@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[]
Jakub Jelen 6cf9b8
     {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
Jakub Jelen 6cf9b8
     {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
Jakub Jelen 6cf9b8
     {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
Petr Lautrbach 57666d
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
Petr Lautrbach 57666d
 #endif
Petr Lautrbach 57666d
     {0, 0, NULL}
Jan F. Chadima 69dd72
 };
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 struct mon_table mon_dispatch_postauth20[] = {
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
Jan F. Chadima 69dd72
+    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
Jan F. Chadima 69dd72
+    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
Jan F. Chadima 69dd72
+    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
Jan F. Chadima 69dd72
+#endif
Petr Lautrbach 190035
 #ifdef WITH_OPENSSL
Jan F. Chadima 69dd72
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
Petr Lautrbach 190035
 #endif
Jakub Jelen bbf61d
@@ -293,6 +302,10 @@ monitor_child_preauth(Authctxt *_authctx
Jakub Jelen 6cf9b8
 	/* Permit requests for moduli and signatures */
Jakub Jelen 6cf9b8
 	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
Jakub Jelen 6cf9b8
 	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jakub Jelen 6cf9b8
+	/* and for the GSSAPI key exchange */
Jakub Jelen 6cf9b8
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
Jan F. Chadima 69dd72
+#endif
Petr Lautrbach 5039c7
 
Jakub Jelen 6cf9b8
 	/* The first few requests do not require asynchronous access */
Jakub Jelen 6cf9b8
 	while (!authenticated) {
Jakub Jelen bbf61d
@@ -405,6 +418,10 @@ monitor_child_postauth(struct monitor *p
Jakub Jelen 6cf9b8
 	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
Jakub Jelen 6cf9b8
 	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
Jakub Jelen 6cf9b8
 	monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jakub Jelen 6cf9b8
+	/* and for the GSSAPI key exchange */
Jakub Jelen 6cf9b8
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
Jan F. Chadima 69dd72
+#endif		
Jakub Jelen 6cf9b8
 
Jakub Jelen 3cd489
 	if (auth_opts->permit_pty_flag) {
Jakub Jelen 6cf9b8
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
Jakub Jelen bbf61d
@@ -1695,6 +1712,13 @@ monitor_apply_keystate(struct monitor *p
Jakub Jelen 132f8f
 # endif
Jakub Jelen 132f8f
 #endif /* WITH_OPENSSL */
Jakub Jelen 132f8f
 		kex->kex[KEX_C25519_SHA256] = kexc25519_server;
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	if (options.gss_keyex) {
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jakub Jelen 132f8f
 		kex->load_host_public_key=&get_hostkey_public_by_type;
Jakub Jelen 132f8f
 		kex->load_host_private_key=&get_hostkey_private_by_type;
Jakub Jelen 132f8f
 		kex->host_key_index=&get_hostkey_index;
Jakub Jelen bbf61d
@@ -1785,7 +1809,7 @@ mm_answer_gss_setup_ctx(int sock, struct
Jakub Jelen bbf61d
 	u_char *p;
Jakub Jelen bbf61d
 	int r;
Jan F. Chadima 69dd72
 
Jakub Jelen 6cf9b8
-	if (!options.gss_authentication)
Jan F. Chadima 69dd72
+	if (!options.gss_authentication && !options.gss_keyex)
Jakub Jelen 6cf9b8
 		fatal("%s: GSSAPI authentication not enabled", __func__);
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
 	if ((r = sshbuf_get_string(m, &p, &len)) != 0)
Jakub Jelen bbf61d
@@ -1818,7 +1842,7 @@ mm_answer_gss_accept_ctx(int sock, struc
Jan F. Chadima 69dd72
 	OM_uint32 flags = 0; /* GSI needs this */
Jakub Jelen bbf61d
 	int r;
Jan F. Chadima 69dd72
 
Jakub Jelen 6cf9b8
-	if (!options.gss_authentication)
Jan F. Chadima 69dd72
+	if (!options.gss_authentication && !options.gss_keyex)
Jakub Jelen 6cf9b8
 		fatal("%s: GSSAPI authentication not enabled", __func__);
Jakub Jelen 6cf9b8
 
Jakub Jelen bbf61d
 	if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)
Jakub Jelen bbf61d
@@ -1839,6 +1863,7 @@ mm_answer_gss_accept_ctx(int sock, struc
Jan F. Chadima 69dd72
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
Jan F. Chadima 69dd72
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
Jan F. Chadima 69dd72
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
Jan F. Chadima 69dd72
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
 	return (0);
Jan F. Chadima 69dd72
 }
Jakub Jelen bbf61d
@@ -1850,7 +1875,7 @@ mm_answer_gss_checkmic(int sock, struct
Jan F. Chadima 69dd72
 	OM_uint32 ret;
Jakub Jelen bbf61d
 	int r;
Jan F. Chadima 69dd72
 
Jakub Jelen 6cf9b8
-	if (!options.gss_authentication)
Jan F. Chadima 69dd72
+	if (!options.gss_authentication && !options.gss_keyex)
Jakub Jelen 6cf9b8
 		fatal("%s: GSSAPI authentication not enabled", __func__);
Jakub Jelen 6cf9b8
 
Jakub Jelen bbf61d
 	if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||
Jakub Jelen bbf61d
@@ -1880,10 +1905,11 @@ mm_answer_gss_userok(int sock, struct ss
Jakub Jelen bbf61d
 	int r, authenticated;
Jakub Jelen 5b55d0
 	const char *displayname;
Jan F. Chadima 69dd72
 
Jakub Jelen 6cf9b8
-	if (!options.gss_authentication)
Jan F. Chadima 69dd72
+	if (!options.gss_authentication && !options.gss_keyex)
Jakub Jelen 6cf9b8
 		fatal("%s: GSSAPI authentication not enabled", __func__);
Jakub Jelen 6cf9b8
 
Jakub Jelen 6cf9b8
-	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
Jakub Jelen 6cf9b8
+	authenticated = authctxt->valid &&
Jan F. Chadima 69dd72
+	    ssh_gssapi_userok(authctxt->user, authctxt->pw);
Jan F. Chadima 69dd72
 
Jakub Jelen bbf61d
 	sshbuf_reset(m);
Jakub Jelen bbf61d
 	if ((r = sshbuf_put_u32(m, authenticated)) != 0)
Jakub Jelen bbf61d
@@ -1900,5 +1926,74 @@ mm_answer_gss_userok(int sock, struct ss
Jan F. Chadima 69dd72
 	/* Monitor loop will terminate if authenticated */
Jan F. Chadima 69dd72
 	return (authenticated);
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+int 
Jakub Jelen bbf61d
+mm_answer_gss_sign(int socket, struct sshbuf *m)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	gss_buffer_desc data;
Jan F. Chadima 69dd72
+	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
+	OM_uint32 major, minor;
Jakub Jelen bbf61d
+	int r;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (!options.gss_authentication && !options.gss_keyex)
Jan F. Chadima 69dd72
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_get_string(m, (u_char **)&data.value, &data.length)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+	if (data.length != 20) 
Jan F. Chadima 69dd72
+		fatal("%s: data length incorrect: %d", __func__, 
Jan F. Chadima 69dd72
+		    (int) data.length);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Save the session ID on the first time around */
Jan F. Chadima 69dd72
+	if (session_id2_len == 0) {
Jan F. Chadima 69dd72
+		session_id2_len = data.length;
Jan F. Chadima 69dd72
+		session_id2 = xmalloc(session_id2_len);
Jan F. Chadima 69dd72
+		memcpy(session_id2, data.value, session_id2_len);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+	major = ssh_gssapi_sign(gsscontext, &data, &hash);
Jan F. Chadima 69dd72
+
Petr Lautrbach 84822b
+	free(data.value);
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	sshbuf_reset(m);
Jakub Jelen bbf61d
+	if ((r = sshbuf_put_u32(m, major)) != 0 ||
Jakub Jelen bbf61d
+	    (r = sshbuf_put_string(m, hash.value, hash.length)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	gss_release_buffer(&minor, &hash);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Turn on getpwnam permissions */
Jan F. Chadima 69dd72
+	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
Jan F. Chadima 69dd72
+	
Jan F. Chadima 69dd72
+	/* And credential updating, for when rekeying */
Jan F. Chadima 69dd72
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return (0);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+int
Jakub Jelen bbf61d
+mm_answer_gss_updatecreds(int socket, struct sshbuf *m) {
Jan F. Chadima 69dd72
+	ssh_gssapi_ccache store;
Jakub Jelen bbf61d
+	int ok, r;
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_get_cstring(m, &store.envvar, NULL)) != 0 ||
Jakub Jelen bbf61d
+	    (r = sshbuf_get_cstring(m, &store.envval, NULL)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	ok = ssh_gssapi_update_creds(&store);
Jan F. Chadima 69dd72
+
Petr Lautrbach 84822b
+	free(store.envvar);
Petr Lautrbach 84822b
+	free(store.envval);
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	sshbuf_reset(m);
Jakub Jelen bbf61d
+	if ((r = sshbuf_put_u32(m, ok)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return(0);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 #endif /* GSSAPI */
Jan F. Chadima 69dd72
 
Jakub Jelen 5b55d0
diff -up openssh/monitor.h.gsskex openssh/monitor.h
Jakub Jelen bbf61d
--- openssh/monitor.h.gsskex	2018-08-22 11:47:33.263216069 +0200
Jakub Jelen bbf61d
+++ openssh/monitor.h	2018-08-22 11:47:33.313216473 +0200
Jakub Jelen bbf61d
@@ -58,6 +58,8 @@ enum monitor_reqtype {
Petr Lautrbach 8a29de
 #ifdef WITH_SELINUX
Petr Lautrbach 8a29de
 	MONITOR_REQ_AUTHROLE = 80,
Petr Lautrbach 8a29de
 #endif
Petr Lautrbach 8a29de
+	MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83,
Petr Lautrbach 8a29de
+	MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85,
Petr Lautrbach 8a29de
 
Petr Lautrbach 8a29de
 	MONITOR_REQ_PAM_START = 100,
Petr Lautrbach 8a29de
 	MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
Jakub Jelen 5b55d0
diff -up openssh/monitor_wrap.c.gsskex openssh/monitor_wrap.c
Jakub Jelen bbf61d
--- openssh/monitor_wrap.c.gsskex	2018-08-22 11:47:33.313216473 +0200
Jakub Jelen bbf61d
+++ openssh/monitor_wrap.c	2018-08-22 13:27:38.665669643 +0200
Jakub Jelen bbf61d
@@ -1004,7 +1004,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 int
Jan F. Chadima 69dd72
-mm_ssh_gssapi_userok(char *user)
Jan F. Chadima 69dd72
+mm_ssh_gssapi_userok(char *user, struct passwd *pw)
Jan F. Chadima 69dd72
 {
Jakub Jelen bbf61d
 	struct sshbuf *m;
Jakub Jelen bbf61d
 	int r, authenticated = 0;
Jakub Jelen bbf61d
@@ -1023,4 +1023,52 @@ mm_ssh_gssapi_userok(char *user)
Jan F. Chadima 69dd72
 	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
Jan F. Chadima 69dd72
 	return (authenticated);
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+OM_uint32
Jan F. Chadima 69dd72
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
Jan F. Chadima 69dd72
+{
Jakub Jelen bbf61d
+	struct sshbuf *m;
Jan F. Chadima 69dd72
+	OM_uint32 major;
Jakub Jelen bbf61d
+	int r;
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((m = sshbuf_new()) == NULL)
Jakub Jelen bbf61d
+		fatal("%s: sshbuf_new failed", __func__);
Jakub Jelen bbf61d
+	if ((r = sshbuf_put_string(m, data->value, data->length)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, m);
Jakub Jelen bbf61d
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, m);
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_get_u32(m, &major)) != 0 ||
Jakub Jelen bbf61d
+	    (r = sshbuf_get_string(m, (u_char **)&hash->value, &hash->length)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	sshbuf_free(m);
Jan F. Chadima 69dd72
+
Jakub Jelen eaa7af
+	return (major);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+int
Jan F. Chadima 69dd72
+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
Jan F. Chadima 69dd72
+{
Jakub Jelen bbf61d
+	struct sshbuf *m;
Jakub Jelen bbf61d
+	int ok, r;
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((m = sshbuf_new()) == NULL)
Jakub Jelen bbf61d
+		fatal("%s: sshbuf_new failed", __func__);
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_put_cstring(m, store->envvar ? store->envvar : "")) != 0 ||
Jakub Jelen bbf61d
+	    (r = sshbuf_put_cstring(m, store->envval ? store->envval : "")) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Petr Lautrbach 3e1dd6
+
Jakub Jelen bbf61d
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, m);
Jakub Jelen bbf61d
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, m);
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	if ((r = sshbuf_get_u32(m, &ok)) != 0)
Jakub Jelen bbf61d
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	sshbuf_free(m);
Petr Lautrbach 3e1dd6
+
Jan F. Chadima 69dd72
+	return (ok);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
 #endif /* GSSAPI */
Jakub Jelen 5b55d0
diff -up openssh/monitor_wrap.h.gsskex openssh/monitor_wrap.h
Jakub Jelen bbf61d
--- openssh/monitor_wrap.h.gsskex	2018-08-22 11:47:33.263216069 +0200
Jakub Jelen bbf61d
+++ openssh/monitor_wrap.h	2018-08-22 11:47:33.313216473 +0200
Jakub Jelen bbf61d
@@ -63,8 +63,10 @@ int mm_sshkey_verify(const struct sshkey
Jan F. Chadima 69dd72
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
Jan F. Chadima 69dd72
 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
Jan F. Chadima 69dd72
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
Jan F. Chadima 69dd72
-int mm_ssh_gssapi_userok(char *user);
Jan F. Chadima 69dd72
+int mm_ssh_gssapi_userok(char *user, struct passwd *);
Jan F. Chadima 69dd72
 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
Jan F. Chadima 69dd72
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
Jan F. Chadima 69dd72
+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
Jan F. Chadima 69dd72
 #endif
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #ifdef USE_PAM
Jakub Jelen 5b55d0
diff -up openssh/readconf.c.gsskex openssh/readconf.c
Jakub Jelen bbf61d
--- openssh/readconf.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/readconf.c	2018-08-22 13:28:17.487982869 +0200
Jakub Jelen bbf61d
@@ -161,6 +161,8 @@ typedef enum {
Jan F. Chadima 69dd72
 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
Jan F. Chadima 69dd72
 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
Jan F. Chadima 69dd72
 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
Jan F. Chadima 69dd72
+	oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
Jan F. Chadima 69dd72
+	oGssServerIdentity, 
Jan F. Chadima 69dd72
 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
Jakub Jelen bbf61d
 	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
Jan F. Chadima 69dd72
 	oHashKnownHosts,
Jakub Jelen bbf61d
@@ -201,10 +203,19 @@ static struct {
Jakub Jelen 17b491
 	/* Sometimes-unsupported options */
Jan F. Chadima 69dd72
 #if defined(GSSAPI)
Jan F. Chadima 69dd72
 	{ "gssapiauthentication", oGssAuthentication },
Jan F. Chadima 69dd72
+	{ "gssapikeyexchange", oGssKeyEx },
Jan F. Chadima 69dd72
 	{ "gssapidelegatecredentials", oGssDelegateCreds },
Jan F. Chadima 69dd72
+	{ "gssapitrustdns", oGssTrustDns },
Jan F. Chadima 69dd72
+	{ "gssapiclientidentity", oGssClientIdentity },
Jan F. Chadima 69dd72
+	{ "gssapiserveridentity", oGssServerIdentity },
Jan F. Chadima 69dd72
+	{ "gssapirenewalforcesrekey", oGssRenewalRekey },
Jakub Jelen 17b491
 # else
Jan F. Chadima 69dd72
 	{ "gssapiauthentication", oUnsupported },
Jan F. Chadima 69dd72
+	{ "gssapikeyexchange", oUnsupported },
Jan F. Chadima 69dd72
 	{ "gssapidelegatecredentials", oUnsupported },
Jan F. Chadima 69dd72
+	{ "gssapitrustdns", oUnsupported },
Jan F. Chadima 69dd72
+	{ "gssapiclientidentity", oUnsupported },
Jan F. Chadima 69dd72
+	{ "gssapirenewalforcesrekey", oUnsupported },
Jan F. Chadima 69dd72
 #endif
Jakub Jelen 17b491
 #ifdef ENABLE_PKCS11
Jakub Jelen 17b491
 	{ "smartcarddevice", oPKCS11Provider },
Jakub Jelen bbf61d
@@ -973,10 +984,30 @@ parse_time:
Jan F. Chadima 69dd72
 		intptr = &options->gss_authentication;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	case oGssKeyEx:
Jan F. Chadima 69dd72
+		intptr = &options->gss_keyex;
Jan F. Chadima 69dd72
+		goto parse_flag;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	case oGssDelegateCreds:
Jan F. Chadima 69dd72
 		intptr = &options->gss_deleg_creds;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	case oGssTrustDns:
Jan F. Chadima 69dd72
+		intptr = &options->gss_trust_dns;
Jan F. Chadima 69dd72
+		goto parse_flag;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	case oGssClientIdentity:
Jan F. Chadima 69dd72
+		charptr = &options->gss_client_identity;
Jan F. Chadima 69dd72
+		goto parse_string;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	case oGssServerIdentity:
Jan F. Chadima 69dd72
+		charptr = &options->gss_server_identity;
Jan F. Chadima 69dd72
+		goto parse_string;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	case oGssRenewalRekey:
Jan F. Chadima 69dd72
+		intptr = &options->gss_renewal_rekey;
Jan F. Chadima 69dd72
+		goto parse_flag;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	case oBatchMode:
Jan F. Chadima 69dd72
 		intptr = &options->batch_mode;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jakub Jelen bbf61d
@@ -1817,7 +1848,12 @@ initialize_options(Options * options)
Jan F. Chadima 69dd72
 	options->pubkey_authentication = -1;
Jan F. Chadima 69dd72
 	options->challenge_response_authentication = -1;
Jan F. Chadima 69dd72
 	options->gss_authentication = -1;
Jan F. Chadima 69dd72
+	options->gss_keyex = -1;
Jan F. Chadima 69dd72
 	options->gss_deleg_creds = -1;
Jan F. Chadima 69dd72
+	options->gss_trust_dns = -1;
Jan F. Chadima 69dd72
+	options->gss_renewal_rekey = -1;
Jan F. Chadima 69dd72
+	options->gss_client_identity = NULL;
Jan F. Chadima 69dd72
+	options->gss_server_identity = NULL;
Jan F. Chadima 69dd72
 	options->password_authentication = -1;
Jan F. Chadima 69dd72
 	options->kbd_interactive_authentication = -1;
Jan F. Chadima 69dd72
 	options->kbd_interactive_devices = NULL;
Jakub Jelen bbf61d
@@ -1962,8 +1998,14 @@ fill_default_options(Options * options)
Jan F. Chadima 69dd72
 		options->challenge_response_authentication = 1;
Jan F. Chadima 69dd72
 	if (options->gss_authentication == -1)
Jan F. Chadima 69dd72
 		options->gss_authentication = 0;
Jan F. Chadima 69dd72
+	if (options->gss_keyex == -1)
Jan F. Chadima 69dd72
+		options->gss_keyex = 0;
Jan F. Chadima 69dd72
 	if (options->gss_deleg_creds == -1)
Jan F. Chadima 69dd72
 		options->gss_deleg_creds = 0;
Jan F. Chadima 69dd72
+	if (options->gss_trust_dns == -1)
Jan F. Chadima 69dd72
+		options->gss_trust_dns = 0;
Jan F. Chadima 69dd72
+	if (options->gss_renewal_rekey == -1)
Jan F. Chadima 69dd72
+		options->gss_renewal_rekey = 0;
Jan F. Chadima 69dd72
 	if (options->password_authentication == -1)
Jan F. Chadima 69dd72
 		options->password_authentication = 1;
Jan F. Chadima 69dd72
 	if (options->kbd_interactive_authentication == -1)
Jakub Jelen 5b55d0
diff -up openssh/readconf.h.gsskex openssh/readconf.h
Jakub Jelen bbf61d
--- openssh/readconf.h.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/readconf.h	2018-08-22 11:47:33.314216481 +0200
Jakub Jelen bbf61d
@@ -40,7 +40,12 @@ typedef struct {
Jan F. Chadima 69dd72
 	int     challenge_response_authentication;
Jan F. Chadima 69dd72
 					/* Try S/Key or TIS, authentication. */
Jan F. Chadima 69dd72
 	int     gss_authentication;	/* Try GSS authentication */
Jan F. Chadima 69dd72
+	int     gss_keyex;		/* Try GSS key exchange */
Jan F. Chadima 69dd72
 	int     gss_deleg_creds;	/* Delegate GSS credentials */
Jan F. Chadima 69dd72
+	int	gss_trust_dns;		/* Trust DNS for GSS canonicalization */
Jan F. Chadima 69dd72
+	int	gss_renewal_rekey;	/* Credential renewal forces rekey */
Jan F. Chadima 69dd72
+	char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
Jan F. Chadima 69dd72
+	char    *gss_server_identity;   /* GSSAPI target principal */
Jan F. Chadima 69dd72
 	int     password_authentication;	/* Try password
Jan F. Chadima 69dd72
 						 * authentication. */
Jan F. Chadima 69dd72
 	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
Jakub Jelen 5b55d0
diff -up openssh/regress/cert-hostkey.sh.gsskex openssh/regress/cert-hostkey.sh
Jakub Jelen bbf61d
--- openssh/regress/cert-hostkey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/regress/cert-hostkey.sh	2018-08-22 11:47:33.314216481 +0200
Jakub Jelen bbf61d
@@ -66,7 +66,7 @@ touch $OBJ/host_revoked_plain
Jakub Jelen 132f8f
 touch $OBJ/host_revoked_cert
Jakub Jelen 5878eb
 cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca
Petr Lautrbach 3e1dd6
 
Petr Lautrbach 3e1dd6
-PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
Petr Lautrbach 3e1dd6
+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
Petr Lautrbach 3e1dd6
 
Jakub Jelen 5878eb
 if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
Jakub Jelen 5878eb
 	PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
Jakub Jelen 5b55d0
diff -up openssh/regress/cert-userkey.sh.gsskex openssh/regress/cert-userkey.sh
Jakub Jelen bbf61d
--- openssh/regress/cert-userkey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/regress/cert-userkey.sh	2018-08-22 11:47:33.314216481 +0200
Jakub Jelen 3f5513
@@ -7,7 +7,7 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us
Petr Lautrbach 3e1dd6
 cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
Jakub Jelen 3f5513
 cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
Petr Lautrbach 3e1dd6
 
Petr Lautrbach 3e1dd6
-PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
Petr Lautrbach 3e1dd6
+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
Jakub Jelen 3cd489
 EXTRA_TYPES=""
Petr Lautrbach 3e1dd6
 
Jakub Jelen 5878eb
 if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
Jakub Jelen 5b55d0
diff -up openssh/regress/kextype.sh.gsskex openssh/regress/kextype.sh
Jakub Jelen bbf61d
--- openssh/regress/kextype.sh.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/regress/kextype.sh	2018-08-22 11:47:33.315216489 +0200
Jakub Jelen 132f8f
@@ -14,6 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/ssh
Petr Lautrbach 3e1dd6
 
Petr Lautrbach 3e1dd6
 tries="1 2 3 4"
Petr Lautrbach 3e1dd6
 for k in `${SSH} -Q kex`; do
Petr Lautrbach 3e1dd6
+	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then
Petr Lautrbach 3e1dd6
+		continue
Petr Lautrbach 3e1dd6
+	fi
Petr Lautrbach 3e1dd6
 	verbose "kex $k"
Petr Lautrbach 3e1dd6
 	for i in $tries; do
Petr Lautrbach 3e1dd6
 		${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true
Jakub Jelen 5b55d0
diff -up openssh/regress/rekey.sh.gsskex openssh/regress/rekey.sh
Jakub Jelen bbf61d
--- openssh/regress/rekey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/regress/rekey.sh	2018-08-22 11:47:33.315216489 +0200
Petr Lautrbach 190035
@@ -38,6 +38,9 @@ increase_datafile_size 300
Petr Lautrbach 3e1dd6
 
Petr Lautrbach 3e1dd6
 opts=""
Petr Lautrbach 3e1dd6
 for i in `${SSH} -Q kex`; do
Petr Lautrbach 3e1dd6
+	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then
Petr Lautrbach 3e1dd6
+		continue
Petr Lautrbach 3e1dd6
+	fi
Petr Lautrbach 3e1dd6
 	opts="$opts KexAlgorithms=$i"
Petr Lautrbach 3e1dd6
 done
Petr Lautrbach 3e1dd6
 for i in `${SSH} -Q cipher`; do
Petr Lautrbach 190035
@@ -56,6 +59,9 @@ done
Petr Lautrbach 3e1dd6
 if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then
Petr Lautrbach 3e1dd6
   for c in `${SSH} -Q cipher-auth`; do
Petr Lautrbach 3e1dd6
     for kex in `${SSH} -Q kex`; do
Petr Lautrbach 3e1dd6
+	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then
Petr Lautrbach 3e1dd6
+		continue
Petr Lautrbach 3e1dd6
+	fi
Petr Lautrbach 3e1dd6
 	verbose "client rekey $c $kex"
Petr Lautrbach 190035
 	ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c
Petr Lautrbach 3e1dd6
     done
Jakub Jelen 5b55d0
diff -up openssh/servconf.c.gsskex openssh/servconf.c
Jakub Jelen bbf61d
--- openssh/servconf.c.gsskex	2018-08-22 11:47:33.296216335 +0200
Jakub Jelen bbf61d
+++ openssh/servconf.c	2018-08-22 13:28:41.905179879 +0200
Jakub Jelen bbf61d
@@ -124,8 +124,10 @@ initialize_server_options(ServerOptions
Jan F. Chadima 69dd72
 	options->kerberos_ticket_cleanup = -1;
Jan F. Chadima 69dd72
 	options->kerberos_get_afs_token = -1;
Jan F. Chadima 69dd72
 	options->gss_authentication=-1;
Jan F. Chadima 69dd72
+	options->gss_keyex = -1;
Jan F. Chadima 69dd72
 	options->gss_cleanup_creds = -1;
Jakub Jelen 535d34
 	options->gss_strict_acceptor = -1;
Jan F. Chadima 69dd72
+	options->gss_store_rekey = -1;
Jan F. Chadima 69dd72
 	options->password_authentication = -1;
Jan F. Chadima 69dd72
 	options->kbd_interactive_authentication = -1;
Jan F. Chadima 69dd72
 	options->challenge_response_authentication = -1;
Jakub Jelen bbf61d
@@ -334,10 +336,14 @@ fill_default_server_options(ServerOption
Jan F. Chadima 69dd72
 		options->kerberos_get_afs_token = 0;
Jan F. Chadima 69dd72
 	if (options->gss_authentication == -1)
Jan F. Chadima 69dd72
 		options->gss_authentication = 0;
Jan F. Chadima 69dd72
+	if (options->gss_keyex == -1)
Jan F. Chadima 69dd72
+		options->gss_keyex = 0;
Jan F. Chadima 69dd72
 	if (options->gss_cleanup_creds == -1)
Jan F. Chadima 69dd72
 		options->gss_cleanup_creds = 1;
Jakub Jelen 535d34
 	if (options->gss_strict_acceptor == -1)
Jakub Jelen 17b491
 		options->gss_strict_acceptor = 1;
Jan F. Chadima 69dd72
+	if (options->gss_store_rekey == -1)
Jan F. Chadima 69dd72
+		options->gss_store_rekey = 0;
Jan F. Chadima 69dd72
 	if (options->password_authentication == -1)
Jan F. Chadima 69dd72
 		options->password_authentication = 1;
Jan F. Chadima 69dd72
 	if (options->kbd_interactive_authentication == -1)
Jakub Jelen bbf61d
@@ -484,7 +490,7 @@ typedef enum {
Jakub Jelen 3f5513
 	sHostKeyAlgorithms,
Jakub Jelen 132f8f
 	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
Jakub Jelen 535d34
 	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
Jakub Jelen bbf61d
-	sAcceptEnv, sSetEnv, sPermitTunnel,
Jakub Jelen bbf61d
+	sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,
Jakub Jelen bbf61d
 	sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
Jan F. Chadima 69dd72
 	sUsePrivilegeSeparation, sAllowAgentForwarding,
Petr Lautrbach 3e1dd6
 	sHostCertificate,
Jakub Jelen bbf61d
@@ -559,11 +565,17 @@ static struct {
Jan F. Chadima 69dd72
 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
Jan F. Chadima 69dd72
 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
Jakub Jelen 535d34
 	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
 #else
Jan F. Chadima 69dd72
 	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
Jan F. Chadima 69dd72
 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
Jakub Jelen 535d34
 	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
 #endif
Jan F. Chadima 69dd72
+	{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
Jan F. Chadima 69dd72
 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
Jan F. Chadima 69dd72
 	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
Jakub Jelen bbf61d
@@ -1463,6 +1475,10 @@ process_server_config_line(ServerOptions
Jan F. Chadima 69dd72
 		intptr = &options->gss_authentication;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	case sGssKeyEx:
Jan F. Chadima 69dd72
+		intptr = &options->gss_keyex;
Jan F. Chadima 69dd72
+		goto parse_flag;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	case sGssCleanupCreds:
Jan F. Chadima 69dd72
 		intptr = &options->gss_cleanup_creds;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jakub Jelen bbf61d
@@ -1471,6 +1487,10 @@ process_server_config_line(ServerOptions
Jakub Jelen 535d34
 		intptr = &options->gss_strict_acceptor;
Jakub Jelen 535d34
 		goto parse_flag;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	case sGssStoreRekey:
Jan F. Chadima 69dd72
+		intptr = &options->gss_store_rekey;
Jan F. Chadima 69dd72
+		goto parse_flag;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	case sPasswordAuthentication:
Jan F. Chadima 69dd72
 		intptr = &options->password_authentication;
Jan F. Chadima 69dd72
 		goto parse_flag;
Jakub Jelen bbf61d
@@ -2560,6 +2580,9 @@ dump_config(ServerOptions *o)
Petr Lautrbach d9e618
 #ifdef GSSAPI
Jan F. Chadima 69dd72
 	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
Jan F. Chadima 69dd72
 	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
Jan F. Chadima 69dd72
+	dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
Jan F. Chadima 69dd72
+	dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
Jan F. Chadima 69dd72
+	dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
Jan F. Chadima 69dd72
 #endif
Petr Lautrbach 3e1dd6
 	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
Petr Lautrbach 3e1dd6
 	dump_cfg_fmtint(sKbdInteractiveAuthentication,
Jakub Jelen 5b55d0
diff -up openssh/servconf.h.gsskex openssh/servconf.h
Jakub Jelen bbf61d
--- openssh/servconf.h.gsskex	2018-08-22 11:47:33.296216335 +0200
Jakub Jelen bbf61d
+++ openssh/servconf.h	2018-08-22 11:47:33.316216497 +0200
Jakub Jelen bbf61d
@@ -124,8 +124,10 @@ typedef struct {
Jan F. Chadima 69dd72
 	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
Jan F. Chadima 69dd72
 						 * authenticated with Kerberos. */
Jan F. Chadima 69dd72
 	int     gss_authentication;	/* If true, permit GSSAPI authentication */
Jan F. Chadima 69dd72
+	int     gss_keyex;		/* If true, permit GSSAPI key exchange */
Jan F. Chadima 69dd72
 	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
Jakub Jelen 535d34
 	int     gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */
Jan F. Chadima 69dd72
+	int 	gss_store_rekey;
Jan F. Chadima 69dd72
 	int     password_authentication;	/* If true, permit password
Jan F. Chadima 69dd72
 						 * authentication. */
Jan F. Chadima 69dd72
 	int     kbd_interactive_authentication;	/* If true, permit */
Jakub Jelen 5b55d0
diff -up openssh/ssh_config.5.gsskex openssh/ssh_config.5
Jakub Jelen bbf61d
--- openssh/ssh_config.5.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/ssh_config.5	2018-08-22 11:47:33.316216497 +0200
Jakub Jelen bbf61d
@@ -718,10 +718,40 @@ The default is
Jakub Jelen 13073f
 Specifies whether user authentication based on GSSAPI is allowed.
Jan F. Chadima 69dd72
 The default is
Jakub Jelen 6cf9b8
 .Cm no .
Jan F. Chadima 69dd72
+.It Cm GSSAPIClientIdentity
Jan F. Chadima 69dd72
+If set, specifies the GSSAPI client identity that ssh should use when 
Jan F. Chadima 69dd72
+connecting to the server. The default is unset, which means that the default 
Jan F. Chadima 69dd72
+identity will be used.
Jan F. Chadima 69dd72
 .It Cm GSSAPIDelegateCredentials
Jan F. Chadima 69dd72
 Forward (delegate) credentials to the server.
Jan F. Chadima 69dd72
 The default is
Jakub Jelen 6cf9b8
 .Cm no .
Jakub Jelen 6cf9b8
+.It Cm GSSAPIKeyExchange
Jakub Jelen 6cf9b8
+Specifies whether key exchange based on GSSAPI may be used. When using
Jakub Jelen 6cf9b8
+GSSAPI key exchange the server need not have a host key.
Jakub Jelen 6cf9b8
+The default is
Jakub Jelen 6cf9b8
+.Dq no .
Jan F. Chadima 69dd72
+.It Cm GSSAPIRenewalForcesRekey
Jan F. Chadima 69dd72
+If set to 
Jan F. Chadima 69dd72
+.Dq yes
Jan F. Chadima 69dd72
+then renewal of the client's GSSAPI credentials will force the rekeying of the
Jan F. Chadima 69dd72
+ssh connection. With a compatible server, this can delegate the renewed 
Jan F. Chadima 69dd72
+credentials to a session on the server.
Jan F. Chadima 69dd72
+The default is
Jan F. Chadima 69dd72
+.Dq no .
Jakub Jelen 6cf9b8
+.It Cm GSSAPIServerIdentity
Jakub Jelen 6cf9b8
+If set, specifies the GSSAPI server identity that ssh should expect when 
Jakub Jelen 6cf9b8
+connecting to the server. The default is unset, which means that the
Jakub Jelen 6cf9b8
+expected GSSAPI server identity will be determined from the target
Jakub Jelen 6cf9b8
+hostname.
Jan F. Chadima 69dd72
+.It Cm GSSAPITrustDns
Jan F. Chadima 69dd72
+Set to 
Jan F. Chadima 69dd72
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
Jan F. Chadima 69dd72
+the name of the host being connected to. If 
Jan F. Chadima 69dd72
+.Dq no, the hostname entered on the
Jan F. Chadima 69dd72
+command line will be passed untouched to the GSSAPI library.
Jan F. Chadima 69dd72
+The default is
Jan F. Chadima 69dd72
+.Dq no .
Jan F. Chadima 69dd72
 .It Cm HashKnownHosts
Jan F. Chadima 69dd72
 Indicates that
Jan F. Chadima 69dd72
 .Xr ssh 1
Jakub Jelen 5b55d0
diff -up openssh/ssh_config.gsskex openssh/ssh_config
Jakub Jelen bbf61d
--- openssh/ssh_config.gsskex	2018-08-22 11:47:33.289216279 +0200
Jakub Jelen bbf61d
+++ openssh/ssh_config	2018-08-22 11:47:33.316216497 +0200
Jakub Jelen 5b55d0
@@ -24,6 +24,8 @@
Jakub Jelen 535d34
 #   HostbasedAuthentication no
Jakub Jelen 535d34
 #   GSSAPIAuthentication no
Jakub Jelen 535d34
 #   GSSAPIDelegateCredentials no
Jakub Jelen 535d34
+#   GSSAPIKeyExchange no
Jakub Jelen 535d34
+#   GSSAPITrustDNS no
Jakub Jelen 535d34
 #   BatchMode no
Jakub Jelen 535d34
 #   CheckHostIP yes
Jakub Jelen 535d34
 #   AddressFamily any
Jakub Jelen 5b55d0
diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c
Jakub Jelen bbf61d
--- openssh/sshconnect2.c.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/sshconnect2.c	2018-08-22 13:33:01.674275795 +0200
Jakub Jelen 5b55d0
@@ -82,6 +82,124 @@ extern char *client_version_string;
Jakub Jelen 5b55d0
 extern char *server_version_string;
Jakub Jelen 5b55d0
 extern Options options;
Jakub Jelen 5b55d0
 
Jakub Jelen 5b55d0
+/* XXX from auth.h -- refactoring move these useful functions away of client context*/
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+/*
Jakub Jelen 5b55d0
+ * Returns the remote DNS hostname as a string. The returned string must not
Jakub Jelen 5b55d0
+ * be freed. NB. this will usually trigger a DNS query the first time it is
Jakub Jelen 5b55d0
+ * called.
Jakub Jelen 5b55d0
+ * This function does additional checks on the hostname to mitigate some
Jakub Jelen 5b55d0
+ * attacks on legacy rhosts-style authentication.
Jakub Jelen 5b55d0
+ * XXX is RhostsRSAAuthentication vulnerable to these?
Jakub Jelen 5b55d0
+ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
Jakub Jelen 5b55d0
+ */
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+static char *
Jakub Jelen 5b55d0
+remote_hostname(struct ssh *ssh)
Jakub Jelen 5b55d0
+{
Jakub Jelen 5b55d0
+	struct sockaddr_storage from;
Jakub Jelen 5b55d0
+	socklen_t fromlen;
Jakub Jelen 5b55d0
+	struct addrinfo hints, *ai, *aitop;
Jakub Jelen 5b55d0
+	char name[NI_MAXHOST], ntop2[NI_MAXHOST];
Jakub Jelen 5b55d0
+	const char *ntop = ssh_remote_ipaddr(ssh);
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	/* Get IP address of client. */
Jakub Jelen 5b55d0
+	fromlen = sizeof(from);
Jakub Jelen 5b55d0
+	memset(&from, 0, sizeof(from));
Jakub Jelen 5b55d0
+	if (getpeername(ssh_packet_get_connection_in(ssh),
Jakub Jelen 5b55d0
+	    (struct sockaddr *)&from, &fromlen) < 0) {
Jakub Jelen 5b55d0
+		debug("getpeername failed: %.100s", strerror(errno));
Jakub Jelen 5b55d0
+		return strdup(ntop);
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	ipv64_normalise_mapped(&from, &fromlen);
Jakub Jelen 5b55d0
+	if (from.ss_family == AF_INET6)
Jakub Jelen 5b55d0
+		fromlen = sizeof(struct sockaddr_in6);
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	debug3("Trying to reverse map address %.100s.", ntop);
Jakub Jelen 5b55d0
+	/* Map the IP address to a host name. */
Jakub Jelen 5b55d0
+	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
Jakub Jelen 5b55d0
+	    NULL, 0, NI_NAMEREQD) != 0) {
Jakub Jelen 5b55d0
+		/* Host name not found.  Use ip address. */
Jakub Jelen 5b55d0
+		return strdup(ntop);
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	/*
Jakub Jelen 5b55d0
+	 * if reverse lookup result looks like a numeric hostname,
Jakub Jelen 5b55d0
+	 * someone is trying to trick us by PTR record like following:
Jakub Jelen 5b55d0
+	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5
Jakub Jelen 5b55d0
+	 */
Jakub Jelen 5b55d0
+	memset(&hints, 0, sizeof(hints));
Jakub Jelen 5b55d0
+	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
Jakub Jelen 5b55d0
+	hints.ai_flags = AI_NUMERICHOST;
Jakub Jelen 5b55d0
+	if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
Jakub Jelen 5b55d0
+		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
Jakub Jelen 5b55d0
+		    name, ntop);
Jakub Jelen 5b55d0
+		freeaddrinfo(ai);
Jakub Jelen 5b55d0
+		return strdup(ntop);
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	/* Names are stored in lowercase. */
Jakub Jelen 5b55d0
+	lowercase(name);
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	/*
Jakub Jelen 5b55d0
+	 * Map it back to an IP address and check that the given
Jakub Jelen 5b55d0
+	 * address actually is an address of this host.  This is
Jakub Jelen 5b55d0
+	 * necessary because anyone with access to a name server can
Jakub Jelen 5b55d0
+	 * define arbitrary names for an IP address. Mapping from
Jakub Jelen 5b55d0
+	 * name to IP address can be trusted better (but can still be
Jakub Jelen 5b55d0
+	 * fooled if the intruder has access to the name server of
Jakub Jelen 5b55d0
+	 * the domain).
Jakub Jelen 5b55d0
+	 */
Jakub Jelen 5b55d0
+	memset(&hints, 0, sizeof(hints));
Jakub Jelen 5b55d0
+	hints.ai_family = from.ss_family;
Jakub Jelen 5b55d0
+	hints.ai_socktype = SOCK_STREAM;
Jakub Jelen 5b55d0
+	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
Jakub Jelen 5b55d0
+		logit("reverse mapping checking getaddrinfo for %.700s "
Jakub Jelen 5b55d0
+		    "[%s] failed.", name, ntop);
Jakub Jelen 5b55d0
+		return strdup(ntop);
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+	/* Look for the address from the list of addresses. */
Jakub Jelen 5b55d0
+	for (ai = aitop; ai; ai = ai->ai_next) {
Jakub Jelen 5b55d0
+		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
Jakub Jelen 5b55d0
+		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
Jakub Jelen 5b55d0
+		    (strcmp(ntop, ntop2) == 0))
Jakub Jelen 5b55d0
+				break;
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+	freeaddrinfo(aitop);
Jakub Jelen 5b55d0
+	/* If we reached the end of the list, the address was not there. */
Jakub Jelen 5b55d0
+	if (ai == NULL) {
Jakub Jelen 5b55d0
+		/* Address not found for the host name. */
Jakub Jelen 5b55d0
+		logit("Address %.100s maps to %.600s, but this does not "
Jakub Jelen 5b55d0
+		    "map back to the address.", ntop, name);
Jakub Jelen 5b55d0
+		return strdup(ntop);
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+	return strdup(name);
Jakub Jelen 5b55d0
+}
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+/*
Jakub Jelen 5b55d0
+ * Return the canonical name of the host in the other side of the current
Jakub Jelen 5b55d0
+ * connection.  The host name is cached, so it is efficient to call this
Jakub Jelen 5b55d0
+ * several times.
Jakub Jelen 5b55d0
+ */
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+const char *
Jakub Jelen 5b55d0
+get_canonical_hostname(struct ssh *ssh, int use_dns)
Jakub Jelen 5b55d0
+{
Jakub Jelen 5b55d0
+	static char *dnsname;
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+	if (!use_dns)
Jakub Jelen 5b55d0
+		return ssh_remote_ipaddr(ssh);
Jakub Jelen 5b55d0
+	else if (dnsname != NULL)
Jakub Jelen 5b55d0
+		return dnsname;
Jakub Jelen 5b55d0
+	else {
Jakub Jelen 5b55d0
+		dnsname = remote_hostname(ssh);
Jakub Jelen 5b55d0
+		return dnsname;
Jakub Jelen 5b55d0
+	}
Jakub Jelen 5b55d0
+}
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
+
Jakub Jelen 5b55d0
 /*
Jakub Jelen 5b55d0
  * SSH2 key exchange
Jakub Jelen 5b55d0
  */
Jakub Jelen e8876f
@@ -162,9 +280,36 @@ ssh_kex2(char *host, struct sockaddr *ho
Jakub Jelen 132f8f
 	struct kex *kex;
Jakub Jelen 132f8f
 	int r;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	char *orig = NULL, *gss = NULL;
Jan F. Chadima 69dd72
+	char *gss_host = NULL;
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	xxx_host = host;
Jan F. Chadima 69dd72
 	xxx_hostaddr = hostaddr;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	if (options.gss_keyex) {
Jan F. Chadima 69dd72
+		/* Add the GSSAPI mechanisms currently supported on this 
Jan F. Chadima 69dd72
+		 * client to the key exchange algorithm proposal */
Jakub Jelen 9a804f
+		orig = options.kex_algorithms;
Jan F. Chadima 69dd72
+
Jakub Jelen e8876f
+		if (options.gss_server_identity)
Jakub Jelen e8876f
+			gss_host = options.gss_server_identity;
Jakub Jelen e8876f
+		else if (options.gss_trust_dns)
Jakub Jelen b487a6
+			gss_host = (char *)get_canonical_hostname(active_state, 1);
Jan F. Chadima 69dd72
+		else
Jan F. Chadima 69dd72
+			gss_host = host;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
Jan F. Chadima 69dd72
+		if (gss) {
Jan F. Chadima 69dd72
+			debug("Offering GSSAPI proposal: %s", gss);
Jakub Jelen 9a804f
+			xasprintf(&options.kex_algorithms,
Jan F. Chadima 69dd72
+			    "%s,%s", gss, orig);
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jakub Jelen 13073f
 	if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
Jakub Jelen 13073f
 		fatal("%s: kex_names_cat", __func__);
Jakub Jelen 13073f
 	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
Jakub Jelen bbf61d
@@ -194,6 +337,17 @@ ssh_kex2(char *host, struct sockaddr *ho
Jakub Jelen 3f5513
 		    order_hostkeyalgs(host, hostaddr, port));
Jakub Jelen 3f5513
 	}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	/* If we've got GSSAPI algorithms, then we also support the
Jan F. Chadima 69dd72
+	 * 'null' hostkey, as a last resort */
Jan F. Chadima 69dd72
+	if (options.gss_keyex && gss) {
Jan F. Chadima 69dd72
+		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
Jakub Jelen dba154
+		xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
Jan F. Chadima 69dd72
+		    "%s,null", orig);
Petr Lautrbach 84822b
+		free(gss);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Petr Lautrbach 84822b
 	if (options.rekey_limit || options.rekey_interval)
Jakub Jelen 17b491
 		packet_set_rekey_limits(options.rekey_limit,
Jakub Jelen 17b491
 		    options.rekey_interval);
Jakub Jelen bbf61d
@@ -214,11 +368,31 @@ ssh_kex2(char *host, struct sockaddr *ho
Jan F. Chadima 69dd72
 	kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
Jakub Jelen 132f8f
 # endif
Petr Lautrbach 190035
 #endif
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	if (options.gss_keyex) {
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jakub Jelen 132f8f
 	kex->kex[KEX_C25519_SHA256] = kexc25519_client;
Jan F. Chadima 69dd72
 	kex->client_version_string=client_version_string;
Jan F. Chadima 69dd72
 	kex->server_version_string=server_version_string;
Jan F. Chadima 69dd72
 	kex->verify_host_key=&verify_host_key_callback;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	if (options.gss_keyex) {
Jan F. Chadima 69dd72
+		kex->gss_deleg_creds = options.gss_deleg_creds;
Jan F. Chadima 69dd72
+		kex->gss_trust_dns = options.gss_trust_dns;
Jan F. Chadima 69dd72
+		kex->gss_client = options.gss_client_identity;
Jan F. Chadima 69dd72
+		if (options.gss_server_identity) {
Jan F. Chadima 69dd72
+			kex->gss_host = options.gss_server_identity;
Jan F. Chadima 69dd72
+		} else {
Jan F. Chadima 69dd72
+			kex->gss_host = gss_host;
Jan F. Chadima 69dd72
+        }
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jakub Jelen 5b55d0
 	ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
Jan F. Chadima 69dd72
 
Jakub Jelen 13073f
 	/* remove ext-info from the KEX proposals for rekeying */
Jakub Jelen bbf61d
@@ -314,6 +488,7 @@ int	input_gssapi_token(int type, u_int32
Jakub Jelen 5b55d0
 int	input_gssapi_hash(int type, u_int32_t, struct ssh *);
Jakub Jelen 5b55d0
 int	input_gssapi_error(int, u_int32_t, struct ssh *);
Jakub Jelen 5b55d0
 int	input_gssapi_errtok(int, u_int32_t, struct ssh *);
Jan F. Chadima 69dd72
+int	userauth_gsskeyex(Authctxt *authctxt);
Jan F. Chadima 69dd72
 #endif
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 void	userauth(Authctxt *, char *);
Jakub Jelen bbf61d
@@ -330,6 +505,11 @@ static char *authmethods_get(void);
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 Authmethod authmethods[] = {
Jan F. Chadima 69dd72
 #ifdef GSSAPI
Jan F. Chadima 69dd72
+	{"gssapi-keyex",
Jan F. Chadima 69dd72
+		userauth_gsskeyex,
Jan F. Chadima 69dd72
+		NULL,
Jan F. Chadima 69dd72
+		&options.gss_authentication,
Jan F. Chadima 69dd72
+		NULL},
Jan F. Chadima 69dd72
 	{"gssapi-with-mic",
Jan F. Chadima 69dd72
 		userauth_gssapi,
Jan F. Chadima 69dd72
 		NULL,
Jakub Jelen bbf61d
@@ -657,19 +837,31 @@ userauth_gssapi(Authctxt *authctxt)
Jan F. Chadima 69dd72
 	static u_int mech = 0;
Jan F. Chadima 69dd72
 	OM_uint32 min;
Jakub Jelen bbf61d
 	int r, ok = 0;
Jan F. Chadima 69dd72
+	const char *gss_host;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (options.gss_server_identity)
Jan F. Chadima 69dd72
+		gss_host = options.gss_server_identity;
Jan F. Chadima 69dd72
+	else if (options.gss_trust_dns)
Jakub Jelen b487a6
+		gss_host = get_canonical_hostname(active_state, 1);
Jan F. Chadima 69dd72
+	else
Jan F. Chadima 69dd72
+		gss_host = authctxt->host;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	/* Try one GSSAPI method at a time, rather than sending them all at
Jan F. Chadima 69dd72
 	 * once. */
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	if (gss_supported == NULL)
Jan F. Chadima 69dd72
-		gss_indicate_mechs(&min, &gss_supported);
Jan F. Chadima 69dd72
+		if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
Jan F. Chadima 69dd72
+			gss_supported = NULL;
Jan F. Chadima 69dd72
+			return 0;
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	/* Check to see if the mechanism is usable before we offer it */
Jan F. Chadima 69dd72
 	while (mech < gss_supported->count && !ok) {
Jan F. Chadima 69dd72
 		/* My DER encoding requires length<128 */
Jan F. Chadima 69dd72
 		if (gss_supported->elements[mech].length < 128 &&
Jakub Jelen bbf61d
 		    ssh_gssapi_check_mechanism(&gssctxt,
Jan F. Chadima 69dd72
-		    &gss_supported->elements[mech], authctxt->host)) {
Jan F. Chadima 69dd72
+		    &gss_supported->elements[mech], gss_host, 
Jan F. Chadima 69dd72
+                    options.gss_client_identity)) {
Jan F. Chadima 69dd72
 			ok = 1; /* Mechanism works */
Jan F. Chadima 69dd72
 		} else {
Jan F. Chadima 69dd72
 			mech++;
Jakub Jelen 90edc0
@@ -906,6 +1098,51 @@ input_gssapi_error(int type, u_int32_t p
Petr Lautrbach 84822b
 	free(lang);
Jakub Jelen bbf61d
 	return r;
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+int
Jan F. Chadima 69dd72
+userauth_gsskeyex(Authctxt *authctxt)
Jan F. Chadima 69dd72
+{
Jakub Jelen bbf61d
+	struct sshbuf *b = NULL;
Jan F. Chadima 69dd72
+	gss_buffer_desc gssbuf;
Jan F. Chadima 69dd72
+	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
Jan F. Chadima 69dd72
+	OM_uint32 ms;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	static int attempt = 0;
Jan F. Chadima 69dd72
+	if (attempt++ >= 1)
Jan F. Chadima 69dd72
+		return (0);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss_kex_context == NULL) {
Jan F. Chadima 69dd72
+		debug("No valid Key exchange context"); 
Jan F. Chadima 69dd72
+		return (0);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jakub Jelen 90edc0
+	if ((b = sshbuf_new()) == NULL)
Jakub Jelen 90edc0
+		fatal("%s: sshbuf_new failed", __func__);
Jakub Jelen 90edc0
+
Jakub Jelen bbf61d
+	ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
Jan F. Chadima 69dd72
+	    "gssapi-keyex");
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	gssbuf.value = sshbuf_mutable_ptr(b);
Jakub Jelen bbf61d
+	gssbuf.length = sshbuf_len(b);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
Jakub Jelen bbf61d
+		sshbuf_free(b);
Jan F. Chadima 69dd72
+		return (0);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	packet_start(SSH2_MSG_USERAUTH_REQUEST);
Jan F. Chadima 69dd72
+	packet_put_cstring(authctxt->server_user);
Jan F. Chadima 69dd72
+	packet_put_cstring(authctxt->service);
Jan F. Chadima 69dd72
+	packet_put_cstring(authctxt->method->name);
Jan F. Chadima 69dd72
+	packet_put_string(mic.value, mic.length);
Jan F. Chadima 69dd72
+	packet_send();
Jan F. Chadima 69dd72
+
Jakub Jelen bbf61d
+	sshbuf_free(b);
Jan F. Chadima 69dd72
+	gss_release_buffer(&ms, &mic);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	return (1);
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 #endif /* GSSAPI */
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 int
Jakub Jelen 5b55d0
diff -up openssh/sshd.c.gsskex openssh/sshd.c
Jakub Jelen bbf61d
--- openssh/sshd.c.gsskex	2018-08-22 11:47:33.299216360 +0200
Jakub Jelen bbf61d
+++ openssh/sshd.c	2018-08-22 13:34:28.455975954 +0200
Jakub Jelen bbf61d
@@ -887,8 +887,9 @@ notify_hostkeys(struct ssh *ssh)
Jakub Jelen 6bf47e
 	}
Jakub Jelen 3cd489
 	debug3("%s: sent %u hostkeys", __func__, nkeys);
Jakub Jelen 6bf47e
 	if (nkeys == 0)
Jakub Jelen 6bf47e
-		fatal("%s: no hostkeys", __func__);
Jakub Jelen 6bf47e
-	packet_send();
Jakub Jelen 6bf47e
+		debug3("%s: no hostkeys", __func__);
Jakub Jelen 6bf47e
+	else
Jakub Jelen 6bf47e
+		packet_send();
Jakub Jelen 6bf47e
 	sshbuf_free(buf);
Jakub Jelen 6bf47e
 }
Jakub Jelen 6bf47e
 
Jakub Jelen bbf61d
@@ -1841,7 +1842,8 @@ main(int ac, char **av)
Jakub Jelen 6cf9b8
 		free(fp);
Jan F. Chadima 69dd72
 	}
Jakub Jelen bbf61d
 	accumulate_host_timing_secret(cfg, NULL);
Jakub Jelen 6cf9b8
-	if (!sensitive_data.have_ssh2_key) {
Jan F. Chadima 69dd72
+	/* The GSSAPI key exchange can run without a host key */
Jakub Jelen 6cf9b8
+	if (!sensitive_data.have_ssh2_key && !options.gss_keyex) {
Jan F. Chadima 69dd72
 		logit("sshd: no hostkeys available -- exiting.");
Jan F. Chadima 69dd72
 		exit(1);
Jakub Jelen 6cf9b8
 	}
Jakub Jelen bbf61d
@@ -2321,6 +2323,48 @@ do_ssh2_kex(void)
Petr Lautrbach 3e1dd6
 	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
Petr Lautrbach 3e1dd6
 	    list_hostkey_types());
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	{
Jan F. Chadima 69dd72
+	char *orig;
Jan F. Chadima 69dd72
+	char *gss = NULL;
Jan F. Chadima 69dd72
+	char *newstr = NULL;
Jan F. Chadima 69dd72
+	orig = myproposal[PROPOSAL_KEX_ALGS];
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* 
Jan F. Chadima 69dd72
+	 * If we don't have a host key, then there's no point advertising
Jan F. Chadima 69dd72
+	 * the other key exchange algorithms
Jan F. Chadima 69dd72
+	 */
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
Jan F. Chadima 69dd72
+		orig = NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (options.gss_keyex)
Jan F. Chadima 69dd72
+		gss = ssh_gssapi_server_mechanisms();
Jan F. Chadima 69dd72
+	else
Jan F. Chadima 69dd72
+		gss = NULL;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (gss && orig)
Jan F. Chadima 69dd72
+		xasprintf(&newstr, "%s,%s", gss, orig);
Jan F. Chadima 69dd72
+	else if (gss)
Jan F. Chadima 69dd72
+		newstr = gss;
Jan F. Chadima 69dd72
+	else if (orig)
Jan F. Chadima 69dd72
+		newstr = orig;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* 
Jan F. Chadima 69dd72
+	 * If we've got GSSAPI mechanisms, then we've got the 'null' host
Jan F. Chadima 69dd72
+	 * key alg, but we can't tell people about it unless its the only
Jan F. Chadima 69dd72
+  	 * host key algorithm we support
Jan F. Chadima 69dd72
+	 */
Jan F. Chadima 69dd72
+	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
Jan F. Chadima 69dd72
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	if (newstr)
Jan F. Chadima 69dd72
+		myproposal[PROPOSAL_KEX_ALGS] = newstr;
Jan F. Chadima 69dd72
+	else
Jan F. Chadima 69dd72
+		fatal("No supported key exchange algorithms");
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	/* start key exchange */
Jakub Jelen 132f8f
 	if ((r = kex_setup(active_state, myproposal)) != 0)
Jakub Jelen 132f8f
 		fatal("kex_setup: %s", ssh_err(r));
Jakub Jelen bbf61d
@@ -2338,6 +2382,13 @@ do_ssh2_kex(void)
Jakub Jelen 132f8f
 # endif
Petr Lautrbach 190035
 #endif
Petr Lautrbach 3e1dd6
 	kex->kex[KEX_C25519_SHA256] = kexc25519_server;
Jan F. Chadima 69dd72
+#ifdef GSSAPI
Jan F. Chadima 69dd72
+	if (options.gss_keyex) {
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+#endif
Jan F. Chadima 69dd72
 	kex->server = 1;
Jan F. Chadima 69dd72
 	kex->client_version_string=client_version_string;
Jan F. Chadima 69dd72
 	kex->server_version_string=server_version_string;
Jakub Jelen 5b55d0
diff -up openssh/sshd_config.5.gsskex openssh/sshd_config.5
Jakub Jelen bbf61d
--- openssh/sshd_config.5.gsskex	2018-08-22 11:47:33.297216344 +0200
Jakub Jelen bbf61d
+++ openssh/sshd_config.5	2018-08-22 13:35:05.531275099 +0200
Jakub Jelen bbf61d
@@ -642,6 +642,11 @@ Specifies whether to automatically destr
Jakub Jelen 6cf9b8
 on logout.
Jan F. Chadima 69dd72
 The default is
Jakub Jelen 6cf9b8
 .Cm yes .
Jan F. Chadima 69dd72
+.It Cm GSSAPIKeyExchange
Jan F. Chadima 69dd72
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
Jan F. Chadima 69dd72
+doesn't rely on ssh keys to verify host identity.
Jan F. Chadima 69dd72
+The default is
Jan F. Chadima 69dd72
+.Dq no .
Jakub Jelen 6cf9b8
 .It Cm GSSAPIStrictAcceptorCheck
Jakub Jelen 6cf9b8
 Determines whether to be strict about the identity of the GSSAPI acceptor
Jakub Jelen 6cf9b8
 a client authenticates against.
Jakub Jelen bbf61d
@@ -656,6 +661,11 @@ machine's default store.
Jakub Jelen 535d34
 This facility is provided to assist with operation on multi homed machines.
Jan F. Chadima 69dd72
 The default is
Jakub Jelen 6cf9b8
 .Cm yes .
Jan F. Chadima 69dd72
+.It Cm GSSAPIStoreCredentialsOnRekey
Jan F. Chadima 69dd72
+Controls whether the user's GSSAPI credentials should be updated following a 
Jan F. Chadima 69dd72
+successful connection rekeying. This option can be used to accepted renewed 
Jan F. Chadima 69dd72
+or updated credentials from a compatible client. The default is
Jan F. Chadima 69dd72
+.Dq no .
Jakub Jelen 132f8f
 .It Cm HostbasedAcceptedKeyTypes
Jakub Jelen 132f8f
 Specifies the key types that will be accepted for hostbased authentication
Jakub Jelen bbf61d
 as a list of comma-separated patterns.
Jakub Jelen 5b55d0
diff -up openssh/sshd_config.gsskex openssh/sshd_config
Jakub Jelen bbf61d
--- openssh/sshd_config.gsskex	2018-08-22 11:47:33.299216360 +0200
Jakub Jelen bbf61d
+++ openssh/sshd_config	2018-08-22 11:47:33.318216513 +0200
Jakub Jelen bbf61d
@@ -85,6 +85,8 @@ ChallengeResponseAuthentication no
Jakub Jelen 535d34
 # GSSAPI options
Jakub Jelen 535d34
 GSSAPIAuthentication yes
Jakub Jelen 535d34
 GSSAPICleanupCredentials no
Jakub Jelen 535d34
+#GSSAPIStrictAcceptorCheck yes
Jakub Jelen 535d34
+#GSSAPIKeyExchange no
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 # Set this to 'yes' to enable PAM authentication, account processing,
Jakub Jelen 535d34
 # and session processing. If this is enabled, PAM authentication will
Jakub Jelen 5b55d0
diff -up openssh/ssh-gss.h.gsskex openssh/ssh-gss.h
Jakub Jelen bbf61d
--- openssh/ssh-gss.h.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/ssh-gss.h	2018-08-22 13:36:44.773075793 +0200
Jakub Jelen 535d34
@@ -1,6 +1,6 @@
Jakub Jelen bbf61d
 /* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */
Jakub Jelen 535d34
 /*
Jakub Jelen 535d34
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
Jakub Jelen 535d34
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
Jakub Jelen 535d34
  *
Jakub Jelen 535d34
  * Redistribution and use in source and binary forms, with or without
Jakub Jelen 535d34
  * modification, are permitted provided that the following conditions
Jakub Jelen 535d34
@@ -61,10 +61,22 @@
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 #define SSH_GSS_OIDTYPE 0x06
Jakub Jelen 535d34
 
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_INIT                            30
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_CONTINUE                        31
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_COMPLETE                        32
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_HOSTKEY                         33
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_ERROR                           34
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_GROUPREQ			40
Jakub Jelen 535d34
+#define SSH2_MSG_KEXGSS_GROUP				41
Jakub Jelen 535d34
+#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"
Jakub Jelen 535d34
+#define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"
Jakub Jelen 535d34
+#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"
Jakub Jelen 535d34
+
Jakub Jelen 535d34
 typedef struct {
Jakub Jelen 535d34
 	char *filename;
Jakub Jelen 535d34
 	char *envvar;
Jakub Jelen 535d34
 	char *envval;
Jakub Jelen 535d34
+	struct passwd *owner;
Jakub Jelen 535d34
 	void *data;
Jakub Jelen 535d34
 } ssh_gssapi_ccache;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
@@ -72,8 +84,11 @@ typedef struct {
Jakub Jelen 535d34
 	gss_buffer_desc displayname;
Jakub Jelen 535d34
 	gss_buffer_desc exportedname;
Jakub Jelen 535d34
 	gss_cred_id_t creds;
Jakub Jelen 535d34
+	gss_name_t name;
Jakub Jelen 535d34
 	struct ssh_gssapi_mech_struct *mech;
Jakub Jelen 535d34
 	ssh_gssapi_ccache store;
Jakub Jelen 535d34
+	int used;
Jakub Jelen 535d34
+	int updated;
Jakub Jelen 535d34
 } ssh_gssapi_client;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 typedef struct ssh_gssapi_mech_struct {
Jakub Jelen 535d34
@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct {
Jakub Jelen 535d34
 	int (*userok) (ssh_gssapi_client *, char *);
Jakub Jelen 535d34
 	int (*localname) (ssh_gssapi_client *, char **);
Jakub Jelen 535d34
 	void (*storecreds) (ssh_gssapi_client *);
Jakub Jelen 535d34
+	int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
Jakub Jelen 535d34
 } ssh_gssapi_mech;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 typedef struct {
Jakub Jelen 535d34
@@ -94,10 +110,11 @@ typedef struct {
Jakub Jelen 535d34
 	gss_OID		oid; /* client */
Jakub Jelen 535d34
 	gss_cred_id_t	creds; /* server */
Jakub Jelen 535d34
 	gss_name_t	client; /* server */
Jakub Jelen 535d34
-	gss_cred_id_t	client_creds; /* server */
Jakub Jelen 535d34
+	gss_cred_id_t	client_creds; /* both */
Jakub Jelen 535d34
 } Gssctxt;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 extern ssh_gssapi_mech *supported_mechs[];
Jakub Jelen 535d34
+extern Gssctxt *gss_kex_context;
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
Jakub Jelen 535d34
 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
Jakub Jelen bbf61d
@@ -123,17 +140,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **);
Jakub Jelen 535d34
 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
Jakub Jelen bbf61d
 void ssh_gssapi_buildmic(struct sshbuf *, const char *,
Jakub Jelen bbf61d
     const char *, const char *);
Jakub Jelen 535d34
-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
Jakub Jelen 535d34
+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
Jakub Jelen 535d34
+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
Jakub Jelen 535d34
+int ssh_gssapi_credentials_updated(Gssctxt *);
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 /* In the server */
Jakub Jelen 535d34
+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
Jakub Jelen 535d34
+    const char *);
Jakub Jelen 535d34
+char *ssh_gssapi_client_mechanisms(const char *, const char *);
Jakub Jelen 535d34
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
Jakub Jelen 535d34
+    const char *);
Jakub Jelen 535d34
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
Jakub Jelen 535d34
+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
Jakub Jelen 535d34
+    const char *);
Jakub Jelen 535d34
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
Jakub Jelen 535d34
-int ssh_gssapi_userok(char *name);
Jakub Jelen 535d34
+int ssh_gssapi_userok(char *name, struct passwd *);
Jakub Jelen 535d34
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
Jakub Jelen 535d34
 void ssh_gssapi_do_child(char ***, u_int *);
Jakub Jelen 535d34
 void ssh_gssapi_cleanup_creds(void);
Jakub Jelen 535d34
 void ssh_gssapi_storecreds(void);
Jakub Jelen 5b55d0
 const char *ssh_gssapi_displayname(void);
Jakub Jelen 535d34
 
Jakub Jelen 535d34
+char *ssh_gssapi_server_mechanisms(void);
Jakub Jelen 535d34
+int ssh_gssapi_oid_table_ok();
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
Jakub Jelen 535d34
+
Jakub Jelen 535d34
+void ssh_gssapi_rekey_creds(void);
Jakub Jelen 535d34
 #endif /* GSSAPI */
Jakub Jelen 535d34
 
Jakub Jelen 535d34
 #endif /* _SSH_GSS_H */
Jakub Jelen 5b55d0
diff -up openssh/sshkey.c.gsskex openssh/sshkey.c
Jakub Jelen bbf61d
--- openssh/sshkey.c.gsskex	2018-08-22 11:47:33.319216521 +0200
Jakub Jelen bbf61d
+++ openssh/sshkey.c	2018-08-22 13:37:18.979351804 +0200
Jakub Jelen bbf61d
@@ -140,6 +140,7 @@ static const struct keytype keytypes[] =
Jakub Jelen c6ba7b
 #  endif /* OPENSSL_HAS_NISTP521 */
Jakub Jelen c6ba7b
 # endif /* OPENSSL_HAS_ECC */
Jakub Jelen c6ba7b
 #endif /* WITH_OPENSSL */
Jakub Jelen bbf61d
+	{ "null", "null", NULL, KEY_NULL, 0, 0, 1 },
Jakub Jelen bbf61d
 	{ NULL, NULL, NULL, -1, -1, 0, 0 }
Jakub Jelen c6ba7b
 };
Jakub Jelen c6ba7b
 
Jakub Jelen 5b55d0
diff -up openssh/sshkey.h.gsskex openssh/sshkey.h
Jakub Jelen bbf61d
--- openssh/sshkey.h.gsskex	2018-08-20 07:57:29.000000000 +0200
Jakub Jelen bbf61d
+++ openssh/sshkey.h	2018-08-22 11:47:33.320216529 +0200
Jakub Jelen bbf61d
@@ -63,6 +63,7 @@ enum sshkey_types {
Jakub Jelen c6ba7b
 	KEY_ED25519_CERT,
Jakub Jelen 3cd489
 	KEY_XMSS,
Jakub Jelen 3cd489
 	KEY_XMSS_CERT,
Jakub Jelen c6ba7b
+	KEY_NULL,
Jakub Jelen c6ba7b
 	KEY_UNSPEC
Jakub Jelen c6ba7b
 };
Jakub Jelen dba154
Jakub Jelen dba154
--- openssh/sshconnect2.c.orig  2017-01-04 19:47:10.000000000 +0100
Jakub Jelen dba154
+++ openssh/sshconnect2.c       2017-01-05 04:13:08.977425272 +0100
Jakub Jelen dba154
@@ -344,7 +344,6 @@
Jakub Jelen dba154
 		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
Jakub Jelen dba154
 		xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
Jakub Jelen dba154
 		    "%s,null", orig);
Jakub Jelen dba154
-		free(gss);
Jakub Jelen dba154
 	}
Jakub Jelen dba154
 #endif
Jakub Jelen dba154
 
Jakub Jelen dba154
@@ -398,6 +397,16 @@
Jakub Jelen dba154
 	/* remove ext-info from the KEX proposals for rekeying */
Jakub Jelen dba154
 	myproposal[PROPOSAL_KEX_ALGS] =
Jakub Jelen dba154
 	    compat_kex_proposal(options.kex_algorithms);
Jakub Jelen dba154
+#ifdef GSSAPI
Jakub Jelen dba154
+	/* repair myproposal after it was crumpled by the */
Jakub Jelen dba154
+	/* ext-info removal above */
Jakub Jelen dba154
+	if (gss) {
Jakub Jelen dba154
+		orig = myproposal[PROPOSAL_KEX_ALGS];
Jakub Jelen dba154
+		xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
Jakub Jelen dba154
+		    "%s,%s", gss, orig);
Jakub Jelen dba154
+		free(gss);
Jakub Jelen dba154
+	}
Jakub Jelen dba154
+#endif
Jakub Jelen dba154
 	if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
Jakub Jelen dba154
 		fatal("kex_prop2buf: %s", ssh_err(r));
Jakub Jelen c6ba7b