diff options
author | Christoph Gysin | 2017-09-24 17:18:02 +0300 |
---|---|---|
committer | Christoph Gysin | 2017-09-28 00:05:41 +0300 |
commit | 708be6678084efd20ddf9e9ce4c55cfc29effcd6 (patch) | |
tree | f5ac9a7a5ef89346f80f3f4a648e969fbf4ecd7c | |
parent | e21f22ff5b23d4f99cf2878fbb07b001a1ac4dc9 (diff) | |
download | aur-708be6678084efd20ddf9e9ce4c55cfc29effcd6.tar.gz |
update to 7.5p1
-rw-r--r-- | .SRCINFO | 25 | ||||
-rw-r--r-- | PKGBUILD | 42 | ||||
-rw-r--r-- | get_canonical_hostname.patch | 388 | ||||
-rw-r--r-- | gssapi-p0.patch | 36 | ||||
-rw-r--r-- | gssapi-p2.patch | 10 | ||||
-rw-r--r-- | gssapi.patch (renamed from gssapi-p1.patch) | 771 |
6 files changed, 819 insertions, 453 deletions
@@ -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 @@ -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 + }; |