git: 6e508486e4 - main - Add SA-23:19.openssh.

Gordon Tetlow <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.doc
Message-ID <[email protected]>
The branch main has been updated by gordon:

URL: https://cgit.FreeBSD.org/doc/commit/?id=6e508486e413dd16c913a664c712dc88a32414e1

commit 6e508486e413dd16c913a664c712dc88a32414e1
Author:     Gordon Tetlow <[email protected]>
AuthorDate: 2023-12-19 20:32:05 +0000
Commit:     Gordon Tetlow <[email protected]>
CommitDate: 2023-12-19 20:32:05 +0000

    Add SA-23:19.openssh.
    
    Approved by:    so
---
 website/data/security/advisories.toml              |   4 +
 .../advisories/FreeBSD-SA-23:19.openssh.asc        | 147 +++++++
 .../static/security/patches/SA-23:19/openssh.patch | 460 +++++++++++++++++++++
 .../security/patches/SA-23:19/openssh.patch.asc    |  16 +
 4 files changed, 627 insertions(+)

diff --git a/website/data/security/advisories.toml b/website/data/security/advisories.toml
index e914a98428..5a4783bd59 100644
--- a/website/data/security/advisories.toml
+++ b/website/data/security/advisories.toml
@@ -1,6 +1,10 @@
 # Sort advisories by year, month and day
 # $FreeBSD$
 
+[[advisories]]
+name = "FreeBSD-SA-23:19.openssh"
+date = "2023-12-19"
+
 [[advisories]]
 name = "FreeBSD-SA-23:18.nfsclient"
 date = "2023-12-12"
diff --git a/website/static/security/advisories/FreeBSD-SA-23:19.openssh.asc b/website/static/security/advisories/FreeBSD-SA-23:19.openssh.asc
new file mode 100644
index 0000000000..bf48a4a6db
--- /dev/null
+++ b/website/static/security/advisories/FreeBSD-SA-23:19.openssh.asc
@@ -0,0 +1,147 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA512
+
+=============================================================================
+FreeBSD-SA-23:19.openssh                                    Security Advisory
+                                                          The FreeBSD Project
+
+Topic:          Prefix Truncation Attack in the SSH protocol
+
+Category:       contrib
+Module:         openssh
+Announced:      2023-12-19
+Credits:        Fabian Bäumer, Marcus Brinkmann, Jörg Schwenk
+Affects:        All supported versions of FreeBSD.
+Corrected:      2023-12-18 16:54:31 UTC (stable/14, 14.0-STABLE)
+                2023-12-19 20:19:48 UTC (releng/14.0, 14.0-RELEASE-p4)
+                2023-12-18 17:10:15 UTC (stable/13, 13.2-STABLE)
+                2023-12-19 20:19:57 UTC (releng/13.2, 13.2-RELEASE-p9)
+CVE Name:       CVE-2023-48795
+
+Note: While this issue does affect 12.4-STABLE and 12.4-RELEASE, the version
+of OpenSSH in 12.4 is old enough the vendor provided patch does not cleanly
+apply. As 12.4 goes out of support at the end of December and in order to
+quickly get fixes out for 14.0 and 13.2, the FreeBSD Security Team is issuing
+this advisory now while feasibility of a 12.4 backport is investigated. Users
+with 12.4 are encouraged to either implement the documented workaround or
+leverage an up to date version of OpenSSH from the ports/pkg collection.
+
+For general information regarding FreeBSD Security Advisories,
+including descriptions of the fields above, security branches, and the
+following sections, please visit <URL:https://security.FreeBSD.org/>.
+
+I.   Background
+
+OpenSSH is an implementation of the SSH protocol suite, providing an
+encrypted and authenticated transport for a variety of services, including
+remote shell access.
+
+II.  Problem Description
+
+The SSH protocol executes an initial handshake between the server and the
+client. This protocol handshake includes the possibility of several
+extensions allowing different options to be selected. Validation of the
+packets in the handshake is done through sequence numbers.
+
+III. Impact
+
+A man in the middle attacker can silently manipulate handshake messages to
+truncate extension negotiation messages potentially leading to less secure
+client authentication algorithms or deactivating keystroke timing attack
+countermeasures.
+
+IV.  Workaround
+
+Add the following lines to /etc/ssh_config and /etc/sshd_config:
+  Ciphers [email protected]
+  MACs -*[email protected]
+
+V.   Solution
+
+Upgrade your vulnerable system to a supported FreeBSD stable or
+release / security branch (releng) dated after the correction date.
+
+Perform one of the following:
+
+1) To update your vulnerable system via a binary patch:
+
+Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms,
+or the i386 platfrom on FreeBSD 13 and earlier, can be updated via
+the freebsd-update(8) utility:
+
+# freebsd-update fetch
+# freebsd-update install
+
+2) To update your vulnerable system via a source code patch:
+
+The following patches have been verified to apply to the applicable
+FreeBSD release branches.
+
+a) Download the relevant patch from the location below, and verify the
+detached PGP signature using your PGP utility.
+
+# fetch https://security.FreeBSD.org/patches/SA-23:19/openssh.patch
+# fetch https://security.FreeBSD.org/patches/SA-23:19/openssh.patch.asc
+# gpg --verify openssh.patch.asc
+
+b) Apply the patch.  Execute the following commands as root:
+
+# cd /usr/src
+# patch < /path/to/patch
+
+c) Recompile the operating system using buildworld and installworld as
+described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
+
+Restart the applicable daemons, or reboot the system.
+
+VI.  Correction details
+
+This issue is corrected as of the corresponding Git commit hash or Subversion
+revision number in the following stable and release branches:
+
+Branch/path                             Hash                     Revision
+- -------------------------------------------------------------------------
+stable/14/                              673d1ead65c9    stable/14-n266020
+releng/14.0/                            b9856d61e99d  releng/14.0-n265399
+stable/13/                              3bafcb9744c9    stable/13-n256910
+releng/13.2/                            69bd68ba30c0  releng/13.2-n254651
+- -------------------------------------------------------------------------
+
+Run the following command to see which files were modified by a
+particular commit:
+
+# git show --stat <commit hash>
+
+Or visit the following URL, replacing NNNNNN with the hash:
+
+<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN>
+
+To determine the commit count in a working tree (for comparison against
+nNNNNNN in the table above), run:
+
+# git rev-list --count --first-parent HEAD
+
+VII. References
+
+<URL:https://terrapin-attack.com/>
+
+<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795>
+
+The latest revision of this advisory is available at
+<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-23:19.openssh.asc>
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmWB/ZIACgkQbljekB8A
+Gu8exRAA5OqnHpTSa3cPpnfBJNyJsWqD1bry8M8fxt6OpD3b8l/pVnH6HMaUSdQ/
+K4SebhwVJgq4sIfTILWey5X3EKOsp2CpRZb6K+h7iKtrGdDVbXWQj7Dbi5/cCTy6
+hdCSWqFwGJq/FpX15osAa2eEhv9DizE6jmYJ6YwnAfqLvvDSCVbtjeWs6wBJHeH3
+q5jlvdiAT64fhWBpC51MeLShLDG95hJEHAfloVaN0asAs0jYj73XFzcoPv+1Cf8J
+qURC5d6KlGYTyaF2ltiQTtssB8I+vhb+GQOyk01t4oyUPnU3myTiooW873xE0321
+as1UeXmzTjuaD/V/5QFawIWbnKOKoVP745llvDyJsF0dLf2Se45vndRH3fP7CdVK
+SPy3/u1ohkwNlm11RmeKSm2LbCa4RUwGZ3CqnEQ+dgYa6HBTATP68rWsaL4kIR/b
+N30AGeW8xMbhTSFsHYNn3rQ+2RnHCzlSN7eKGfdd9yBVwsRls0ckVVgldmyR26lQ
+7eYCbFMAdSCL45qKgYNww8PWSB1ge7AxnlC1MHPAct+kr6TrBwG4b6SAlI7GiDRP
+zzqOG2o6k2pEetvn3suLmoMYmmBVZYwzITHUFvyEF1UwF00QCa68xoUW0s2haWnJ
+riv7Wewt8m/vUXQ2ad2noElL31hdoRusaKCKVIVOKsCCvwAB/WI=
+=RQjY
+-----END PGP SIGNATURE-----
diff --git a/website/static/security/patches/SA-23:19/openssh.patch b/website/static/security/patches/SA-23:19/openssh.patch
new file mode 100644
index 0000000000..4131565ed7
--- /dev/null
+++ b/website/static/security/patches/SA-23:19/openssh.patch
@@ -0,0 +1,460 @@
+--- crypto/openssh/PROTOCOL.orig
++++ crypto/openssh/PROTOCOL
+@@ -137,6 +137,32 @@
+ short packet lengths, which would not be possible with other
+ approaches.
+ 
++1.9 transport: strict key exchange extension
++
++OpenSSH supports a number of transport-layer hardening measures under
++a "strict KEX" feature. This feature is signalled similarly to the
++RFC8308 ext-info feature: by including a additional algorithm in the
++initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append
++"[email protected]" to its kex_algorithms and the server
++may append "[email protected]". These pseudo-algorithms
++are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored
++if they are present in subsequent SSH2_MSG_KEXINIT packets.
++
++When an endpoint that supports this extension observes this algorithm
++name in a peer's KEXINIT packet, it MUST make the following changes to
++the the protocol:
++
++a) During initial KEX, terminate the connection if any unexpected or
++   out-of-sequence packet is received. This includes terminating the
++   connection if the first packet received is not SSH2_MSG_KEXINIT.
++   Unexpected packets for the purpose of strict KEX include messages
++   that are otherwise valid at any time during the connection such as
++   SSH2_MSG_DEBUG and SSH2_MSG_IGNORE.
++b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the
++   packet sequence number to zero. This behaviour persists for the
++   duration of the connection (i.e. not just the first
++   SSH2_MSG_NEWKEYS).
++
+ 2. Connection protocol changes
+ 
+ 2.1. connection: Channel write close extension "[email protected]"
+--- crypto/openssh/kex.c.orig
++++ crypto/openssh/kex.c
+@@ -65,7 +65,7 @@
+ #include "xmalloc.h"
+ 
+ /* prototype */
+-static int kex_choose_conf(struct ssh *);
++static int kex_choose_conf(struct ssh *, uint32_t seq);
+ static int kex_input_newkeys(int, u_int32_t, struct ssh *);
+ 
+ static const char * const proposal_names[PROPOSAL_MAX] = {
+@@ -177,6 +177,18 @@
+ 	return 1;
+ }
+ 
++/* returns non-zero if proposal contains any algorithm from algs */
++static int
++has_any_alg(const char *proposal, const char *algs)
++{
++	char *cp;
++
++	if ((cp = match_list(proposal, algs, NULL)) == NULL)
++		return 0;
++	free(cp);
++	return 1;
++}
++
+ /*
+  * Concatenate algorithm names, avoiding duplicates in the process.
+  * Caller must free returned string.
+@@ -184,7 +196,7 @@
+ char *
+ kex_names_cat(const char *a, const char *b)
+ {
+-	char *ret = NULL, *tmp = NULL, *cp, *p, *m;
++	char *ret = NULL, *tmp = NULL, *cp, *p;
+ 	size_t len;
+ 
+ 	if (a == NULL || *a == '\0')
+@@ -201,10 +213,8 @@
+ 	}
+ 	strlcpy(ret, a, len);
+ 	for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
+-		if ((m = match_list(ret, p, NULL)) != NULL) {
+-			free(m);
++		if (has_any_alg(ret, p))
+ 			continue; /* Algorithm already present */
+-		}
+ 		if (strlcat(ret, ",", len) >= len ||
+ 		    strlcat(ret, p, len) >= len) {
+ 			free(tmp);
+@@ -334,15 +344,23 @@
+ 	const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
+ 	const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
+ 	u_int i;
++	char *cp;
+ 
+ 	if (prop == NULL)
+ 		fatal_f("proposal missing");
+ 
++	/* Append EXT_INFO signalling to KexAlgorithms */
++	if (kexalgos == NULL)
++		kexalgos = defprop[PROPOSAL_KEX_ALGS];
++	if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
++	    "[email protected]" :
++	    "ext-info-c,[email protected]")) == NULL)
++		fatal_f("kex_names_cat");
++
+ 	for (i = 0; i < PROPOSAL_MAX; i++) {
+ 		switch(i) {
+ 		case PROPOSAL_KEX_ALGS:
+-			prop[i] = compat_kex_proposal(ssh,
+-			    kexalgos ? kexalgos : defprop[i]);
++			prop[i] = compat_kex_proposal(ssh, cp);
+ 			break;
+ 		case PROPOSAL_ENC_ALGS_CTOS:
+ 		case PROPOSAL_ENC_ALGS_STOC:
+@@ -363,6 +381,7 @@
+ 			prop[i] = xstrdup(defprop[i]);
+ 		}
+ 	}
++	free(cp);
+ }
+ 
+ void
+@@ -466,7 +485,12 @@
+ {
+ 	int r;
+ 
+-	error("kex protocol error: type %d seq %u", type, seq);
++	/* If in strict mode, any unexpected message is an error */
++	if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
++		ssh_packet_disconnect(ssh, "strict KEX violation: "
++		    "unexpected packet type %u (seqnr %u)", type, seq);
++	}
++	error_f("type %u seq %u", type, seq);
+ 	if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
+ 	    (r = sshpkt_put_u32(ssh, seq)) != 0 ||
+ 	    (r = sshpkt_send(ssh)) != 0)
+@@ -563,7 +587,7 @@
+ 	if (ninfo >= 1024) {
+ 		error("SSH2_MSG_EXT_INFO with too many entries, expected "
+ 		    "<=1024, received %u", ninfo);
+-		return SSH_ERR_INVALID_FORMAT;
++		return dispatch_protocol_error(type, seq, ssh);
+ 	}
+ 	for (i = 0; i < ninfo; i++) {
+ 		if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
+@@ -681,7 +705,7 @@
+ 		error_f("no kex");
+ 		return SSH_ERR_INTERNAL_ERROR;
+ 	}
+-	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
++	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
+ 	ptr = sshpkt_ptr(ssh, &dlen);
+ 	if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
+ 		return r;
+@@ -717,7 +741,7 @@
+ 	if (!(kex->flags & KEX_INIT_SENT))
+ 		if ((r = kex_send_kexinit(ssh)) != 0)
+ 			return r;
+-	if ((r = kex_choose_conf(ssh)) != 0)
++	if ((r = kex_choose_conf(ssh, seq)) != 0)
+ 		return r;
+ 
+ 	if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
+@@ -981,20 +1005,14 @@
+ 	return (1);
+ }
+ 
+-/* returns non-zero if proposal contains any algorithm from algs */
+ static int
+-has_any_alg(const char *proposal, const char *algs)
++kexalgs_contains(char **peer, const char *ext)
+ {
+-	char *cp;
+-
+-	if ((cp = match_list(proposal, algs, NULL)) == NULL)
+-		return 0;
+-	free(cp);
+-	return 1;
++	return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
+ }
+ 
+ static int
+-kex_choose_conf(struct ssh *ssh)
++kex_choose_conf(struct ssh *ssh, uint32_t seq)
+ {
+ 	struct kex *kex = ssh->kex;
+ 	struct newkeys *newkeys;
+@@ -1019,13 +1037,23 @@
+ 		sprop=peer;
+ 	}
+ 
+-	/* Check whether client supports ext_info_c */
+-	if (kex->server && (kex->flags & KEX_INITIAL)) {
+-		char *ext;
+-
+-		ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
+-		kex->ext_info_c = (ext != NULL);
+-		free(ext);
++	/* Check whether peer supports ext_info/kex_strict */
++	if ((kex->flags & KEX_INITIAL) != 0) {
++		if (kex->server) {
++			kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
++			kex->kex_strict = kexalgs_contains(peer,
++			    "[email protected]");
++		} else {
++			kex->kex_strict = kexalgs_contains(peer,
++			    "[email protected]");
++		}
++		if (kex->kex_strict) {
++			debug3_f("will use strict KEX ordering");
++			if (seq != 0)
++				ssh_packet_disconnect(ssh,
++				    "strict KEX violation: "
++				    "KEXINIT was not the first packet");
++		}
+ 	}
+ 
+ 	/* Check whether client supports rsa-sha2 algorithms */
+--- crypto/openssh/kex.h.orig
++++ crypto/openssh/kex.h
+@@ -149,6 +149,7 @@
+ 	u_int	kex_type;
+ 	char	*server_sig_algs;
+ 	int	ext_info_c;
++	int	kex_strict;
+ 	struct sshbuf *my;
+ 	struct sshbuf *peer;
+ 	struct sshbuf *client_version;
+--- crypto/openssh/packet.c.orig
++++ crypto/openssh/packet.c
+@@ -1208,8 +1208,13 @@
+ 	sshbuf_dump(state->output, stderr);
+ #endif
+ 	/* increment sequence number for outgoing packets */
+-	if (++state->p_send.seqnr == 0)
++	if (++state->p_send.seqnr == 0) {
++		if ((ssh->kex->flags & KEX_INITIAL) != 0) {
++			ssh_packet_disconnect(ssh, "outgoing sequence number "
++			    "wrapped during initial key exchange");
++		}
+ 		logit("outgoing seqnr wraps around");
++	}
+ 	if (++state->p_send.packets == 0)
+ 		if (!(ssh->compat & SSH_BUG_NOREKEY))
+ 			return SSH_ERR_NEED_REKEY;
+@@ -1217,6 +1222,11 @@
+ 	state->p_send.bytes += len;
+ 	sshbuf_reset(state->outgoing_packet);
+ 
++	if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
++		debug_f("resetting send seqnr %u", state->p_send.seqnr);
++		state->p_send.seqnr = 0;
++	}
++
+ 	if (type == SSH2_MSG_NEWKEYS)
+ 		r = ssh_set_newkeys(ssh, MODE_OUT);
+ 	else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
+@@ -1345,8 +1355,7 @@
+ 	/* Stay in the loop until we have received a complete packet. */
+ 	for (;;) {
+ 		/* Try to read a packet from the buffer. */
+-		r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
+-		if (r != 0)
++		if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0)
+ 			break;
+ 		/* If we got a packet, return it. */
+ 		if (*typep != SSH_MSG_NONE)
+@@ -1417,29 +1426,6 @@
+ 	return type;
+ }
+ 
+-/*
+- * Waits until a packet has been received, verifies that its type matches
+- * that given, and gives a fatal error and exits if there is a mismatch.
+- */
+-
+-int
+-ssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
+-{
+-	int r;
+-	u_char type;
+-
+-	if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
+-		return r;
+-	if (type != expected_type) {
+-		if ((r = sshpkt_disconnect(ssh,
+-		    "Protocol error: expected packet type %d, got %d",
+-		    expected_type, type)) != 0)
+-			return r;
+-		return SSH_ERR_PROTOCOL_ERROR;
+-	}
+-	return 0;
+-}
+-
+ static int
+ ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
+ {
+@@ -1630,10 +1616,16 @@
+ 		if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
+ 			goto out;
+ 	}
++
+ 	if (seqnr_p != NULL)
+ 		*seqnr_p = state->p_read.seqnr;
+-	if (++state->p_read.seqnr == 0)
++	if (++state->p_read.seqnr == 0) {
++		if ((ssh->kex->flags & KEX_INITIAL) != 0) {
++			ssh_packet_disconnect(ssh, "incoming sequence number "
++			    "wrapped during initial key exchange");
++		}
+ 		logit("incoming seqnr wraps around");
++	}
+ 	if (++state->p_read.packets == 0)
+ 		if (!(ssh->compat & SSH_BUG_NOREKEY))
+ 			return SSH_ERR_NEED_REKEY;
+@@ -1699,6 +1691,10 @@
+ #endif
+ 	/* reset for next packet */
+ 	state->packlen = 0;
++	if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
++		debug_f("resetting read seqnr %u", state->p_read.seqnr);
++		state->p_read.seqnr = 0;
++	}
+ 
+ 	if ((r = ssh_packet_check_rekey(ssh)) != 0)
+ 		return r;
+@@ -1721,10 +1717,39 @@
+ 		r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
+ 		if (r != 0)
+ 			return r;
+-		if (*typep) {
+-			state->keep_alive_timeouts = 0;
+-			DBG(debug("received packet type %d", *typep));
++		if (*typep == 0) {
++			/* no message ready */
++			return 0;
+ 		}
++		state->keep_alive_timeouts = 0;
++		DBG(debug("received packet type %d", *typep));
++
++		/* Always process disconnect messages */
++		if (*typep == SSH2_MSG_DISCONNECT) {
++			if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
++			    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
++				return r;
++			/* Ignore normal client exit notifications */
++			do_log2(ssh->state->server_side &&
++			    reason == SSH2_DISCONNECT_BY_APPLICATION ?
++			    SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
++			    "Received disconnect from %s port %d:"
++			    "%u: %.400s", ssh_remote_ipaddr(ssh),
++			    ssh_remote_port(ssh), reason, msg);
++			free(msg);
++			return SSH_ERR_DISCONNECTED;
++		}
++
++		/*
++		 * Do not implicitly handle any messages here during initial
++		 * KEX when in strict mode. They will be need to be allowed
++		 * explicitly by the KEX dispatch table or they will generate
++		 * protocol errors.
++		 */
++		if (ssh->kex != NULL &&
++		    (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict)
++			return 0;
++		/* Implicitly handle transport-level messages */
+ 		switch (*typep) {
+ 		case SSH2_MSG_IGNORE:
+ 			debug3("Received SSH2_MSG_IGNORE");
+@@ -1739,19 +1764,6 @@
+ 			debug("Remote: %.900s", msg);
+ 			free(msg);
+ 			break;
+-		case SSH2_MSG_DISCONNECT:
+-			if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
+-			    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
+-				return r;
+-			/* Ignore normal client exit notifications */
+-			do_log2(ssh->state->server_side &&
+-			    reason == SSH2_DISCONNECT_BY_APPLICATION ?
+-			    SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
+-			    "Received disconnect from %s port %d:"
+-			    "%u: %.400s", ssh_remote_ipaddr(ssh),
+-			    ssh_remote_port(ssh), reason, msg);
+-			free(msg);
+-			return SSH_ERR_DISCONNECTED;
+ 		case SSH2_MSG_UNIMPLEMENTED:
+ 			if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
+ 				return r;
+@@ -2244,6 +2256,7 @@
+ 	    (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
+ 	    (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
+ 	    (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
++	    (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 ||
+ 	    (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
+ 	    (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
+ 	    (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
+@@ -2406,6 +2419,7 @@
+ 	    (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
+ 	    (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
+ 	    (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
++	    (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 ||
+ 	    (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
+ 	    (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
+ 	    (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
+@@ -2734,6 +2748,7 @@
+ 	vsnprintf(buf, sizeof(buf), fmt, args);
+ 	va_end(args);
+ 
++	debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf);
+ 	if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
+ 	    (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
+ 	    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
+--- crypto/openssh/packet.h.orig
++++ crypto/openssh/packet.h
+@@ -124,7 +124,6 @@
+ int	 ssh_packet_send2(struct ssh *);
+ 
+ int      ssh_packet_read(struct ssh *);
+-int	 ssh_packet_read_expect(struct ssh *, u_int type);
+ int      ssh_packet_read_poll(struct ssh *);
+ int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
+ int	 ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len);
+--- crypto/openssh/sshconnect2.c.orig
++++ crypto/openssh/sshconnect2.c
+@@ -358,7 +358,6 @@
+ };
+ 
+ static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
+-static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
+ static int input_userauth_success(int, u_int32_t, struct ssh *);
+ static int input_userauth_failure(int, u_int32_t, struct ssh *);
+ static int input_userauth_banner(int, u_int32_t, struct ssh *);
+@@ -472,7 +471,7 @@
+ 
+ 	ssh->authctxt = &authctxt;
+ 	ssh_dispatch_init(ssh, &input_userauth_error);
+-	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
++	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info);
+ 	ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
+ 	ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success);	/* loop until success */
+ 	pubkey_cleanup(ssh);
+@@ -523,12 +522,6 @@
+ 	return r;
+ }
+ 
+-static int
+-input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
+-{
+-	return kex_input_ext_info(type, seqnr, ssh);
+-}
+-
+ void
+ userauth(struct ssh *ssh, char *authlist)
+ {
+@@ -607,6 +600,7 @@
+ 	free(authctxt->methoddata);
+ 	authctxt->methoddata = NULL;
+ 	authctxt->success = 1;			/* break out */
++	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error);
+ 	return 0;
+ }
diff --git a/website/static/security/patches/SA-23:19/openssh.patch.asc b/website/static/security/patches/SA-23:19/openssh.patch.asc
new file mode 100644
index 0000000000..33c0f2e785
--- /dev/null
+++ b/website/static/security/patches/SA-23:19/openssh.patch.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmWB/ZcACgkQbljekB8A
+Gu9Okg/+ImvzoJbeXz+q/hza0Ehc+mJcGEJ0Xs3WKRcexXXDcfrHTnOQGj4dNiDr
+BtL/Sbga5FMWS1JQBFwrUMcYiATL6g3m9Cut5hwGbJ3eQg5ytxyiRamrELxT/eJa
+Q9s0fs+tQH3We9FNy33wjexD5slMPtaScoywmkk7CdRf8RJc6Ett4D+qWlfzOrLE
+L1HjjrWGyRaw1YVe4pduIA0M8yeaFC1vCIzYaCEd8g/IQwe29NXVaULXBcIXs/kv
+LB8A22d75ksGlGx+MDYr6e03KYMEmHF11q9NwaFl4+S3lNIBuwf5naDahQjYwWDg
+7cJu7VpPpUduFB+NCHn/WVt9dQ5gST1gW5CN/WolsXcZe8qTLh+ry0rve0sQc5t/
+iWZ6YnrXM5wihyUAzM89jxc9krkS/1tKBKsLWCpgIYBzGrQHJrUT5RYcEQSWMlhc
+2vAk7XvWxE3M4zxekUzo3Y71gtNzbdbbV8uOBq2sdHQ2XgMQR0jA6GfdpgfNL33+
+ukP+Zsb3NsQ7tfp2k4YSulihK+aDFervZSFtN81rjetl7w3+hW8g/EuRQDlmaPBl
+zju4jh7udz9deo7DpX90VWWVqucQOkGFvgvKs/in668nL6WfqaNCOakonWfU6IZU
+xyi0ae6YhXS1P/ZiB0OMs5MHuOSYmoziBbLxP4PSFq1zPkchflk=
+=MDwh
+-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.