From 3cfb2ab8d6d8b5a94d031f2750230cea8fd8639e Mon Sep 17 00:00:00 2001 From: Xavier Beaudouin Date: Tue, 8 Oct 2024 12:06:09 +0200 Subject: [PATCH] Fix --- .../openssh-portable/files/patch-SA-23:19 | 425 ------------------ 1 file changed, 425 deletions(-) delete mode 100644 security/openssh-portable/files/patch-SA-23:19 diff --git a/security/openssh-portable/files/patch-SA-23:19 b/security/openssh-portable/files/patch-SA-23:19 deleted file mode 100644 index 6240578..0000000 --- a/security/openssh-portable/files/patch-SA-23:19 +++ /dev/null @@ -1,425 +0,0 @@ ---- kex.c.orig -+++ 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 ? -+ "kex-strict-s-v00@openssh.com" : -+ "ext-info-c,kex-strict-c-v00@openssh.com")) == 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, -+ "kex-strict-c-v00@openssh.com"); -+ } else { -+ kex->kex_strict = kexalgs_contains(peer, -+ "kex-strict-s-v00@openssh.com"); -+ } -+ 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 */ ---- kex.h.orig -+++ 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; ---- packet.c.orig -+++ 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 || ---- packet.h.orig -+++ 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); ---- sshconnect2.c.orig -+++ 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; - }