summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Gysin2017-09-24 17:18:02 +0300
committerChristoph Gysin2017-09-28 00:05:41 +0300
commit708be6678084efd20ddf9e9ce4c55cfc29effcd6 (patch)
treef5ac9a7a5ef89346f80f3f4a648e969fbf4ecd7c
parente21f22ff5b23d4f99cf2878fbb07b001a1ac4dc9 (diff)
downloadaur-708be6678084efd20ddf9e9ce4c55cfc29effcd6.tar.gz
update to 7.5p1
-rw-r--r--.SRCINFO25
-rw-r--r--PKGBUILD42
-rw-r--r--get_canonical_hostname.patch388
-rw-r--r--gssapi-p0.patch36
-rw-r--r--gssapi-p2.patch10
-rw-r--r--gssapi.patch (renamed from gssapi-p1.patch)771
6 files changed, 819 insertions, 453 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 8502f152462e..cf01d2ddd67b 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,11 +1,10 @@
# Generated by mksrcinfo v8
-# Tue Sep 26 18:19:52 UTC 2017
+# Wed Sep 27 12:59:44 UTC 2017
pkgbase = openssh-gssapi
pkgdesc = Free version of the SSH connectivity tools
- pkgver = 7.1p2
- pkgrel = 2
- url = http://www.openssh.org/portable.html
- install = install
+ pkgver = 7.5p1
+ pkgrel = 1
+ url = https://www.openssh.com/portable.html
arch = i686
arch = x86_64
license = custom:BSD
@@ -21,26 +20,26 @@ pkgbase = openssh-gssapi
backup = etc/ssh/ssh_config
backup = etc/ssh/sshd_config
backup = etc/pam.d/sshd
- source = https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.1p2.tar.gz
+ source = https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz
+ source = https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz.asc
source = sshdgenkeys.service
source = sshd@.service
source = sshd.service
source = sshd.socket
source = sshd.conf
source = sshd.pam
- source = gssapi-p0.patch
- source = gssapi-p1.patch
- source = gssapi-p2.patch
- sha1sums = 9202f5a2a50c8a55ecfb830609df1e1fde97f758
+ source = get_canonical_hostname.patch
+ source = gssapi.patch
+ sha1sums = 5e8f185d00afb4f4f89801e9b0f8b9cee9d87ebd
+ sha1sums = SKIP
sha1sums = cc1ceec606c98c7407e7ac21ade23aed81e31405
sha1sums = 6a0ff3305692cf83aca96e10f3bb51e1c26fccda
sha1sums = ec49c6beba923e201505f5669cea48cad29014db
sha1sums = e12fa910b26a5634e5a6ac39ce1399a132cf6796
sha1sums = c9b2e4ce259cd62ddb00364d3ee6f00a8bf2d05f
sha1sums = d93dca5ebda4610ff7647187f8928a3de28703f3
- sha1sums = cf5aa7652259c007d581371007e4d110e486ee29
- sha1sums = b11a223eccd8832e75dc69ba5e5b3c5d8606565c
- sha1sums = 4ef9b3550107750637d2306777e472167e60653c
+ sha1sums = 16a3dc0ddcffbcfb7b166dc5839cee6536597c8e
+ sha1sums = 1f835864ef2a64d919e57c8337f711a1b9442af4
pkgname = openssh-gssapi
diff --git a/PKGBUILD b/PKGBUILD
index 694d1e442c87..35e5ff303698 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -6,10 +6,10 @@
pkgname=openssh-gssapi
_pkgname=openssh
-pkgver=7.1p2
-pkgrel=2
+pkgver=7.5p1
+pkgrel=1
pkgdesc='Free version of the SSH connectivity tools'
-url='http://www.openssh.org/portable.html'
+url='https://www.openssh.com/portable.html'
license=('custom:BSD')
arch=('i686' 'x86_64')
makedepends=('linux-headers')
@@ -19,36 +19,38 @@ depends=('krb5' 'openssl-1.0' 'libedit' 'ldns')
optdepends=('xorg-xauth: X11 forwarding'
'x11-ssh-askpass: input passphrase in X')
validpgpkeys=('59C2118ED206D927E667EBE3D3E5F56B6D920D30')
-source=("https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/${_pkgname}-${pkgver}.tar.gz"
+source=("https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/${_pkgname}-${pkgver}.tar.gz"{,.asc}
'sshdgenkeys.service'
'sshd@.service'
'sshd.service'
'sshd.socket'
'sshd.conf'
'sshd.pam'
- 'gssapi-p0.patch'
- 'gssapi-p1.patch'
- 'gssapi-p2.patch')
-sha1sums=('9202f5a2a50c8a55ecfb830609df1e1fde97f758'
+ 'get_canonical_hostname.patch'
+ 'gssapi.patch')
+sha1sums=('5e8f185d00afb4f4f89801e9b0f8b9cee9d87ebd'
+ 'SKIP'
'cc1ceec606c98c7407e7ac21ade23aed81e31405'
'6a0ff3305692cf83aca96e10f3bb51e1c26fccda'
'ec49c6beba923e201505f5669cea48cad29014db'
'e12fa910b26a5634e5a6ac39ce1399a132cf6796'
'c9b2e4ce259cd62ddb00364d3ee6f00a8bf2d05f'
'd93dca5ebda4610ff7647187f8928a3de28703f3'
- 'cf5aa7652259c007d581371007e4d110e486ee29'
- 'b11a223eccd8832e75dc69ba5e5b3c5d8606565c'
- '4ef9b3550107750637d2306777e472167e60653c')
+ '16a3dc0ddcffbcfb7b166dc5839cee6536597c8e'
+ '1f835864ef2a64d919e57c8337f711a1b9442af4')
backup=('etc/ssh/ssh_config' 'etc/ssh/sshd_config' 'etc/pam.d/sshd')
-install=install
+prepare() {
+ cd "${srcdir}/${_pkgname}-${pkgver}"
+
+ # GSSAPI patches
+ patch -Np1 -i ../get_canonical_hostname.patch
+ patch -Np1 -i ../gssapi.patch
+}
build() {
cd "${srcdir}/${_pkgname}-${pkgver}"
- patch -p1 -i ../gssapi-p0.patch
- patch -p1 -i ../gssapi-p1.patch
- patch -p1 -i ../gssapi-p2.patch
# compile against openssl-1.0
ssldir="$srcdir"/openssl-1.0
@@ -79,11 +81,13 @@ build() {
check() {
cd "${srcdir}/${_pkgname}-${pkgver}"
+ # Tests require openssh to be already installed system-wide,
+ # also connectivity tests will fail under makechrootpkg since
+ # it runs as nobody which has /bin/false as login shell.
- make tests || true
- # hard to suitably test connectivity:
- # - fails with /bin/false as login shell
- # - fails with firewall activated, etc.
+ if [[ -e /usr/bin/scp && ! -e /.arch-chroot ]]; then
+ make tests
+ fi
}
package() {
diff --git a/get_canonical_hostname.patch b/get_canonical_hostname.patch
new file mode 100644
index 000000000000..bc9697a2a2b1
--- /dev/null
+++ b/get_canonical_hostname.patch
@@ -0,0 +1,388 @@
+commit 75a930fc820eb0ab50b53824a68aea0e321e2536
+Author: Christoph Gysin <christoph.gysin@gmail.com>
+Date: Mon Sep 25 23:40:36 2017 +0300
+
+ move get_canonical_hostname back to canohost
+
+diff --git a/auth-options.c b/auth-options.c
+index 57b49f7..fbc2af2 100644
+--- a/auth-options.c
++++ b/auth-options.c
+@@ -276,7 +276,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
+ cp = "from=\"";
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+ const char *remote_ip = ssh_remote_ipaddr(ssh);
+- const char *remote_host = auth_get_canonical_hostname(
++ const char *remote_host = get_canonical_hostname(
+ ssh, options.use_dns);
+ char *patterns = xmalloc(strlen(opts) + 1);
+
+diff --git a/auth-pam.c b/auth-pam.c
+index bc8e5e0..1aa4183 100644
+--- a/auth-pam.c
++++ b/auth-pam.c
+@@ -643,7 +643,7 @@ sshpam_init(Authctxt *authctxt)
+ sshpam_handle = NULL;
+ return (-1);
+ }
+- pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns);
++ pam_rhost = get_canonical_hostname(ssh, options.use_dns);
+ debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
+ sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
+ if (sshpam_err != PAM_SUCCESS) {
+@@ -801,7 +801,7 @@ sshpam_query(void *ctx, char **name, char **info,
+ error("PAM: %s for %s%.100s from %.100s", msg,
+ sshpam_authctxt->valid ? "" : "illegal user ",
+ sshpam_authctxt->user,
+- auth_get_canonical_hostname(ssh, options.use_dns));
++ get_canonical_hostname(ssh, options.use_dns));
+ /* FALLTHROUGH */
+ default:
+ *num = 0;
+diff --git a/auth.c b/auth.c
+index 6ee6116..3cd12e6 100644
+--- a/auth.c
++++ b/auth.c
+@@ -186,7 +186,7 @@ allowed_user(struct passwd * pw)
+
+ if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
+ options.num_deny_groups > 0 || options.num_allow_groups > 0) {
+- hostname = auth_get_canonical_hostname(ssh, options.use_dns);
++ hostname = get_canonical_hostname(ssh, options.use_dns);
+ ipaddr = ssh_remote_ipaddr(ssh);
+ }
+
+@@ -328,11 +328,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
+ strncmp(method, "keyboard-interactive", 20) == 0 ||
+ strcmp(method, "challenge-response") == 0))
+ record_failed_login(authctxt->user,
+- auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
++ get_canonical_hostname(ssh, options.use_dns), "ssh");
+ # ifdef WITH_AIXAUTHENTICATE
+ if (authenticated)
+ sys_auth_record_login(authctxt->user,
+- auth_get_canonical_hostname(ssh, options.use_dns), "ssh",
++ get_canonical_hostname(ssh, options.use_dns), "ssh",
+ &loginmsg);
+ # endif
+ #endif
+@@ -663,7 +663,7 @@ getpwnamallow(const char *user)
+ user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+ #ifdef CUSTOM_FAILED_LOGIN
+ record_failed_login(user,
+- auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
++ get_canonical_hostname(ssh, options.use_dns), "ssh");
+ #endif
+ #ifdef SSH_AUDIT_EVENTS
+ audit_event(SSH_INVALID_USER);
+@@ -793,117 +793,3 @@ fakepw(void)
+
+ return (&fake);
+ }
+-
+-/*
+- * Returns the remote DNS hostname as a string. The returned string must not
+- * be freed. NB. this will usually trigger a DNS query the first time it is
+- * called.
+- * This function does additional checks on the hostname to mitigate some
+- * attacks on legacy rhosts-style authentication.
+- * XXX is RhostsRSAAuthentication vulnerable to these?
+- * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
+- */
+-
+-static char *
+-remote_hostname(struct ssh *ssh)
+-{
+- struct sockaddr_storage from;
+- socklen_t fromlen;
+- struct addrinfo hints, *ai, *aitop;
+- char name[NI_MAXHOST], ntop2[NI_MAXHOST];
+- const char *ntop = ssh_remote_ipaddr(ssh);
+-
+- /* Get IP address of client. */
+- fromlen = sizeof(from);
+- memset(&from, 0, sizeof(from));
+- if (getpeername(ssh_packet_get_connection_in(ssh),
+- (struct sockaddr *)&from, &fromlen) < 0) {
+- debug("getpeername failed: %.100s", strerror(errno));
+- return strdup(ntop);
+- }
+-
+- ipv64_normalise_mapped(&from, &fromlen);
+- if (from.ss_family == AF_INET6)
+- fromlen = sizeof(struct sockaddr_in6);
+-
+- debug3("Trying to reverse map address %.100s.", ntop);
+- /* Map the IP address to a host name. */
+- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
+- NULL, 0, NI_NAMEREQD) != 0) {
+- /* Host name not found. Use ip address. */
+- return strdup(ntop);
+- }
+-
+- /*
+- * if reverse lookup result looks like a numeric hostname,
+- * someone is trying to trick us by PTR record like following:
+- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
+- */
+- memset(&hints, 0, sizeof(hints));
+- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+- hints.ai_flags = AI_NUMERICHOST;
+- if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
+- logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
+- name, ntop);
+- freeaddrinfo(ai);
+- return strdup(ntop);
+- }
+-
+- /* Names are stored in lowercase. */
+- lowercase(name);
+-
+- /*
+- * Map it back to an IP address and check that the given
+- * address actually is an address of this host. This is
+- * necessary because anyone with access to a name server can
+- * define arbitrary names for an IP address. Mapping from
+- * name to IP address can be trusted better (but can still be
+- * fooled if the intruder has access to the name server of
+- * the domain).
+- */
+- memset(&hints, 0, sizeof(hints));
+- hints.ai_family = from.ss_family;
+- hints.ai_socktype = SOCK_STREAM;
+- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
+- logit("reverse mapping checking getaddrinfo for %.700s "
+- "[%s] failed.", name, ntop);
+- return strdup(ntop);
+- }
+- /* Look for the address from the list of addresses. */
+- for (ai = aitop; ai; ai = ai->ai_next) {
+- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
+- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
+- (strcmp(ntop, ntop2) == 0))
+- break;
+- }
+- freeaddrinfo(aitop);
+- /* If we reached the end of the list, the address was not there. */
+- if (ai == NULL) {
+- /* Address not found for the host name. */
+- logit("Address %.100s maps to %.600s, but this does not "
+- "map back to the address.", ntop, name);
+- return strdup(ntop);
+- }
+- return strdup(name);
+-}
+-
+-/*
+- * Return the canonical name of the host in the other side of the current
+- * connection. The host name is cached, so it is efficient to call this
+- * several times.
+- */
+-
+-const char *
+-auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
+-{
+- static char *dnsname;
+-
+- if (!use_dns)
+- return ssh_remote_ipaddr(ssh);
+- else if (dnsname != NULL)
+- return dnsname;
+- else {
+- dnsname = remote_hostname(ssh);
+- return dnsname;
+- }
+-}
+diff --git a/auth.h b/auth.h
+index 338a62d..17eb9d7 100644
+--- a/auth.h
++++ b/auth.h
+@@ -184,8 +184,6 @@ FILE *auth_openkeyfile(const char *, struct passwd *, int);
+ FILE *auth_openprincipals(const char *, struct passwd *, int);
+ int auth_key_is_revoked(Key *);
+
+-const char *auth_get_canonical_hostname(struct ssh *, int);
+-
+ HostStatus
+ check_key_in_hostfiles(struct passwd *, Key *, const char *,
+ const char *, const char *);
+diff --git a/auth2-hostbased.c b/auth2-hostbased.c
+index 1b3c3b2..e6d3e3d 100644
+--- a/auth2-hostbased.c
++++ b/auth2-hostbased.c
+@@ -169,7 +169,7 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
+ if (auth_key_is_revoked(key))
+ return 0;
+
+- resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
++ resolvedname = get_canonical_hostname(ssh, options.use_dns);
+ ipaddr = ssh_remote_ipaddr(ssh);
+
+ debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
+diff --git a/canohost.c b/canohost.c
+index f71a085..2d94025 100644
+--- a/canohost.c
++++ b/canohost.c
+@@ -202,3 +202,117 @@ get_local_port(int sock)
+ {
+ return get_sock_port(sock, 1);
+ }
++
++/*
++ * Returns the remote DNS hostname as a string. The returned string must not
++ * be freed. NB. this will usually trigger a DNS query the first time it is
++ * called.
++ * This function does additional checks on the hostname to mitigate some
++ * attacks on legacy rhosts-style authentication.
++ * XXX is RhostsRSAAuthentication vulnerable to these?
++ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
++ */
++
++static char *
++remote_hostname(struct ssh *ssh)
++{
++ struct sockaddr_storage from;
++ socklen_t fromlen;
++ struct addrinfo hints, *ai, *aitop;
++ char name[NI_MAXHOST], ntop2[NI_MAXHOST];
++ const char *ntop = ssh_remote_ipaddr(ssh);
++
++ /* Get IP address of client. */
++ fromlen = sizeof(from);
++ memset(&from, 0, sizeof(from));
++ if (getpeername(ssh_packet_get_connection_in(ssh),
++ (struct sockaddr *)&from, &fromlen) < 0) {
++ debug("getpeername failed: %.100s", strerror(errno));
++ return strdup(ntop);
++ }
++
++ ipv64_normalise_mapped(&from, &fromlen);
++ if (from.ss_family == AF_INET6)
++ fromlen = sizeof(struct sockaddr_in6);
++
++ debug3("Trying to reverse map address %.100s.", ntop);
++ /* Map the IP address to a host name. */
++ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
++ NULL, 0, NI_NAMEREQD) != 0) {
++ /* Host name not found. Use ip address. */
++ return strdup(ntop);
++ }
++
++ /*
++ * if reverse lookup result looks like a numeric hostname,
++ * someone is trying to trick us by PTR record like following:
++ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
++ */
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
++ hints.ai_flags = AI_NUMERICHOST;
++ if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
++ logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
++ name, ntop);
++ freeaddrinfo(ai);
++ return strdup(ntop);
++ }
++
++ /* Names are stored in lowercase. */
++ lowercase(name);
++
++ /*
++ * Map it back to an IP address and check that the given
++ * address actually is an address of this host. This is
++ * necessary because anyone with access to a name server can
++ * define arbitrary names for an IP address. Mapping from
++ * name to IP address can be trusted better (but can still be
++ * fooled if the intruder has access to the name server of
++ * the domain).
++ */
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = from.ss_family;
++ hints.ai_socktype = SOCK_STREAM;
++ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
++ logit("reverse mapping checking getaddrinfo for %.700s "
++ "[%s] failed.", name, ntop);
++ return strdup(ntop);
++ }
++ /* Look for the address from the list of addresses. */
++ for (ai = aitop; ai; ai = ai->ai_next) {
++ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
++ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
++ (strcmp(ntop, ntop2) == 0))
++ break;
++ }
++ freeaddrinfo(aitop);
++ /* If we reached the end of the list, the address was not there. */
++ if (ai == NULL) {
++ /* Address not found for the host name. */
++ logit("Address %.100s maps to %.600s, but this does not "
++ "map back to the address.", ntop, name);
++ return strdup(ntop);
++ }
++ return strdup(name);
++}
++
++/*
++ * Return the canonical name of the host in the other side of the current
++ * connection. The host name is cached, so it is efficient to call this
++ * several times.
++ */
++
++const char *
++get_canonical_hostname(struct ssh *ssh, int use_dns)
++{
++ static char *dnsname;
++
++ if (!use_dns)
++ return ssh_remote_ipaddr(ssh);
++ else if (dnsname != NULL)
++ return dnsname;
++ else {
++ dnsname = remote_hostname(ssh);
++ return dnsname;
++ }
++}
+diff --git a/canohost.h b/canohost.h
+index 26d6285..626d708 100644
+--- a/canohost.h
++++ b/canohost.h
+@@ -15,6 +15,8 @@
+ #ifndef _CANOHOST_H
+ #define _CANOHOST_H
+
++struct ssh;
++
+ char *get_peer_ipaddr(int);
+ int get_peer_port(int);
+ char *get_local_ipaddr(int);
+@@ -24,3 +26,5 @@ int get_local_port(int);
+ #endif /* _CANOHOST_H */
+
+ void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
++
++const char *get_canonical_hostname(struct ssh *, int);
+diff --git a/servconf.c b/servconf.c
+index 56b8316..0955ef7 100644
+--- a/servconf.c
++++ b/servconf.c
+@@ -700,7 +700,7 @@ get_connection_info(int populate, int use_dns)
+
+ if (!populate)
+ return &ci;
+- ci.host = auth_get_canonical_hostname(ssh, use_dns);
++ ci.host = get_canonical_hostname(ssh, use_dns);
+ ci.address = ssh_remote_ipaddr(ssh);
+ ci.laddress = ssh_local_ipaddr(ssh);
+ ci.lport = ssh_local_port(ssh);
+diff --git a/session.c b/session.c
+index a08aa69..5aa6f4b 100644
+--- a/session.c
++++ b/session.c
+@@ -2572,7 +2572,7 @@ session_get_remote_name_or_ip(struct ssh *ssh, u_int utmp_size, int use_dns)
+ const char *remote = "";
+
+ if (utmp_size > 0)
+- remote = auth_get_canonical_hostname(ssh, use_dns);
++ remote = get_canonical_hostname(ssh, use_dns);
+ if (utmp_size == 0 || strlen(remote) > utmp_size)
+ remote = ssh_remote_ipaddr(ssh);
+ return remote;
diff --git a/gssapi-p0.patch b/gssapi-p0.patch
deleted file mode 100644
index 14e473d18b8a..000000000000
--- a/gssapi-p0.patch
+++ /dev/null
@@ -1,36 +0,0 @@
---- a/sshconnect2.c.orig 2015-10-26 09:44:28.602338321 +0100
-+++ b/sshconnect2.c 2015-10-26 09:43:53.394738805 +0100
-@@ -160,9 +160,33 @@
- struct kex *kex;
- int r;
-
-+#ifdef GSSAPI
-+ char *orig = NULL, *gss = NULL;
-+ char *gss_host = NULL;
-+#endif
-+
- xxx_host = host;
- xxx_hostaddr = hostaddr;
-
-+#ifdef GSSAPI
-+if (options.gss_keyex) {
-+ /* Add the GSSAPI mechanisms currently supported on this
-+ * client to the key exchange algorithm proposal */
-+ orig = options.kex_algorithms;
-+ if (options.gss_trust_dns)
-+ gss_host = (char *)get_canonical_hostname(1);
-+ else
-+ gss_host = host;
-+
-+ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
-+ if (gss) {
-+ debug("Offering GSSAPI proposal: %s", gss);
-+ xasprintf(&options.kex_algorithms, "%s,%s", gss, orig);
-+ }
-+}
-+#endif
-+
-+
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- options.kex_algorithms);
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
diff --git a/gssapi-p2.patch b/gssapi-p2.patch
deleted file mode 100644
index 5e51fd4d673c..000000000000
--- a/gssapi-p2.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/sshkey.h.orig 2015-10-26 09:32:42.957272377 +0100
-+++ b/sshkey.h 2015-10-26 09:32:53.654341503 +0100
-@@ -62,6 +62,7 @@
- KEY_DSA_CERT,
- KEY_ECDSA_CERT,
- KEY_ED25519_CERT,
-+ KEY_NULL,
- KEY_UNSPEC
- };
-
diff --git a/gssapi-p1.patch b/gssapi.patch
index e3b384e91109..539301207d35 100644
--- a/gssapi-p1.patch
+++ b/gssapi.patch
@@ -1,81 +1,29 @@
-From 5d3dc7ea4c96cab9483d5389a3b04163771fdee2 Mon Sep 17 00:00:00 2001
-From: Simon Wilkinson <simon@sxw.org.uk>
-Date: Sun, 9 Feb 2014 16:09:48 +0000
-Subject: GSSAPI key exchange support
+commit ef9608da67e2c6e2c1bb869c5ec4b3900fef8c16
+Author: Christoph Gysin <christoph.gysin@gmail.com>
+Date: Wed Sep 27 15:49:41 2017 +0300
-This patch has been rejected upstream: "None of the OpenSSH developers are
-in favour of adding this, and this situation has not changed for several
-years. This is not a slight on Simon's patch, which is of fine quality, but
-just that a) we don't trust GSSAPI implementations that much and b) we don't
-like adding new KEX since they are pre-auth attack surface. This one is
-particularly scary, since it requires hooks out to typically root-owned
-system resources."
-
-However, quite a lot of people rely on this in Debian, and it's better to
-have it merged into the main openssh package rather than having separate
--krb5 packages (as we used to have). It seems to have a generally good
-security history.
-
-Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
-Last-Updated: 2015-08-19
-
-Patch-Name: gssapi.patch
----
- ChangeLog.gssapi | 113 +++++++++++++++++++
- Makefile.in | 5 +-
- auth-krb5.c | 17 ++-
- auth2-gss.c | 48 +++++++-
- auth2.c | 2 +
- clientloop.c | 13 +++
- config.h.in | 6 +
- configure.ac | 24 ++++
- gss-genr.c | 275 ++++++++++++++++++++++++++++++++++++++++++++-
- gss-serv-krb5.c | 85 ++++++++++++--
- gss-serv.c | 185 +++++++++++++++++++++++++++---
- kex.c | 16 +++
- kex.h | 14 +++
- kexgssc.c | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
- kexgsss.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++
- monitor.c | 108 +++++++++++++++++-
- monitor.h | 3 +
- monitor_wrap.c | 47 +++++++-
- monitor_wrap.h | 4 +-
- readconf.c | 42 +++++++
- readconf.h | 5 +
- servconf.c | 28 ++++-
- servconf.h | 2 +
- ssh-gss.h | 41 ++++++-
- ssh_config | 2 +
- ssh_config.5 | 34 +++++-
- sshconnect2.c | 124 +++++++++++++++++++-
- sshd.c | 110 ++++++++++++++++++
- sshd_config | 2 +
- sshd_config.5 | 11 ++
- sshkey.c | 3 +-
- sshkey.h | 1 +
- 32 files changed, 1955 insertions(+), 46 deletions(-)
- create mode 100644 ChangeLog.gssapi
- create mode 100644 kexgssc.c
- create mode 100644 kexgsss.c
+ gssapi
diff --git a/ChangeLog.gssapi b/ChangeLog.gssapi
new file mode 100644
-index 0000000..f117a33
+index 0000000..ec6f2ee
--- /dev/null
+++ b/ChangeLog.gssapi
-@@ -0,0 +1,113 @@
+@@ -0,0 +1,115 @@
++20170925
++ - Update to OpenSSH 7.5p1
++
+20110101
+ - Finally update for OpenSSH 5.6p1
+ - Add GSSAPIServerIdentity option from Jim Basney
-+
++
+20100308
+ - [ Makefile.in, key.c, key.h ]
+ Updates for OpenSSH 5.4p1
+ - [ servconf.c ]
+ Include GSSAPI options in the sshd -T configuration dump, and flag
-+ some older configuration options as being unsupported. Thanks to Colin
++ some older configuration options as being unsupported. Thanks to Colin
+ Watson.
-+ -
+
+20100124
+ - [ sshconnect2.c ]
@@ -86,15 +34,15 @@ index 0000000..f117a33
+ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
+ sshd.c ]
+ Fix issues identified by Greg Hudson following a code review
-+ Check return value of gss_indicate_mechs
-+ Protect GSSAPI calls in monitor, so they can only be used if enabled
-+ Check return values of bignum functions in key exchange
-+ Use BN_clear_free to clear other side's DH value
-+ Make ssh_gssapi_id_kex more robust
-+ Only configure kex table pointers if GSSAPI is enabled
-+ Don't leak mechanism list, or gss mechanism list
-+ Cast data.length before printing
-+ If serverkey isn't provided, use an empty string, rather than NULL
++ Check return value of gss_indicate_mechs
++ Protect GSSAPI calls in monitor, so they can only be used if enabled
++ Check return values of bignum functions in key exchange
++ Use BN_clear_free to clear other side's DH value
++ Make ssh_gssapi_id_kex more robust
++ Only configure kex table pointers if GSSAPI is enabled
++ Don't leak mechanism list, or gss mechanism list
++ Cast data.length before printing
++ If serverkey isn't provided, use an empty string, rather than NULL
+
+20090201
+ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
@@ -110,12 +58,12 @@ index 0000000..f117a33
+
+20070317
+ - [ gss-serv-krb5.c ]
-+ Remove C99ism, where new_ccname was being declared in the middle of a
++ Remove C99ism, where new_ccname was being declared in the middle of a
+ function
+
+20061220
+ - [ servconf.c ]
-+ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
++ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
+ documented, behaviour. Reported by Dan Watson.
+
+20060910
@@ -136,12 +84,12 @@ index 0000000..f117a33
+20060909
+ - [ gss-genr.c gss-serv.c ]
+ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
-+ only, where they belong
++ only, where they belong
+ <Bugzilla #1225>
+
+20060829
+ - [ gss-serv-krb5.c ]
-+ Fix CCAPI credentials cache name when creating KRB5CCNAME environment
++ Fix CCAPI credentials cache name when creating KRB5CCNAME environment
+ variable
+
+20060828
@@ -151,13 +99,13 @@ index 0000000..f117a33
+
+20060818
+ - [ gss-genr.c ssh-gss.h sshconnect2.c ]
-+ Make sure that SPENGO is disabled
++ Make sure that SPENGO is disabled
+ <Bugzilla #1218 - Fixed upstream 20060818>
+
+20060421
+ - [ gssgenr.c, sshconnect2.c ]
+ a few type changes (signed versus unsigned, int versus size_t) to
-+ fix compiler errors/warnings
++ fix compiler errors/warnings
+ (from jbasney AT ncsa.uiuc.edu)
+ - [ kexgssc.c, sshconnect2.c ]
+ fix uninitialized variable warnings
@@ -170,7 +118,7 @@ index 0000000..f117a33
+ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
+ (from jbasney AT ncsa.uiuc.edu)
+ <Fixed upstream 20060304>
-+ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
++ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
+ add client-side GssapiKeyExchange option
+ (from jbasney AT ncsa.uiuc.edu)
+ - [ sshconnect2.c ]
@@ -178,33 +126,31 @@ index 0000000..f117a33
+ (from jbasney AT ncsa.uiuc.edu)
+ <gssapi-with-mic support is Bugzilla #1008>
diff --git a/Makefile.in b/Makefile.in
-index 40cc7aa..3d2a328 100644
+index 5870e9e..6b774c1 100644
--- a/Makefile.in
+++ b/Makefile.in
-@@ -91,7 +91,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
- sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
+@@ -92,6 +92,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
-- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o
-+ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
-+ kexgssc.o
+ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
++ kexgssc.o \
+ platform-pledge.o platform-tracing.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
- sshconnect.o sshconnect1.o sshconnect2.o mux.o \
-@@ -105,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+@@ -105,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
- monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \
+ monitor.o monitor_wrap.o auth-krb5.o \
- auth2-gss.o gss-serv.o gss-serv-krb5.o \
+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
- roaming_common.o roaming_serv.o \
+ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
diff --git a/auth-krb5.c b/auth-krb5.c
-index 0089b18..ec47869 100644
+index a5a81ed..1fd6190 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
-@@ -183,8 +183,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
+@@ -182,8 +182,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
len = strlen(authctxt->krb5_ticket_file) + 6;
authctxt->krb5_ccname = xmalloc(len);
@@ -218,7 +164,16 @@ index 0089b18..ec47869 100644
#ifdef USE_PAM
if (options.use_pam)
-@@ -241,15 +246,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
+@@ -192,7 +197,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
+
+ out:
+ restore_uid();
+-
++
+ free(platform_client);
+
+ if (problem) {
+@@ -240,15 +245,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
#ifndef HEIMDAL
krb5_error_code
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
@@ -243,7 +198,7 @@ index 0089b18..ec47869 100644
old_umask = umask(0177);
tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
-@@ -266,6 +278,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
+@@ -265,6 +277,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
return oerrno;
}
close(tmpfd);
@@ -252,7 +207,7 @@ index 0089b18..ec47869 100644
return (krb5_cc_resolve(ctx, ccname, ccache));
}
diff --git a/auth2-gss.c b/auth2-gss.c
-index 1ca8357..3b5036d 100644
+index 1ca8357..43a466f 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -1,7 +1,7 @@
@@ -268,7 +223,7 @@ index 1ca8357..3b5036d 100644
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_errtok(int, u_int32_t, void *);
-+/*
++/*
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
@@ -291,11 +246,11 @@ index 1ca8357..3b5036d 100644
+ gssbuf.length = buffer_len(&b);
+
+ /* gss_kex_context is NULL with privsep, so we can't check it here */
-+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
+ &gssbuf, &mic))))
+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+ authctxt->pw));
-+
++
+ buffer_free(&b);
+ free(mic.value);
+
@@ -320,7 +275,7 @@ index 1ca8357..3b5036d 100644
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
-+ authenticated =
++ authenticated =
+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
else
logit("GSSAPI MIC check failed");
@@ -339,7 +294,7 @@ index 1ca8357..3b5036d 100644
"gssapi-with-mic",
userauth_gssapi,
diff --git a/auth2.c b/auth2.c
-index 7177962..3f49bdc 100644
+index 97dd2ef..946e923 100644
--- a/auth2.c
+++ b/auth2.c
@@ -70,6 +70,7 @@ extern Authmethod method_passwd;
@@ -359,10 +314,10 @@ index 7177962..3f49bdc 100644
#endif
&method_passwd,
diff --git a/clientloop.c b/clientloop.c
-index dc0e557..77d5498 100644
+index 0648162..57ed7a3 100644
--- a/clientloop.c
+++ b/clientloop.c
-@@ -114,6 +114,10 @@
+@@ -113,6 +113,10 @@
#include "ssherr.h"
#include "hostfile.h"
@@ -373,27 +328,26 @@ index dc0e557..77d5498 100644
/* import options */
extern Options options;
-@@ -1609,6 +1613,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
- /* Do channel operations unless rekeying in progress. */
- if (!rekeying) {
+@@ -1667,6 +1671,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
+ if (!ssh_packet_is_rekeying(active_state))
channel_after_select(readset, writeset);
-+
+
+#ifdef GSSAPI
-+ if (options.gss_renewal_rekey &&
-+ ssh_gssapi_credentials_updated(NULL)) {
-+ debug("credentials updated - forcing rekey");
-+ need_rekeying = 1;
-+ }
++ if (options.gss_renewal_rekey &&
++ ssh_gssapi_credentials_updated(NULL)) {
++ debug("credentials updated - forcing rekey");
++ need_rekeying = 1;
++ }
+#endif
+
- if (need_rekeying || packet_need_rekeying()) {
- debug("need rekeying");
- active_state->kex->done = 0;
+ /* Buffer input from the connection. */
+ client_process_net_input(readset);
+
diff --git a/config.h.in b/config.h.in
-index 7e7e38e..6c7de98 100644
+index b65420e..1820898 100644
--- a/config.h.in
+++ b/config.h.in
-@@ -1623,6 +1623,9 @@
+@@ -1670,6 +1670,9 @@
/* Use btmp to log bad logins */
#undef USE_BTMP
@@ -403,9 +357,9 @@ index 7e7e38e..6c7de98 100644
/* Use libedit for sftp */
#undef USE_LIBEDIT
-@@ -1638,6 +1641,9 @@
- /* Use PIPES instead of a socketpair() */
- #undef USE_PIPES
+@@ -1688,6 +1691,9 @@
+ /* Define if you have Solaris privileges */
+ #undef USE_SOLARIS_PRIVS
+/* platform has the Security Authorization Session API */
+#undef USE_SECURITY_SESSION_API
@@ -414,10 +368,10 @@ index 7e7e38e..6c7de98 100644
#undef USE_SOLARIS_PROCESS_CONTRACTS
diff --git a/configure.ac b/configure.ac
-index bb0095f..df21693 100644
+index c2878e3..98b5ab5 100644
--- a/configure.ac
+++ b/configure.ac
-@@ -625,6 +625,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
+@@ -623,6 +623,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
[Use tunnel device compatibility to OpenBSD])
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
@@ -425,7 +379,7 @@ index bb0095f..df21693 100644
+ AC_TRY_COMPILE([#include <Security/AuthSession.h>],
+ [SessionCreate(0, 0);],
+ [ac_cv_use_security_session_api="yes"
-+ AC_DEFINE([USE_SECURITY_SESSION_API], [1],
++ AC_DEFINE([USE_SECURITY_SESSION_API], [1],
+ [platform has the Security Authorization Session API])
+ LIBS="$LIBS -framework Security"
+ AC_MSG_RESULT([yes])],
@@ -436,7 +390,7 @@ index bb0095f..df21693 100644
+ [#include <Kerberos/Kerberos.h>],
+ [cc_context_t c;
+ (void) cc_initialize (&c, 0, NULL, NULL);],
-+ [AC_DEFINE([USE_CCAPI], [1],
++ [AC_DEFINE([USE_CCAPI], [1],
+ [platform uses an in-memory credentials cache])
+ LIBS="$LIBS -framework Security"
+ AC_MSG_RESULT([yes])
@@ -446,14 +400,14 @@ index bb0095f..df21693 100644
+ [AC_MSG_RESULT([no])]
+ )
m4_pattern_allow([AU_IPv])
- AC_CHECK_DECL([AU_IPv4], [],
+ AC_CHECK_DECL([AU_IPv4], [],
AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
diff --git a/gss-genr.c b/gss-genr.c
-index d617d60..b4eca3f 100644
+index 62559ed..0a929bc 100644
--- a/gss-genr.c
+++ b/gss-genr.c
@@ -1,7 +1,7 @@
- /* $OpenBSD: gss-genr.c,v 1.23 2015/01/20 23:14:00 deraadt Exp $ */
+ /* $OpenBSD: gss-genr.c,v 1.24 2016/09/12 01:22:38 deraadt Exp $ */
/*
- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
@@ -461,7 +415,7 @@ index d617d60..b4eca3f 100644
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
-@@ -41,12 +41,167 @@
+@@ -40,12 +40,167 @@
#include "buffer.h"
#include "log.h"
#include "ssh2.h"
@@ -489,7 +443,7 @@ index d617d60..b4eca3f 100644
+
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
+
-+int
++int
+ssh_gssapi_oid_table_ok(void) {
+ return (gss_enc2oid != NULL);
+}
@@ -562,7 +516,7 @@ index d617d60..b4eca3f 100644
+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
+ buffer_append(&buf, encoded, enclen);
+ buffer_put_char(&buf, ',');
-+ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID,
++ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID,
+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
+ buffer_append(&buf, encoded, enclen);
+ buffer_put_char(&buf, ',');
@@ -588,14 +542,14 @@ index d617d60..b4eca3f 100644
+ free(mechs);
+ mechs = NULL;
+ }
-+
++
+ return (mechs);
+}
+
+gss_OID
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
+ int i = 0;
-+
++
+ switch (kex_type) {
+ case KEX_GSS_GRP1_SHA1:
+ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
@@ -629,7 +583,7 @@ index d617d60..b4eca3f 100644
/* Check that the OID in a data stream matches that in the context */
int
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
-@@ -199,7 +354,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
+@@ -198,7 +353,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
}
ctx->major = gss_init_sec_context(&ctx->minor,
@@ -638,10 +592,11 @@ index d617d60..b4eca3f 100644
GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
0, NULL, recv_tok, NULL, send_tok, flags, NULL);
-@@ -229,8 +384,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
+@@ -227,9 +382,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
+ return (ctx->major);
}
- OM_uint32
++OM_uint32
+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
+{
+ gss_buffer_desc gssbuf;
@@ -659,8 +614,8 @@ index d617d60..b4eca3f 100644
+ GSS_C_NT_USER_NAME, &gssname);
+
+ if (!ctx->major)
-+ ctx->major = gss_acquire_cred(&ctx->minor,
-+ gssname, 0, oidset, GSS_C_INITIATE,
++ ctx->major = gss_acquire_cred(&ctx->minor,
++ gssname, 0, oidset, GSS_C_INITIATE,
+ &ctx->client_creds, NULL, NULL);
+
+ gss_release_name(&status, &gssname);
@@ -672,16 +627,16 @@ index d617d60..b4eca3f 100644
+ return(ctx->major);
+}
+
-+OM_uint32
+ OM_uint32
ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
{
-+ if (ctx == NULL)
++ if (ctx == NULL)
+ return -1;
+
if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
GSS_C_QOP_DEFAULT, buffer, hash)))
ssh_gssapi_error(ctx);
-@@ -238,6 +427,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
+@@ -237,6 +426,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
return (ctx->major);
}
@@ -701,12 +656,12 @@ index d617d60..b4eca3f 100644
void
ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
const char *context)
-@@ -251,11 +453,16 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
+@@ -250,22 +452,31 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
}
int
-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
-+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host,
++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host,
+ const char *client)
{
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
@@ -718,8 +673,11 @@ index d617d60..b4eca3f 100644
+ ctx = &intctx;
/* RFC 4462 says we MUST NOT do SPNEGO */
- if (oid->length == spnego_oid.length &&
-@@ -265,6 +472,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+- if (oid->length == spnego_oid.length &&
++ if (oid->length == spnego_oid.length &&
+ (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0))
+ return 0; /* false */
+
ssh_gssapi_build_ctx(ctx);
ssh_gssapi_set_oid(*ctx, oid);
major = ssh_gssapi_import_name(*ctx, host);
@@ -728,14 +686,17 @@ index d617d60..b4eca3f 100644
+ major = ssh_gssapi_client_identity(*ctx, client);
+
if (!GSS_ERROR(major)) {
- major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
+- major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
++ major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
NULL);
-@@ -274,10 +485,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+ gss_release_buffer(&minor, &token);
+ if ((*ctx)->context != GSS_C_NO_CONTEXT)
+@@ -273,10 +484,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
GSS_C_NO_BUFFER);
}
- if (GSS_ERROR(major))
-+ if (GSS_ERROR(major) || intctx != NULL)
++ if (GSS_ERROR(major) || intctx != NULL)
ssh_gssapi_delete_ctx(ctx);
return (!GSS_ERROR(major));
@@ -779,7 +740,7 @@ index d617d60..b4eca3f 100644
+ if (saved_mech == GSS_C_NO_OID)
+ return 0;
+
-+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
+ &name, &lifetime, NULL, NULL);
+ if (major == GSS_S_CREDENTIALS_EXPIRED)
+ return 0;
@@ -799,7 +760,7 @@ index d617d60..b4eca3f 100644
+
#endif /* GSSAPI */
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
-index 795992d..fd8b371 100644
+index 795992d..93c38d0 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -1,7 +1,7 @@
@@ -847,7 +808,7 @@ index 795992d..fd8b371 100644
}
+int
-+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
+ ssh_gssapi_client *client)
+{
+ krb5_ccache ccache = NULL;
@@ -856,14 +817,14 @@ index 795992d..fd8b371 100644
+ krb5_error_code problem;
+ OM_uint32 maj_status, min_status;
+
-+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
-+ logit("krb5_cc_resolve(): %.100s",
-+ krb5_get_err_text(krb_context, problem));
-+ return 0;
-+ }
-+
++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
++ logit("krb5_cc_resolve(): %.100s",
++ krb5_get_err_text(krb_context, problem));
++ return 0;
++ }
++
+ /* Find out who the principal in this cache is */
-+ if ((problem = krb5_cc_get_principal(krb_context, ccache,
++ if ((problem = krb5_cc_get_principal(krb_context, ccache,
+ &principal))) {
+ logit("krb5_cc_get_principal(): %.100s",
+ krb5_get_err_text(krb_context, problem));
@@ -925,7 +886,7 @@ index 795992d..fd8b371 100644
#endif /* KRB5 */
diff --git a/gss-serv.c b/gss-serv.c
-index 53993d6..2f6baf7 100644
+index 53993d6..481e347 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -1,7 +1,7 @@
@@ -962,10 +923,11 @@ index 53993d6..2f6baf7 100644
#ifdef KRB5
extern ssh_gssapi_mech gssapi_kerberos_mech;
-@@ -142,6 +147,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
+@@ -141,6 +146,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
+ return (ssh_gssapi_acquire_cred(*ctx));
}
- /* Unprivileged */
++/* Unprivileged */
+char *
+ssh_gssapi_server_mechanisms(void) {
+ gss_OID_set supported;
@@ -981,17 +943,16 @@ index 53993d6..2f6baf7 100644
+ const char *dummy) {
+ Gssctxt *ctx = NULL;
+ int res;
-+
++
+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
+ ssh_gssapi_delete_ctx(&ctx);
+
+ return (res);
+}
+
-+/* Unprivileged */
+ /* Unprivileged */
void
ssh_gssapi_supported_oids(gss_OID_set *oidset)
- {
@@ -151,7 +179,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset)
gss_OID_set supported;
@@ -1010,7 +971,8 @@ index 53993d6..2f6baf7 100644
+ int equal = 0;
+ gss_name_t new_name = GSS_C_NO_NAME;
+ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
-+
+
+- gss_buffer_desc ename;
+ if (options.gss_store_rekey && client->used && ctx->client_creds) {
+ if (client->mech->oid.length != ctx->oid->length ||
+ (memcmp(client->mech->oid.elements,
@@ -1019,27 +981,26 @@ index 53993d6..2f6baf7 100644
+ return GSS_S_COMPLETE;
+ }
+
-+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
-+ ctx->client_creds, ctx->oid, &new_name,
++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
++ ctx->client_creds, ctx->oid, &new_name,
+ NULL, NULL, NULL))) {
+ ssh_gssapi_error(ctx);
+ return (ctx->major);
+ }
+
-+ ctx->major = gss_compare_name(&ctx->minor, client->name,
++ ctx->major = gss_compare_name(&ctx->minor, client->name,
+ new_name, &equal);
+
+ if (GSS_ERROR(ctx->major)) {
+ ssh_gssapi_error(ctx);
+ return (ctx->major);
+ }
-+
++
+ if (!equal) {
+ debug("Rekeyed credentials have different name");
+ return GSS_S_COMPLETE;
+ }
-
-- gss_buffer_desc ename;
++
+ debug("Marking rekeyed credentials for export");
+
+ gss_release_name(&ctx->minor, &client->name);
@@ -1106,27 +1067,28 @@ index 53993d6..2f6baf7 100644
-/* Privileged */
-OM_uint32
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
-+/* These bits are only used for rekeying. The unpriviledged child is running
+-{
+- ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+- gssbuf, gssmic, NULL);
++/* These bits are only used for rekeying. The unpriviledged child is running
+ * as the user, the monitor is root.
+ *
+ * In the child, we want to :
+ * *) Ask the monitor to store our credentials into the store we specify
+ * *) If it succeeds, maybe do a PAM update
+ */
-+
+
+- return (ctx->major);
+/* Stuff for PAM */
+
+#ifdef USE_PAM
-+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg,
++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
- {
-- ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-- gssbuf, gssmic, NULL);
++{
+ return (PAM_CONV_ERR);
+}
+#endif
-
-- return (ctx->major);
++
+void
+ssh_gssapi_rekey_creds(void) {
+ int ok;
@@ -1137,11 +1099,11 @@ index 53993d6..2f6baf7 100644
+ char *envstr;
+#endif
+
-+ if (gssapi_client.store.filename == NULL &&
++ if (gssapi_client.store.filename == NULL &&
+ gssapi_client.store.envval == NULL &&
+ gssapi_client.store.envvar == NULL)
+ return;
-+
++
+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
+
+ if (!ok)
@@ -1164,7 +1126,7 @@ index 53993d6..2f6baf7 100644
+ if (ret)
+ return;
+
-+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar,
++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar,
+ gssapi_client.store.envval);
+
+ ret = pam_putenv(pamh, envstr);
@@ -1174,7 +1136,7 @@ index 53993d6..2f6baf7 100644
+#endif
+}
+
-+int
++int
+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
+ int ok = 0;
+
@@ -1197,10 +1159,10 @@ index 53993d6..2f6baf7 100644
#endif
diff --git a/kex.c b/kex.c
-index dbc55ef..4d8e6f5 100644
+index cf4ac0d..09f5d83 100644
--- a/kex.c
+++ b/kex.c
-@@ -55,6 +55,10 @@
+@@ -54,6 +54,10 @@
#include "sshbuf.h"
#include "digest.h"
@@ -1211,7 +1173,7 @@ index dbc55ef..4d8e6f5 100644
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
# if defined(HAVE_EVP_SHA256)
# define evp_ssh_sha256 EVP_sha256
-@@ -97,6 +101,14 @@ static const struct kexalg kexalgs[] = {
+@@ -113,6 +117,14 @@ static const struct kexalg kexalgs[] = {
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
{ NULL, -1, -1, -1},
};
@@ -1226,7 +1188,7 @@ index dbc55ef..4d8e6f5 100644
char *
kex_alg_list(char sep)
-@@ -129,6 +141,10 @@ kex_alg_by_name(const char *name)
+@@ -145,6 +157,10 @@ kex_alg_by_name(const char *name)
if (strcmp(k->name, name) == 0)
return k;
}
@@ -1238,10 +1200,10 @@ index dbc55ef..4d8e6f5 100644
}
diff --git a/kex.h b/kex.h
-index f70b81f..7194b14 100644
+index 3794f21..fd56171 100644
--- a/kex.h
+++ b/kex.h
-@@ -93,6 +93,9 @@ enum kex_exchange {
+@@ -99,6 +99,9 @@ enum kex_exchange {
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_C25519_SHA256,
@@ -1251,7 +1213,7 @@ index f70b81f..7194b14 100644
KEX_MAX
};
-@@ -139,6 +142,12 @@ struct kex {
+@@ -147,6 +150,12 @@ struct kex {
u_int flags;
int hash_alg;
int ec_nid;
@@ -1263,8 +1225,8 @@ index f70b81f..7194b14 100644
+#endif
char *client_version_string;
char *server_version_string;
- int (*verify_host_key)(struct sshkey *, struct ssh *);
-@@ -184,6 +193,11 @@ int kexecdh_server(struct ssh *);
+ char *failed_choice;
+@@ -197,6 +206,11 @@ int kexecdh_server(struct ssh *);
int kexc25519_client(struct ssh *);
int kexc25519_server(struct ssh *);
@@ -1273,15 +1235,15 @@ index f70b81f..7194b14 100644
+int kexgss_server(struct ssh *);
+#endif
+
- int kex_dh_hash(const char *, const char *,
+ int kex_dh_hash(int, const char *, const char *,
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
diff --git a/kexgssc.c b/kexgssc.c
new file mode 100644
-index 0000000..a49bac2
+index 0000000..4708fd0
--- /dev/null
+++ b/kexgssc.c
-@@ -0,0 +1,336 @@
+@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+ *
@@ -1337,11 +1299,11 @@ index 0000000..a49bac2
+ Gssctxt *ctxt;
+ OM_uint32 maj_status, min_status, ret_flags;
+ u_int klen, kout, slen = 0, strlen;
-+ DH *dh;
++ DH *dh;
+ BIGNUM *dh_server_pub = NULL;
+ BIGNUM *shared_secret = NULL;
+ BIGNUM *p = NULL;
-+ BIGNUM *g = NULL;
++ BIGNUM *g = NULL;
+ u_char *kbuf;
+ u_char *serverhostkey = NULL;
+ u_char *empty = "";
@@ -1352,16 +1314,16 @@ index 0000000..a49bac2
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t hashlen;
+
-+ /* Initialise our GSSAPI world */
++ /* Initialise our GSSAPI world */
+ ssh_gssapi_build_ctx(&ctxt);
-+ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type)
++ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type)
+ == GSS_C_NO_OID)
+ fatal("Couldn't identify host exchange");
+
+ if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host))
+ fatal("Couldn't import hostname");
+
-+ if (ssh->kex->gss_client &&
++ if (ssh->kex->gss_client &&
+ ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client))
+ fatal("Couldn't acquire client credentials");
+
@@ -1401,7 +1363,7 @@ index 0000000..a49bac2
+ default:
+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
+ }
-+
++
+ /* Step 1 - e is dh->pub_key */
+ dh_gen_key(dh, ssh->kex->we_need * 8);
+
@@ -1411,10 +1373,10 @@ index 0000000..a49bac2
+ fatal("dh_server_pub == NULL");
+
+ token_ptr = GSS_C_NO_BUFFER;
-+
++
+ do {
+ debug("Calling gss_init_sec_context");
-+
++
+ maj_status = ssh_gssapi_init_ctx(ctxt,
+ ssh->kex->gss_deleg_creds, token_ptr, &send_tok,
+ &ret_flags);
@@ -1442,9 +1404,9 @@ index 0000000..a49bac2
+ fatal("Integrity check failed");
+ }
+
-+ /*
++ /*
+ * If we have data to send, then the last message that we
-+ * received cannot have been a 'complete'.
++ * received cannot have been a 'complete'.
+ */
+ if (send_tok.length != 0) {
+ if (first) {
@@ -1462,13 +1424,13 @@ index 0000000..a49bac2
+ gss_release_buffer(&min_status, &send_tok);
+
+ /* If we've sent them data, they should reply */
-+ do {
++ do {
+ type = packet_read();
+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
+ debug("Received KEXGSS_HOSTKEY");
+ if (serverhostkey)
+ fatal("Server host key received more than once");
-+ serverhostkey =
++ serverhostkey =
+ packet_get_string(&slen);
+ }
+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
@@ -1476,16 +1438,16 @@ index 0000000..a49bac2
+ switch (type) {
+ case SSH2_MSG_KEXGSS_CONTINUE:
+ debug("Received GSSAPI_CONTINUE");
-+ if (maj_status == GSS_S_COMPLETE)
++ if (maj_status == GSS_S_COMPLETE)
+ fatal("GSSAPI Continue received from server when complete");
+ recv_tok.value = packet_get_string(&strlen);
-+ recv_tok.length = strlen;
++ recv_tok.length = strlen;
+ break;
+ case SSH2_MSG_KEXGSS_COMPLETE:
+ debug("Received GSSAPI_COMPLETE");
+ packet_get_bignum2(dh_server_pub);
+ msg_tok.value = packet_get_string(&strlen);
-+ msg_tok.length = strlen;
++ msg_tok.length = strlen;
+
+ /* Is there a token included? */
+ if (packet_get_char()) {
@@ -1520,9 +1482,9 @@ index 0000000..a49bac2
+ }
+ } while (maj_status & GSS_S_CONTINUE_NEEDED);
+
-+ /*
-+ * We _must_ have received a COMPLETE message in reply from the
-+ * server, which will have set dh_server_pub and msg_tok
++ /*
++ * We _must_ have received a COMPLETE message in reply from the
++ * server, which will have set dh_server_pub and msg_tok
+ */
+
+ if (type != SSH2_MSG_KEXGSS_COMPLETE)
@@ -1553,7 +1515,9 @@ index 0000000..a49bac2
+ switch (ssh->kex->kex_type) {
+ case KEX_GSS_GRP1_SHA1:
+ case KEX_GSS_GRP14_SHA1:
-+ kex_dh_hash( ssh->kex->client_version_string,
++ kex_dh_hash(
++ ssh->kex->hash_alg,
++ ssh->kex->client_version_string,
+ ssh->kex->server_version_string,
+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
@@ -1620,10 +1584,10 @@ index 0000000..a49bac2
+#endif /* GSSAPI */
diff --git a/kexgsss.c b/kexgsss.c
new file mode 100644
-index 0000000..0847469
+index 0000000..cfb8680
--- /dev/null
+++ b/kexgsss.c
-@@ -0,0 +1,295 @@
+@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+ *
@@ -1678,12 +1642,12 @@ index 0000000..0847469
+kexgss_server(struct ssh *ssh)
+{
+ OM_uint32 maj_status, min_status;
-+
-+ /*
++
++ /*
+ * Some GSSAPI implementations use the input value of ret_flags (an
-+ * output variable) as a means of triggering mechanism specific
-+ * features. Initializing it to zero avoids inadvertently
-+ * activating this non-standard behaviour.
++ * output variable) as a means of triggering mechanism specific
++ * features. Initializing it to zero avoids inadvertently
++ * activating this non-standard behaviour.
+ */
+
+ OM_uint32 ret_flags = 0;
@@ -1764,10 +1728,10 @@ index 0000000..0847469
+ type = packet_read();
+ switch(type) {
+ case SSH2_MSG_KEXGSS_INIT:
-+ if (dh_client_pub != NULL)
++ if (dh_client_pub != NULL)
+ fatal("Received KEXGSS_INIT after initialising");
+ recv_tok.value = packet_get_string(&slen);
-+ recv_tok.length = slen;
++ recv_tok.length = slen;
+
+ if ((dh_client_pub = BN_new()) == NULL)
+ fatal("dh_client_pub == NULL");
@@ -1778,7 +1742,7 @@ index 0000000..0847469
+ break;
+ case SSH2_MSG_KEXGSS_CONTINUE:
+ recv_tok.value = packet_get_string(&slen);
-+ recv_tok.length = slen;
++ recv_tok.length = slen;
+ break;
+ default:
+ packet_disconnect(
@@ -1786,7 +1750,7 @@ index 0000000..0847469
+ type);
+ }
+
-+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
+ &send_tok, &ret_flags));
+
+ free(recv_tok.value);
@@ -1796,7 +1760,7 @@ index 0000000..0847469
+
+ if (dh_client_pub == NULL)
+ fatal("No client public key");
-+
++
+ if (maj_status & GSS_S_CONTINUE_NEEDED) {
+ debug("Sending GSSAPI_CONTINUE");
+ packet_start(SSH2_MSG_KEXGSS_CONTINUE);
@@ -1820,12 +1784,12 @@ index 0000000..0847469
+
+ if (!(ret_flags & GSS_C_INTEG_FLAG))
+ fatal("Integrity flag wasn't set");
-+
++
+ if (!dh_pub_is_valid(dh, dh_client_pub))
+ packet_disconnect("bad client public DH value");
+
+ klen = DH_size(dh);
-+ kbuf = xmalloc(klen);
++ kbuf = xmalloc(klen);
+ kout = DH_compute_key(kbuf, dh_client_pub, dh);
+ if (kout < 0)
+ fatal("DH_compute_key: failed");
@@ -1845,7 +1809,9 @@ index 0000000..0847469
+ case KEX_GSS_GRP1_SHA1:
+ case KEX_GSS_GRP14_SHA1:
+ kex_dh_hash(
-+ ssh->kex->client_version_string, ssh->kex->server_version_string,
++ ssh->kex->hash_alg,
++ ssh->kex->client_version_string,
++ ssh->kex->server_version_string,
+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
+ NULL, 0, /* Change this if we start sending host keys */
@@ -1903,7 +1869,7 @@ index 0000000..0847469
+
+ if (gss_kex_context == NULL)
+ gss_kex_context = ctxt;
-+ else
++ else
+ ssh_gssapi_delete_ctx(&ctxt);
+
+ DH_free(dh);
@@ -1920,7 +1886,7 @@ index 0000000..0847469
+}
+#endif /* GSSAPI */
diff --git a/monitor.c b/monitor.c
-index b410965..bdc2972 100644
+index 6252a78..cd909cd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -157,6 +157,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *);
@@ -1932,10 +1898,10 @@ index b410965..bdc2972 100644
#endif
#ifdef SSH_AUDIT_EVENTS
-@@ -234,11 +236,18 @@ struct mon_table mon_dispatch_proto20[] = {
- {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
- {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
- {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+@@ -230,11 +232,18 @@ struct mon_table mon_dispatch_proto20[] = {
+ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+ {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
+ {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
+ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
#endif
{0, 0, NULL}
@@ -1951,29 +1917,29 @@ index b410965..bdc2972 100644
#ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, 0, mm_answer_moduli},
#endif
-@@ -353,6 +362,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
- /* Permit requests for moduli and signatures */
- monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+@@ -302,6 +311,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
+ /* Permit requests for moduli and signatures */
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI
-+ /* and for the GSSAPI key exchange */
-+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
++ /* and for the GSSAPI key exchange */
++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif
- } else {
- mon_dispatch = mon_dispatch_proto15;
-@@ -461,6 +474,10 @@ monitor_child_postauth(struct monitor *pmonitor)
- monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+ /* The first few requests do not require asynchronous access */
+ while (!authenticated) {
+@@ -402,6 +415,10 @@ monitor_child_postauth(struct monitor *pmonitor)
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+#ifdef GSSAPI
-+ /* and for the GSSAPI key exchange */
-+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
-+#endif
- } else {
- mon_dispatch = mon_dispatch_postauth15;
- monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
-@@ -1864,6 +1881,13 @@ monitor_apply_keystate(struct monitor *pmonitor)
++ /* and for the GSSAPI key exchange */
++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
++#endif
+
+ if (!no_pty_flag) {
+ monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
+@@ -1608,6 +1625,13 @@ monitor_apply_keystate(struct monitor *pmonitor)
# endif
#endif /* WITH_OPENSSL */
kex->kex[KEX_C25519_SHA256] = kexc25519_server;
@@ -1987,9 +1953,9 @@ index b410965..bdc2972 100644
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
-@@ -1963,6 +1987,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
- OM_uint32 major;
- u_int len;
+@@ -1690,6 +1714,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
+ if (!options.gss_authentication && !options.gss_keyex)
+ fatal("In GSSAPI monitor when GSSAPI is disabled");
@@ -1997,9 +1963,9 @@ index b410965..bdc2972 100644
goid.elements = buffer_get_string(m, &len);
goid.length = len;
-@@ -1990,6 +2017,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
- OM_uint32 flags = 0; /* GSI needs this */
- u_int len;
+@@ -1720,6 +1747,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
+ if (!options.gss_authentication && !options.gss_keyex)
+ fatal("In GSSAPI monitor when GSSAPI is disabled");
@@ -2007,7 +1973,7 @@ index b410965..bdc2972 100644
in.value = buffer_get_string(m, &len);
in.length = len;
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
-@@ -2007,6 +2037,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
+@@ -1737,6 +1767,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
@@ -2015,9 +1981,9 @@ index b410965..bdc2972 100644
}
return (0);
}
-@@ -2018,6 +2049,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
- OM_uint32 ret;
- u_int len;
+@@ -1751,6 +1782,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
+ if (!options.gss_authentication && !options.gss_keyex)
+ fatal("In GSSAPI monitor when GSSAPI is disabled");
@@ -2025,25 +1991,25 @@ index b410965..bdc2972 100644
gssbuf.value = buffer_get_string(m, &len);
gssbuf.length = len;
mic.value = buffer_get_string(m, &len);
-@@ -2044,7 +2078,11 @@ mm_answer_gss_userok(int sock, Buffer *m)
- {
- int authenticated;
+@@ -1780,7 +1814,11 @@ mm_answer_gss_userok(int sock, Buffer *m)
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+ if (!options.gss_authentication && !options.gss_keyex)
+ fatal("In GSSAPI monitor when GSSAPI is disabled");
+
-+ authenticated = authctxt->valid &&
++ authenticated = authctxt->valid &&
+ ssh_gssapi_userok(authctxt->user, authctxt->pw);
buffer_clear(m);
buffer_put_int(m, authenticated);
-@@ -2057,5 +2095,73 @@ mm_answer_gss_userok(int sock, Buffer *m)
+@@ -1793,5 +1831,73 @@ mm_answer_gss_userok(int sock, Buffer *m)
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
+
-+int
++int
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+ gss_buffer_desc data;
@@ -2056,8 +2022,8 @@ index b410965..bdc2972 100644
+
+ data.value = buffer_get_string(m, &len);
+ data.length = len;
-+ if (data.length != 20)
-+ fatal("%s: data length incorrect: %d", __func__,
++ if (data.length != 20)
++ fatal("%s: data length incorrect: %d", __func__,
+ (int) data.length);
+
+ /* Save the session ID on the first time around */
@@ -2113,7 +2079,7 @@ index b410965..bdc2972 100644
#endif /* GSSAPI */
diff --git a/monitor.h b/monitor.h
-index 93b8b66..bc50ade 100644
+index d68f674..ec41404 100644
--- a/monitor.h
+++ b/monitor.h
@@ -65,6 +65,9 @@ enum monitor_reqtype {
@@ -2125,12 +2091,12 @@ index 93b8b66..bc50ade 100644
+
};
- struct mm_master;
+ struct monitor {
diff --git a/monitor_wrap.c b/monitor_wrap.c
-index e6217b3..71e7c08 100644
+index 64ff928..d5cb640 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
-@@ -1069,7 +1069,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+@@ -924,7 +924,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
}
int
@@ -2139,7 +2105,7 @@ index e6217b3..71e7c08 100644
{
Buffer m;
int authenticated = 0;
-@@ -1086,5 +1086,50 @@ mm_ssh_gssapi_userok(char *user)
+@@ -941,5 +941,50 @@ mm_ssh_gssapi_userok(char *user)
debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
return (authenticated);
}
@@ -2191,10 +2157,10 @@ index e6217b3..71e7c08 100644
#endif /* GSSAPI */
diff --git a/monitor_wrap.h b/monitor_wrap.h
-index de4a08f..9758290 100644
+index db5902f..8f9dd89 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
-@@ -58,8 +58,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+@@ -55,8 +55,10 @@ int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
@@ -2207,20 +2173,20 @@ index de4a08f..9758290 100644
#ifdef USE_PAM
diff --git a/readconf.c b/readconf.c
-index db7d0bb..68dac76 100644
+index 9d59493..ea525c5 100644
--- a/readconf.c
+++ b/readconf.c
-@@ -147,6 +147,8 @@ typedef enum {
+@@ -160,6 +160,8 @@ typedef enum {
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
-+ oGssServerIdentity,
++ oGssServerIdentity,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
-@@ -191,10 +193,19 @@ static struct {
- { "afstokenpassing", oUnsupported },
+@@ -196,10 +198,19 @@ static struct {
+ /* Sometimes-unsupported options */
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
+ { "gssapikeyexchange", oGssKeyEx },
@@ -2229,7 +2195,7 @@ index db7d0bb..68dac76 100644
+ { "gssapiclientidentity", oGssClientIdentity },
+ { "gssapiserveridentity", oGssServerIdentity },
+ { "gssapirenewalforcesrekey", oGssRenewalRekey },
- #else
+ # else
{ "gssapiauthentication", oUnsupported },
+ { "gssapikeyexchange", oUnsupported },
{ "gssapidelegatecredentials", oUnsupported },
@@ -2237,9 +2203,9 @@ index db7d0bb..68dac76 100644
+ { "gssapiclientidentity", oUnsupported },
+ { "gssapirenewalforcesrekey", oUnsupported },
#endif
- { "fallbacktorsh", oDeprecated },
- { "usersh", oDeprecated },
-@@ -892,10 +903,30 @@ parse_time:
+ #ifdef ENABLE_PKCS11
+ { "smartcarddevice", oPKCS11Provider },
+@@ -973,10 +984,30 @@ parse_time:
intptr = &options->gss_authentication;
goto parse_flag;
@@ -2270,7 +2236,7 @@ index db7d0bb..68dac76 100644
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
-@@ -1601,7 +1632,12 @@ initialize_options(Options * options)
+@@ -1798,7 +1829,12 @@ initialize_options(Options * options)
options->pubkey_authentication = -1;
options->challenge_response_authentication = -1;
options->gss_authentication = -1;
@@ -2283,7 +2249,7 @@ index db7d0bb..68dac76 100644
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
-@@ -1728,8 +1764,14 @@ fill_default_options(Options * options)
+@@ -1942,8 +1978,14 @@ fill_default_options(Options * options)
options->challenge_response_authentication = 1;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
@@ -2299,7 +2265,7 @@ index db7d0bb..68dac76 100644
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
diff --git a/readconf.h b/readconf.h
-index 576b9e3..ef39c4c 100644
+index cef55f7..fd3d7c7 100644
--- a/readconf.h
+++ b/readconf.h
@@ -45,7 +45,12 @@ typedef struct {
@@ -2316,10 +2282,10 @@ index 576b9e3..ef39c4c 100644
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
diff --git a/servconf.c b/servconf.c
-index df93fc4..2f7f41e 100644
+index 56b8316..d796b7c 100644
--- a/servconf.c
+++ b/servconf.c
-@@ -115,8 +115,10 @@ initialize_server_options(ServerOptions *options)
+@@ -113,8 +113,10 @@ initialize_server_options(ServerOptions *options)
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
options->gss_authentication=-1;
@@ -2330,7 +2296,7 @@ index df93fc4..2f7f41e 100644
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
-@@ -275,10 +277,14 @@ fill_default_server_options(ServerOptions *options)
+@@ -267,10 +269,14 @@ fill_default_server_options(ServerOptions *options)
options->kerberos_get_afs_token = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
@@ -2339,22 +2305,21 @@ index df93fc4..2f7f41e 100644
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
if (options->gss_strict_acceptor == -1)
-- options->gss_strict_acceptor = 0;
-+ options->gss_strict_acceptor = 1;
+ options->gss_strict_acceptor = 1;
+ if (options->gss_store_rekey == -1)
+ options->gss_store_rekey = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
-@@ -401,6 +407,7 @@ typedef enum {
- sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
+@@ -407,6 +413,7 @@ typedef enum {
+ sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssKeyEx, sGssStoreRekey,
sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
-@@ -473,12 +480,20 @@ static struct {
+@@ -480,12 +487,20 @@ static struct {
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
@@ -2375,7 +2340,7 @@ index df93fc4..2f7f41e 100644
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
-@@ -1214,6 +1229,10 @@ process_server_config_line(ServerOptions *options, char *line,
+@@ -1217,6 +1232,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->gss_authentication;
goto parse_flag;
@@ -2386,7 +2351,7 @@ index df93fc4..2f7f41e 100644
case sGssCleanupCreds:
intptr = &options->gss_cleanup_creds;
goto parse_flag;
-@@ -1222,6 +1241,10 @@ process_server_config_line(ServerOptions *options, char *line,
+@@ -1225,6 +1244,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->gss_strict_acceptor;
goto parse_flag;
@@ -2397,7 +2362,7 @@ index df93fc4..2f7f41e 100644
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
-@@ -2229,7 +2252,10 @@ dump_config(ServerOptions *o)
+@@ -2250,7 +2273,10 @@ dump_config(ServerOptions *o)
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
@@ -2409,10 +2374,10 @@ index df93fc4..2f7f41e 100644
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
diff --git a/servconf.h b/servconf.h
-index 606d80c..b99b270 100644
+index 5853a97..90dfa4c 100644
--- a/servconf.h
+++ b/servconf.h
-@@ -117,8 +117,10 @@ typedef struct {
+@@ -112,8 +112,10 @@ typedef struct {
int kerberos_get_afs_token; /* If true, try to get AFS token if
* authenticated with Kerberos. */
int gss_authentication; /* If true, permit GSSAPI authentication */
@@ -2424,7 +2389,7 @@ index 606d80c..b99b270 100644
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
diff --git a/ssh-gss.h b/ssh-gss.h
-index a99d7f0..914701b 100644
+index a99d7f0..d467229 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,6 +1,6 @@
@@ -2501,13 +2466,13 @@ index a99d7f0..914701b 100644
+int ssh_gssapi_credentials_updated(Gssctxt *);
/* In the server */
-+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
+ const char *);
+char *ssh_gssapi_client_mechanisms(const char *, const char *);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
+ const char *);
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
-+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
+ const char *);
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
-int ssh_gssapi_userok(char *name);
@@ -2527,7 +2492,7 @@ index a99d7f0..914701b 100644
#endif /* _SSH_GSS_H */
diff --git a/ssh_config b/ssh_config
-index 03a228f..228e5ab 100644
+index 90fb63f..4e879cd 100644
--- a/ssh_config
+++ b/ssh_config
@@ -26,6 +26,8 @@
@@ -2540,13 +2505,13 @@ index 03a228f..228e5ab 100644
# CheckHostIP yes
# AddressFamily any
diff --git a/ssh_config.5 b/ssh_config.5
-index 268a627..b840261 100644
+index 532745b..90d820d 100644
--- a/ssh_config.5
+++ b/ssh_config.5
-@@ -744,11 +744,43 @@ Specifies whether user authentication based on GSSAPI is allowed.
+@@ -752,10 +752,42 @@ The default is
+ Specifies whether user authentication based on GSSAPI is allowed.
The default is
- .Dq no .
- Note that this option applies to protocol version 2 only.
+ .Cm no .
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
@@ -2554,32 +2519,30 @@ index 268a627..b840261 100644
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
-+If set, specifies the GSSAPI client identity that ssh should use when
-+connecting to the server. The default is unset, which means that the default
++If set, specifies the GSSAPI client identity that ssh should use when
++connecting to the server. The default is unset, which means that the default
+identity will be used.
+.It Cm GSSAPIServerIdentity
-+If set, specifies the GSSAPI server identity that ssh should expect when
++If set, specifies the GSSAPI server identity that ssh should expect when
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
.It Cm GSSAPIDelegateCredentials
Forward (delegate) credentials to the server.
The default is
- .Dq no .
--Note that this option applies to protocol version 2 only.
-+Note that this option applies to protocol version 2 connections using GSSAPI.
+ .Cm no .
+.It Cm GSSAPIRenewalForcesRekey
-+If set to
++If set to
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
-+ssh connection. With a compatible server, this can delegate the renewed
++ssh connection. With a compatible server, this can delegate the renewed
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
-+Set to
++Set to
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
-+the name of the host being connected to. If
++the name of the host being connected to. If
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
@@ -2589,28 +2552,63 @@ index 268a627..b840261 100644
Indicates that
.Xr ssh 1
diff --git a/sshconnect2.c b/sshconnect2.c
-index fcaed6b..44c89e6 100644
+index f8a54be..8ea9b3c 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
-@@ -200,6 +225,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- myproposal[PROPOSAL_KEX_ALGS]);
+@@ -161,10 +161,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+ char *s;
+ struct kex *kex;
+ int r;
++ struct ssh *ssh = active_state;
++
++#ifdef GSSAPI
++ char *orig = NULL, *gss = NULL;
++ char *gss_host = NULL;
++#endif
+
+ xxx_host = host;
+ xxx_hostaddr = hostaddr;
+
++#ifdef GSSAPI
++ if (options.gss_keyex) {
++ /* Add the GSSAPI mechanisms currently supported on this
++ * client to the key exchange algorithm proposal */
++ orig = options.kex_algorithms;
++ if (options.gss_trust_dns)
++ gss_host = (char *)get_canonical_hostname(ssh, 1);
++ else
++ gss_host = host;
++
++ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
++ if (gss) {
++ debug("Offering GSSAPI proposal: %s", gss);
++ xasprintf(&options.kex_algorithms, "%s,%s", gss, orig);
++ }
++ }
++#endif
++
+ if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
+ fatal("%s: kex_names_cat", __func__);
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
+@@ -192,6 +216,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+ order_hostkeyalgs(host, hostaddr, port));
+ }
+#ifdef GSSAPI
+ /* If we've got GSSAPI algorithms, then we also support the
+ * 'null' hostkey, as a last resort */
+ if (options.gss_keyex && gss) {
+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
-+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
+ "%s,null", orig);
+ free(gss);
+ }
+#endif
+
if (options.rekey_limit || options.rekey_interval)
- packet_set_rekey_limits((u_int32_t)options.rekey_limit,
- (time_t)options.rekey_interval);
-@@ -218,10 +254,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+ packet_set_rekey_limits(options.rekey_limit,
+ options.rekey_interval);
+@@ -213,10 +248,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
# endif
#endif
kex->kex[KEX_C25519_SHA256] = kexc25519_client;
@@ -2640,8 +2638,8 @@ index fcaed6b..44c89e6 100644
+
dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
- if (options.use_roaming && !kex->roaming) {
-@@ -313,6 +369,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
+ /* remove ext-info from the KEX proposals for rekeying */
+@@ -311,6 +366,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
int input_gssapi_hash(int type, u_int32_t, void *);
int input_gssapi_error(int, u_int32_t, void *);
int input_gssapi_errtok(int, u_int32_t, void *);
@@ -2649,7 +2647,7 @@ index fcaed6b..44c89e6 100644
#endif
void userauth(Authctxt *, char *);
-@@ -328,6 +385,11 @@ static char *authmethods_get(void);
+@@ -327,6 +383,11 @@ static char *authmethods_get(void);
Authmethod authmethods[] = {
#ifdef GSSAPI
@@ -2661,16 +2659,17 @@ index fcaed6b..44c89e6 100644
{"gssapi-with-mic",
userauth_gssapi,
NULL,
-@@ -634,19 +696,31 @@ userauth_gssapi(Authctxt *authctxt)
+@@ -652,19 +713,32 @@ userauth_gssapi(Authctxt *authctxt)
static u_int mech = 0;
OM_uint32 min;
int ok = 0;
+ const char *gss_host;
++ struct ssh *ssh = active_state;
+
+ if (options.gss_server_identity)
+ gss_host = options.gss_server_identity;
+ else if (options.gss_trust_dns)
-+ gss_host = get_canonical_hostname(1);
++ gss_host = get_canonical_hostname(ssh, 1);
+ else
+ gss_host = authctxt->host;
@@ -2688,14 +2687,15 @@ index fcaed6b..44c89e6 100644
while (mech < gss_supported->count && !ok) {
/* My DER encoding requires length<128 */
if (gss_supported->elements[mech].length < 128 &&
- ssh_gssapi_check_mechanism(&gssctxt,
+- ssh_gssapi_check_mechanism(&gssctxt,
- &gss_supported->elements[mech], authctxt->host)) {
-+ &gss_supported->elements[mech], gss_host,
++ ssh_gssapi_check_mechanism(&gssctxt,
++ &gss_supported->elements[mech], gss_host,
+ options.gss_client_identity)) {
ok = 1; /* Mechanism works */
} else {
mech++;
-@@ -743,8 +817,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
+@@ -761,8 +835,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
@@ -2706,7 +2706,7 @@ index fcaed6b..44c89e6 100644
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
-@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+@@ -875,6 +949,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
free(lang);
return 0;
}
@@ -2724,7 +2724,7 @@ index fcaed6b..44c89e6 100644
+ return (0);
+
+ if (gss_kex_context == NULL) {
-+ debug("No valid Key exchange context");
++ debug("No valid Key exchange context");
+ return (0);
+ }
+
@@ -2756,10 +2756,10 @@ index fcaed6b..44c89e6 100644
int
diff --git a/sshd.c b/sshd.c
-index 6f8c6f2..6b85e6c 100644
+index 010a2c3..b52c5d8 100644
--- a/sshd.c
+++ b/sshd.c
-@@ -125,6 +125,10 @@
+@@ -123,6 +123,10 @@
#include "version.h"
#include "ssherr.h"
@@ -2767,25 +2767,35 @@ index 6f8c6f2..6b85e6c 100644
+#include <Security/AuthSession.h>
+#endif
+
- #ifndef O_NOCTTY
- #define O_NOCTTY 0
- #endif
-@@ -1823,10 +1827,13 @@ main(int ac, char **av)
- logit("Disabling protocol version 1. Could not load host key");
- options.protocol &= ~SSH_PROTO_1;
+ /* Re-exec fds */
+ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
+ #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
+@@ -1485,7 +1489,7 @@ main(int ac, char **av)
+ fprintf(stderr, "too many host keys.\n");
+ exit(1);
+ }
+- options.host_key_files[options.num_host_key_files++] =
++ options.host_key_files[options.num_host_key_files++] =
+ derelativise_path(optarg);
+ break;
+ case 't':
+@@ -1719,10 +1723,14 @@ main(int ac, char **av)
+ key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp);
+ free(fp);
}
++
+#ifndef GSSAPI
+ /* The GSSAPI key exchange can run without a host key */
- if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
- logit("Disabling protocol version 2. Could not load host key");
- options.protocol &= ~SSH_PROTO_2;
- }
-+#endif
- if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+ if (!sensitive_data.have_ssh2_key) {
logit("sshd: no hostkeys available -- exiting.");
exit(1);
-@@ -2141,6 +2148,60 @@ main(int ac, char **av)
- remote_ip, remote_port, laddr, get_local_port());
+ }
++#endif
+
+ /*
+ * Load certificates. They are stored in an array at identical
+@@ -1992,6 +2000,60 @@ main(int ac, char **av)
+ remote_ip, remote_port, laddr, ssh_local_port(ssh));
free(laddr);
+#ifdef USE_SECURITY_SESSION_API
@@ -2830,7 +2840,7 @@ index 6f8c6f2..6b85e6c 100644
+ error("SessionCreate() failed with error %.8X",
+ (unsigned) err);
+
-+ err = SessionGetInfo(callerSecuritySession, &sid,
++ err = SessionGetInfo(callerSecuritySession, &sid,
+ &sattrs);
+ if (err)
+ error("SessionGetInfo() failed with error %.8X",
@@ -2845,7 +2855,7 @@ index 6f8c6f2..6b85e6c 100644
/*
* We don't want to listen forever unless the other side
* successfully authenticates itself. So we set up an alarm which is
-@@ -2570,6 +2631,48 @@ do_ssh2_kex(void)
+@@ -2173,6 +2235,48 @@ do_ssh2_kex(void)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types());
@@ -2856,7 +2866,7 @@ index 6f8c6f2..6b85e6c 100644
+ char *newstr = NULL;
+ orig = myproposal[PROPOSAL_KEX_ALGS];
+
-+ /*
++ /*
+ * If we don't have a host key, then there's no point advertising
+ * the other key exchange algorithms
+ */
@@ -2876,7 +2886,7 @@ index 6f8c6f2..6b85e6c 100644
+ else if (orig)
+ newstr = orig;
+
-+ /*
++ /*
+ * If we've got GSSAPI mechanisms, then we've got the 'null' host
+ * key alg, but we can't tell people about it unless its the only
+ * host key algorithm we support
@@ -2894,7 +2904,7 @@ index 6f8c6f2..6b85e6c 100644
/* start key exchange */
if ((r = kex_setup(active_state, myproposal)) != 0)
fatal("kex_setup: %s", ssh_err(r));
-@@ -2584,6 +2687,13 @@ do_ssh2_kex(void)
+@@ -2190,6 +2294,13 @@ do_ssh2_kex(void)
# endif
#endif
kex->kex[KEX_C25519_SHA256] = kexc25519_server;
@@ -2909,10 +2919,10 @@ index 6f8c6f2..6b85e6c 100644
kex->client_version_string=client_version_string;
kex->server_version_string=server_version_string;
diff --git a/sshd_config b/sshd_config
-index cf7d8e1..1dfd0f1 100644
+index 4eb2e02..c01dd65 100644
--- a/sshd_config
+++ b/sshd_config
-@@ -84,6 +84,8 @@ AuthorizedKeysFile .ssh/authorized_keys
+@@ -70,6 +70,8 @@ AuthorizedKeysFile .ssh/authorized_keys
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
@@ -2922,13 +2932,13 @@ index cf7d8e1..1dfd0f1 100644
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
diff --git a/sshd_config.5 b/sshd_config.5
-index 5ab4318..68424f1 100644
+index ac6ccc7..ab35547 100644
--- a/sshd_config.5
+++ b/sshd_config.5
-@@ -616,6 +616,12 @@ Specifies whether user authentication based on GSSAPI is allowed.
+@@ -627,6 +627,12 @@ The default is
+ Specifies whether user authentication based on GSSAPI is allowed.
The default is
- .Dq no .
- Note that this option applies to protocol version 2 only.
+ .Cm no .
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
@@ -2938,37 +2948,48 @@ index 5ab4318..68424f1 100644
.It Cm GSSAPICleanupCredentials
Specifies whether to automatically destroy the user's credentials cache
on logout.
-@@ -637,6 +643,11 @@ machine's default store.
+@@ -646,6 +652,11 @@ machine's default store.
This facility is provided to assist with operation on multi homed machines.
The default is
- .Dq yes .
+ .Cm yes .
+.It Cm GSSAPIStoreCredentialsOnRekey
-+Controls whether the user's GSSAPI credentials should be updated following a
-+successful connection rekeying. This option can be used to accepted renewed
++Controls whether the user's GSSAPI credentials should be updated following a
++successful connection rekeying. This option can be used to accepted renewed
+or updated credentials from a compatible client. The default is
+.Dq no .
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a comma-separated pattern list.
diff --git a/sshkey.c b/sshkey.c
-index cfe5980..2c87d80 100644
+index 829bd04..9a58396 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -116,6 +116,7 @@ static const struct keytype keytypes[] = {
- { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
- KEY_DSA_CERT_V00, 0, 1 },
+ # endif /* OPENSSL_HAS_NISTP521 */
+ # endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
-+ { "null", "null", KEY_NULL, 0, 0 },
- { NULL, NULL, -1, -1, 0 }
++ { "null", "null", KEY_NULL, 0, 0, 0 },
+ { NULL, NULL, -1, -1, 0, 0 }
};
-@@ -204,7 +205,7 @@ key_alg_list(int certs_only, int plain_only)
+@@ -204,7 +205,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->name == NULL)
+ if (kt->name == NULL || kt->type == KEY_NULL)
continue;
- if ((certs_only && !kt->cert) || (plain_only && kt->cert))
+ if (!include_sigonly && kt->sigonly)
continue;
+diff --git a/sshkey.h b/sshkey.h
+index 1b9e42f..f91e4a0 100644
+--- a/sshkey.h
++++ b/sshkey.h
+@@ -62,6 +62,7 @@ enum sshkey_types {
+ KEY_DSA_CERT,
+ KEY_ECDSA_CERT,
+ KEY_ED25519_CERT,
++ KEY_NULL,
+ KEY_UNSPEC
+ };