!242 [sync] PR-240: fix CVE-2023-48795

From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
This commit is contained in:
openeuler-ci-bot 2024-01-11 06:17:36 +00:00 committed by Gitee
commit e8affb30e2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 110 additions and 577 deletions

View File

@ -1,7 +1,7 @@
From 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 Mon Sep 17 00:00:00 2001
From 802a7af111c9ddb438ca4fd8c5cc35534e199fda Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 18 Dec 2023 14:45:17 +0000
Subject: [PATCH] upstream: implement "strict key exchange" in ssh and sshd
Subject: upstream: implement "strict key exchange" in ssh and sshd
This adds a protocol extension to improve the integrity of the SSH
transport protocol, particular in and around the initial key exchange
@ -13,19 +13,24 @@ with markus@
OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14
Reference:https://github.com/openssh/openssh-portable/commit/1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5
Conflict:upstream: Fix signature algorithm selection logic for UpdateHostkeys on the server side
Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5
Last-Update: 2023-12-21
Patch-Name: CVE-2023-48795.patch
Reference:https://sources.debian.org/src/openssh/1%3A8.4p1-5%2Bdeb11u3/debian/patches/CVE-2023-48795.patch/
Conflict:NA
---
PROTOCOL | 28 +++++++++++++-
kex.c | 80 +++++++++++++++++++++++++++++----------
kex.h | 3 +-
packet.c | 103 +++++++++++++++++++++++++++++---------------------
packet.h | 3 +-
sshconnect2.c | 13 ++-----
6 files changed, 152 insertions(+), 78 deletions(-)
PROTOCOL | 26 +++++++++++++++++
kex.c | 68 ++++++++++++++++++++++++++++++++-----------
kex.h | 1 +
packet.c | 80 ++++++++++++++++++++++++++++++++++++++-------------
sshconnect2.c | 14 +++------
sshd.c | 8 ++++--
6 files changed, 149 insertions(+), 48 deletions(-)
diff --git a/PROTOCOL b/PROTOCOL
index 3141cda..9f02bb9 100644
index f75c1c0..89bddfe 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -102,6 +102,32 @@ OpenSSH supports the use of ECDH in Curve25519 for key exchange as
@ -61,23 +66,11 @@ index 3141cda..9f02bb9 100644
2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com"
@@ -575,4 +601,4 @@ OpenSSH's connection multiplexing uses messages as described in
PROTOCOL.mux over a Unix domain socket for communications between a
master instance and later clients.
-$OpenBSD: PROTOCOL,v 1.42 2021/08/09 23:47:44 djm Exp $
+$OpenBSD: PROTOCOL,v 1.50 2023/12/18 14:45:17 djm Exp $
diff --git a/kex.c b/kex.c
index 2afa087..5e437f9 100644
index 7c5f635..77eb7c0 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.178 2023/03/12 10:40:39 dtucker Exp $ */
+/* $OpenBSD: kex.c,v 1.183 2023/12/18 14:45:17 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -73,7 +73,7 @@
@@ -72,7 +72,7 @@
#endif
/* prototype */
@ -86,7 +79,7 @@ index 2afa087..5e437f9 100644
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
static const char *proposal_names[PROPOSAL_MAX] = {
@@ -218,6 +218,18 @@ kex_names_valid(const char *names)
@@ -215,6 +215,18 @@ kex_names_valid(const char *names)
return 1;
}
@ -105,7 +98,7 @@ index 2afa087..5e437f9 100644
/*
* Concatenate algorithm names, avoiding duplicates in the process.
* Caller must free returned string.
@@ -225,7 +237,7 @@ kex_names_valid(const char *names)
@@ -222,7 +234,7 @@ kex_names_valid(const char *names)
char *
kex_names_cat(const char *a, const char *b)
{
@ -114,7 +107,7 @@ index 2afa087..5e437f9 100644
size_t len;
if (a == NULL || *a == '\0')
@@ -242,10 +254,8 @@ kex_names_cat(const char *a, const char *b)
@@ -239,10 +251,8 @@ kex_names_cat(const char *a, const char *b)
}
strlcpy(ret, a, len);
for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
@ -126,41 +119,7 @@ index 2afa087..5e437f9 100644
if (strlcat(ret, ",", len) >= len ||
strlcat(ret, p, len) >= len) {
free(tmp);
@@ -375,15 +385,23 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
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:
@@ -404,6 +422,7 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
prop[i] = xstrdup(defprop[i]);
}
}
+ free(cp);
}
void
@@ -531,7 +550,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
@@ -474,7 +484,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
int r;
@ -170,20 +129,23 @@ index 2afa087..5e437f9 100644
+ ssh_packet_disconnect(ssh, "strict KEX violation: "
+ "unexpected packet type %u (seqnr %u)", type, seq);
+ }
+ error_f("type %u seq %u", type, seq);
+ error("%s: type %u seq %u", __func__, type, seq);
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
@@ -606,7 +630,7 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
if (ninfo >= 1024) {
error("SSH2_MSG_EXT_INFO with too many entries, expected "
"<=1024, received %u", ninfo);
- return SSH_ERR_INVALID_FORMAT;
@@ -546,6 +561,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
return r;
+ if (ninfo >= 1024) {
+ error("SSH2_MSG_EXT_INFO with too many entries, expected "
+ "<=1024, received %u", ninfo);
+ return dispatch_protocol_error(type, seq, ssh);
}
+ }
for (i = 0; i < ninfo; i++) {
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
@@ -708,7 +732,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
return r;
@@ -646,7 +666,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
error_f("no kex");
return SSH_ERR_INTERNAL_ERROR;
}
@ -192,7 +154,7 @@ index 2afa087..5e437f9 100644
ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r;
@@ -744,7 +768,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
@@ -682,7 +702,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
if (!(kex->flags & KEX_INIT_SENT))
if ((r = kex_send_kexinit(ssh)) != 0)
return r;
@ -201,7 +163,7 @@ index 2afa087..5e437f9 100644
return r;
if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
@@ -1022,7 +1046,13 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
@@ -960,7 +980,13 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
}
static int
@ -216,7 +178,7 @@ index 2afa087..5e437f9 100644
{
struct kex *kex = ssh->kex;
struct newkeys *newkeys;
@@ -1047,13 +1077,23 @@ kex_choose_conf(struct ssh *ssh)
@@ -985,13 +1011,23 @@ kex_choose_conf(struct ssh *ssh)
sprop=peer;
}
@ -238,7 +200,7 @@ index 2afa087..5e437f9 100644
+ "kex-strict-s-v00@openssh.com");
+ }
+ if (kex->kex_strict) {
+ debug3_f("will use strict KEX ordering");
+ debug3("%s: will use strict KEX ordering", __func__);
+ if (seq != 0)
+ ssh_packet_disconnect(ssh,
+ "strict KEX violation: "
@ -248,16 +210,10 @@ index 2afa087..5e437f9 100644
/* Algorithm Negotiation */
diff --git a/kex.h b/kex.h
index 87ba7c8..1374a8c 100644
index eabae1d..5d3895c 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.118 2023/03/06 12:14:48 dtucker Exp $ */
+/* $OpenBSD: kex.h,v 1.120 2023/12/18 14:45:17 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -153,6 +153,7 @@ struct kex {
@@ -155,6 +155,7 @@ struct kex {
u_int kex_type;
char *server_sig_algs;
int ext_info_c;
@ -266,16 +222,10 @@ index 87ba7c8..1374a8c 100644
struct sshbuf *peer;
struct sshbuf *client_version;
diff --git a/packet.c b/packet.c
index 96ff2ac..95c1dd1 100644
index f3231e1..16b87f5 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.301 2021/07/16 09:00:23 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.313 2023/12/18 14:45:17 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1221,8 +1221,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
@@ -1228,8 +1228,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
sshbuf_dump(state->output, stderr);
#endif
/* increment sequence number for outgoing packets */
@ -290,19 +240,20 @@ index 96ff2ac..95c1dd1 100644
if (++state->p_send.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
@@ -1230,6 +1235,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
@@ -1237,6 +1242,12 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
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);
+ debug("%s: resetting send seqnr %u", __func__,
+ 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)
@@ -1362,8 +1372,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
@@ -1370,8 +1381,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
/* Stay in the loop until we have received a complete packet. */
for (;;) {
/* Try to read a packet from the buffer. */
@ -312,7 +263,7 @@ index 96ff2ac..95c1dd1 100644
break;
/* If we got a packet, return it. */
if (*typep != SSH_MSG_NONE)
@@ -1650,10 +1636,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
@@ -1658,10 +1668,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
goto out;
}
@ -330,18 +281,19 @@ index 96ff2ac..95c1dd1 100644
if (++state->p_read.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
@@ -1719,6 +1711,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
@@ -1727,6 +1743,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
#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);
+ debug("%s: resetting read seqnr %u", __func__,
+ state->p_read.seqnr);
+ state->p_read.seqnr = 0;
+ }
if ((r = ssh_packet_check_rekey(ssh)) != 0)
return r;
@@ -1739,10 +1735,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
@@ -1747,10 +1768,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
if (r != 0)
return r;
@ -351,7 +303,7 @@ index 96ff2ac..95c1dd1 100644
+ if (*typep == 0) {
+ /* no message ready */
+ return 0;
}
+ }
+ state->keep_alive_timeouts = 0;
+ DBG(debug("received packet type %d", *typep));
+
@ -369,7 +321,7 @@ index 96ff2ac..95c1dd1 100644
+ ssh_remote_port(ssh), reason, msg);
+ free(msg);
+ return SSH_ERR_DISCONNECTED;
+ }
}
+
+ /*
+ * Do not implicitly handle any messages here during initial
@ -384,7 +336,7 @@ index 96ff2ac..95c1dd1 100644
switch (*typep) {
case SSH2_MSG_IGNORE:
debug3("Received SSH2_MSG_IGNORE");
@@ -1757,19 +1782,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
@@ -1765,19 +1815,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
debug("Remote: %.900s", msg);
free(msg);
break;
@ -404,7 +356,7 @@ index 96ff2ac..95c1dd1 100644
case SSH2_MSG_UNIMPLEMENTED:
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
return r;
@@ -2288,6 +2300,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
@@ -2321,6 +2358,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
(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 ||
@ -412,7 +364,7 @@ index 96ff2ac..95c1dd1 100644
(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 ||
@@ -2450,6 +2463,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
@@ -2483,6 +2521,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
(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 ||
@ -420,35 +372,29 @@ index 96ff2ac..95c1dd1 100644
(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 ||
@@ -2778,6 +2792,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
@@ -2810,6 +2849,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+ debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf);
+ debug2("%s: sending SSH2_MSG_DISCONNECT: %s", __func__, 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 ||
diff --git a/packet.h b/packet.h
index b3d4280..047c111 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.93 2021/07/16 09:00:23 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.96 2023/12/18 14:45:17 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
diff --git a/sshconnect2.c b/sshconnect2.c
index 9267534..701e02d 100644
index 82846b5..1827f65 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.364 2023/03/06 12:14:48 dtucker Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.370 2023/12/18 14:45:17 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -427,7 +427,6 @@ struct cauthmethod {
@@ -236,7 +236,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
fatal_fr(r, "kex_assemble_namelist");
free(all_key);
- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
+ if ((s = kex_names_cat(options.kex_algorithms,
+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
fatal_f("kex_names_cat");
myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
@@ -430,7 +431,6 @@ struct cauthmethod {
};
static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
@ -456,7 +402,7 @@ index 9267534..701e02d 100644
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 *);
@@ -548,7 +547,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
@@ -554,7 +554,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
ssh->authctxt = &authctxt;
ssh_dispatch_init(ssh, &input_userauth_error);
@ -465,7 +411,7 @@ index 9267534..701e02d 100644
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);
@@ -604,13 +603,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
@@ -602,13 +602,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
return r;
}
@ -479,7 +425,7 @@ index 9267534..701e02d 100644
void
userauth(struct ssh *ssh, char *authlist)
{
@@ -692,6 +684,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
@@ -690,6 +683,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
free(authctxt->methoddata);
authctxt->methoddata = NULL;
authctxt->success = 1; /* break out */
@ -487,6 +433,34 @@ index 9267534..701e02d 100644
return 0;
}
diff --git a/sshd.c b/sshd.c
index ed5f075..e544b0c 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2494,10 +2494,13 @@ do_ssh2_kex(struct ssh *ssh)
char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
struct kex *kex;
char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
+ char *s;
int r;
- myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
- options.kex_algorithms);
+ if ((s = kex_names_cat(options.kex_algorithms,
+ "kex-strict-s-v00@openssh.com")) == NULL)
+ fatal("%s: kex_names_cat", __func__);
+ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
compat_cipher_proposal(ssh, options.ciphers);
@@ -2615,6 +2618,7 @@ do_ssh2_kex(struct ssh *ssh)
free(prop_kex);
free(prop_enc);
free(prop_hostkey);
+ free(s);
debug("KEX done");
}
--
2.33.0

View File

@ -1,41 +0,0 @@
From d95af508e78c0cd3dce56b83853baaa59ae295cf Mon Sep 17 00:00:00 2001
From: "dtucker@openbsd.org" <dtucker@openbsd.org>
Date: Sun, 12 Mar 2023 10:40:39 +0000
Subject: [PATCH] upstream: Limit number of entries in SSH2_MSG_EXT_INFO
request. This is already constrained by the maximum SSH packet size but this
makes it explicit. Prompted by Coverity CID 291868, ok djm@ markus@
OpenBSD-Commit-ID: aea023819aa44a2dcb9dd0fbec10561896fc3a09
Conflict:NA
Reference:https://github.com/openssh/openssh-portable/commit/d95af508e78c0cd3dce56b83853baaa59ae295cf
---
kex.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/kex.c b/kex.c
index b681c58..2afa087 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.176 2023/03/06 12:14:48 dtucker Exp $ */
+/* $OpenBSD: kex.c,v 1.178 2023/03/12 10:40:39 dtucker Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -603,6 +603,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
return r;
+ if (ninfo >= 1024) {
+ error("SSH2_MSG_EXT_INFO with too many entries, expected "
+ "<=1024, received %u", ninfo);
+ return SSH_ERR_INVALID_FORMAT;
+ }
for (i = 0; i < ninfo; i++) {
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
return r;
--
2.33.0

View File

@ -1,402 +0,0 @@
From 9641753e0fd146204d57b2a4165f552a81afade4 Mon Sep 17 00:00:00 2001
From: "dtucker@openbsd.org" <dtucker@openbsd.org>
Date: Mon, 6 Mar 2023 12:14:48 +0000
Subject: [PATCH] upstream: Refactor creation of KEX proposal.
This adds kex_proposal_populate_entries (and corresponding free) which
populates the KEX proposal array with dynamically allocated strings.
This replaces the previous mix of static and dynamic that has been the
source of previous leaks and bugs. Remove unused compat functions.
With & ok djm@.
OpenBSD-Commit-ID: f2f99da4aae2233cb18bf9c749320c5e040a9c7b
Reference:https://github.com/openssh/openssh-portable/commit/9641753e0fd146204d57b2a4165f552a81afade4
Conflict:Remove now-unused compat bit SSH_BUG_RSASIGMD5
gssapi-keyex
---
compat.c | 35 ++------------------------
compat.h | 6 ++---
kex.c | 58 ++++++++++++++++++++++++++++++++++++++++++-
kex.h | 5 +++-
sshconnect2.c | 68 +++++++++++++++++++--------------------------------
sshd.c | 37 +++++++++-------------------
6 files changed, 102 insertions(+), 107 deletions(-)
diff --git a/compat.c b/compat.c
index 555a372..4f8a1fb 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.121 2023/02/02 12:10:05 djm Exp $ */
+/* $OpenBSD: compat.c,v 1.126 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -36,7 +36,6 @@
#include "compat.h"
#include "log.h"
#include "match.h"
-#include "kex.h"
/* determine bug flags from SSH protocol banner */
void
@@ -158,37 +157,7 @@ compat_banner(struct ssh *ssh, const char *version)
/* Always returns pointer to allocated memory, caller must free. */
char *
-compat_cipher_proposal(struct ssh *ssh, char *cipher_prop)
-{
- if (!(ssh->compat & SSH_BUG_BIGENDIANAES))
- return xstrdup(cipher_prop);
- debug2_f("original cipher proposal: %s", cipher_prop);
- if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL)
- fatal("match_filter_denylist failed");
- debug2_f("compat cipher proposal: %s", cipher_prop);
- if (*cipher_prop == '\0')
- fatal("No supported ciphers found");
- return cipher_prop;
-}
-
-/* Always returns pointer to allocated memory, caller must free. */
-char *
-compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop)
-{
- if (!(ssh->compat & SSH_BUG_RSASIGMD5))
- return xstrdup(pkalg_prop);
- debug2_f("original public key proposal: %s", pkalg_prop);
- if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL)
- fatal("match_filter_denylist failed");
- debug2_f("compat public key proposal: %s", pkalg_prop);
- if (*pkalg_prop == '\0')
- fatal("No supported PK algorithms found");
- return pkalg_prop;
-}
-
-/* Always returns pointer to allocated memory, caller must free. */
-char *
-compat_kex_proposal(struct ssh *ssh, char *p)
+compat_kex_proposal(struct ssh *ssh, const char *p)
{
char *cp = NULL, *cp2 = NULL;
diff --git a/compat.h b/compat.h
index 167409b..013c855 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.h,v 1.57 2021/06/06 03:40:39 djm Exp $ */
+/* $OpenBSD: compat.h,v 1.62 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -61,7 +61,5 @@
struct ssh;
void compat_banner(struct ssh *, const char *);
-char *compat_cipher_proposal(struct ssh *, char *);
-char *compat_pkalg_proposal(struct ssh *, char *);
-char *compat_kex_proposal(struct ssh *, char *);
+char *compat_kex_proposal(struct ssh *, const char *);
#endif
diff --git a/kex.c b/kex.c
index e8c2741..b681c58 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.168 2021/04/03 06:18:40 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.176 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -60,6 +60,7 @@
#include "misc.h"
#include "dispatch.h"
#include "monitor.h"
+#include "myproposal.h"
#include "xmalloc.h"
#include "ssherr.h"
@@ -359,6 +360,61 @@ kex_assemble_names(char **listp, const char *def, const char *all)
return r;
}
+/*
+ * Fill out a proposal array with dynamically allocated values, which may
+ * be modified as required for compatibility reasons.
+ * Any of the options may be NULL, in which case the default is used.
+ * Array contents must be freed by calling kex_proposal_free_entries.
+ */
+void
+kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
+ const char *kexalgos, const char *ciphers, const char *macs,
+ const char *comp, const char *hkalgs)
+{
+ const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
+ const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
+ const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
+ u_int i;
+
+ if (prop == NULL)
+ fatal_f("proposal missing");
+
+ for (i = 0; i < PROPOSAL_MAX; i++) {
+ switch(i) {
+ case PROPOSAL_KEX_ALGS:
+ prop[i] = compat_kex_proposal(ssh,
+ kexalgos ? kexalgos : defprop[i]);
+ break;
+ case PROPOSAL_ENC_ALGS_CTOS:
+ case PROPOSAL_ENC_ALGS_STOC:
+ prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
+ break;
+ case PROPOSAL_MAC_ALGS_CTOS:
+ case PROPOSAL_MAC_ALGS_STOC:
+ prop[i] = xstrdup(macs ? macs : defprop[i]);
+ break;
+ case PROPOSAL_COMP_ALGS_CTOS:
+ case PROPOSAL_COMP_ALGS_STOC:
+ prop[i] = xstrdup(comp ? comp : defprop[i]);
+ break;
+ case PROPOSAL_SERVER_HOST_KEY_ALGS:
+ prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
+ break;
+ default:
+ prop[i] = xstrdup(defprop[i]);
+ }
+ }
+}
+
+void
+kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
+{
+ u_int i;
+
+ for (i = 0; i < PROPOSAL_MAX; i++)
+ free(prop[i]);
+}
+
/* Validate GSS KEX method name list */
int
kex_gss_names_valid(const char *names)
diff --git a/kex.h b/kex.h
index 8b95227..87ba7c8 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.114 2021/01/31 22:55:29 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.118 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -192,6 +192,9 @@ char *kex_alg_list(char);
char *kex_gss_alg_list(char);
char *kex_names_cat(const char *, const char *);
int kex_assemble_names(char **, const char *, const char *);
+void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX],
+ const char *, const char *, const char *, const char *, const char *);
+void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]);
int kex_gss_names_valid(const char *);
int kex_exchange_identification(struct ssh *, int, const char *);
diff --git a/sshconnect2.c b/sshconnect2.c
index eb0df92..9267534 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.359 2022/07/01 03:39:44 dtucker Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.364 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -58,7 +58,6 @@
#include "cipher.h"
#include "sshkey.h"
#include "kex.h"
-#include "myproposal.h"
#include "sshconnect.h"
#include "authfile.h"
#include "dh.h"
@@ -216,11 +215,9 @@ void
ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
const struct ssh_conn_info *cinfo)
{
- char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
- char *s, *all_key;
- char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
- int r, use_known_hosts_order = 0;
-
+ char *myproposal[PROPOSAL_MAX];
+ char *s, *all_key, *hkalgs = NULL;
+ int r;
#if defined(GSSAPI) && defined(WITH_OPENSSL)
char *orig = NULL, *gss = NULL;
char *gss_host = NULL;
@@ -230,15 +227,9 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
xxx_hostaddr = hostaddr;
xxx_conn_info = cinfo;
- /*
- * If the user has not specified HostkeyAlgorithms, or has only
- * appended or removed algorithms from that list then prefer algorithms
- * that are in the list that are supported by known_hosts keys.
- */
- if (options.hostkeyalgorithms == NULL ||
- options.hostkeyalgorithms[0] == '-' ||
- options.hostkeyalgorithms[0] == '+')
- use_known_hosts_order = 1;
+ if (options.rekey_limit || options.rekey_interval)
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
+ options.rekey_interval);
/* Expand or fill in HostkeyAlgorithms */
all_key = sshkey_alg_list(0, 0, 1, ',');
@@ -249,25 +240,22 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
fatal_f("kex_names_cat");
- myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s);
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
- compat_cipher_proposal(ssh, options.ciphers);
- myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] =
- (char *)compression_alg_list(options.compression);
- myproposal[PROPOSAL_MAC_ALGS_CTOS] =
- myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
- if (use_known_hosts_order) {
- /* Query known_hosts and prefer algorithms that appear there */
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
- compat_pkalg_proposal(ssh,
- order_hostkeyalgs(host, hostaddr, port, cinfo));
- } else {
- /* Use specified HostkeyAlgorithms exactly */
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
- compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
- }
+
+ /*
+ * If the user has not specified HostkeyAlgorithms, or has only
+ * appended or removed algorithms from that list then prefer algorithms
+ * that are in the list that are supported by known_hosts keys.
+ */
+ if (options.hostkeyalgorithms == NULL ||
+ options.hostkeyalgorithms[0] == '-' ||
+ options.hostkeyalgorithms[0] == '+')
+ hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
+
+ kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers,
+ options.macs, compression_alg_list(options.compression),
+ hkalgs ? hkalgs : options.hostkeyalgorithms);
+
+ free(hkalgs);
#if defined(GSSAPI) && defined(WITH_OPENSSL)
if (options.gss_keyex) {
@@ -310,10 +298,6 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
}
#endif
- if (options.rekey_limit || options.rekey_interval)
- ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
- options.rekey_interval);
-
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
fatal_r(r, "kex_setup");
@@ -357,6 +341,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
/* remove ext-info from the KEX proposals for rekeying */
+ free(myproposal[PROPOSAL_KEX_ALGS]);
myproposal[PROPOSAL_KEX_ALGS] =
compat_kex_proposal(ssh, options.kex_algorithms);
#if defined(GSSAPI) && defined(WITH_OPENSSL)
@@ -380,10 +365,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
(r = ssh_packet_write_wait(ssh)) != 0)
fatal_fr(r, "send packet");
#endif
- /* Free only parts of proposal that were dynamically allocated here. */
- free(prop_kex);
- free(prop_enc);
- free(prop_hostkey);
+ kex_proposal_free_entries(myproposal);
}
/*
diff --git a/sshd.c b/sshd.c
index dd7e1d4..aa3c3b7 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.594 2022/12/16 06:56:47 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.599 2023/03/06 12:14:48 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -107,7 +107,6 @@
#include "digest.h"
#include "sshkey.h"
#include "kex.h"
-#include "myproposal.h"
#include "authfile.h"
#include "pathnames.h"
#include "atomicio.h"
@@ -2524,33 +2523,23 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
static void
do_ssh2_kex(struct ssh *ssh)
{
- char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
+ char *hkalgs = NULL, *myproposal[PROPOSAL_MAX];
+ const char *compression = NULL;
struct kex *kex;
- char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
int r;
- myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
- options.kex_algorithms);
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
- compat_cipher_proposal(ssh, options.ciphers);
- myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh,
- options.ciphers);
- myproposal[PROPOSAL_MAC_ALGS_CTOS] =
- myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
-
- if (options.compression == COMP_NONE) {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
- }
-
if (options.rekey_limit || options.rekey_interval)
ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
- /* coverity[leaked_storage : FALSE]*/
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
- compat_pkalg_proposal(ssh, list_hostkey_types());
+ if (options.compression == COMP_NONE)
+ compression = "none";
+ hkalgs = list_hostkey_types();
+
+ kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms,
+ options.ciphers, options.macs, compression, hkalgs);
+
+ free(hkalgs);
#if defined(GSSAPI) && defined(WITH_OPENSSL)
{
char *orig;
@@ -2645,9 +2634,7 @@ do_ssh2_kex(struct ssh *ssh)
(r = ssh_packet_write_wait(ssh)) != 0)
fatal_fr(r, "send test");
#endif
- free(prop_kex);
- free(prop_enc);
- free(prop_hostkey);
+ kex_proposal_free_entries(myproposal);
debug("KEX done");
}
--
2.33.0

View File

@ -6,7 +6,7 @@
%{?no_gtk2:%global gtk2 0}
%global sshd_uid 74
%global openssh_release 25
%global openssh_release 26
Name: openssh
Version: 8.8p1
@ -129,10 +129,8 @@ Patch98: backport-upstream-test-compat_kex_proposal-by-dtucker.patch
Patch99: backport-adapt-compat_kex_proposal-test-to-portable.patch
Patch100: backport-fix-CVE-2023-38408-upstream-terminate-process.patch
Patch101: backport-upstream-In-channel_request_remote_forwarding-the-pa.patch
Patch102: backport-upstream-Refactor-creation-of-KEX-proposal.patch
Patch103: backport-upstream-Limit-number-of-entries-in-SSH2_MSG_EXT_INF.patch
Patch104: backport-CVE-2023-48795-upstream-implement-strict-key-exchange-in-ssh-and-ss.patch
Patch105: backport-CVE-2023-51385-upstream-ban-user-hostnames-with-most-shell-metachar.patch
Patch102: backport-CVE-2023-51385-upstream-ban-user-hostnames-with-most-shell-metachar.patch
Patch103: backport-CVE-2023-48795.patch
Requires: /sbin/nologin
Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8
@ -314,8 +312,6 @@ popd
%patch101 -p1
%patch102 -p1
%patch103 -p1
%patch104 -p1
%patch105 -p1
autoreconf
pushd pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4
@ -512,6 +508,12 @@ getent passwd sshd >/dev/null || \
%attr(0644,root,root) %{_mandir}/man8/sftp-server.8*
%changelog
* Wed Jan 10 2024 renmingshuai<renmingshuai@huawei.com> - 8.8p1-26
- Type:CVE
- CVE:CVE-2023-48795
- SUG:NA
- DESC:fix CVE-2023-48795 by using the other patch instead
* Sat Dec 23 2023 renmingshuai<renmingshuai@huawei.com> - 8.8p1-25
- Type:CVE
- CVE:CVE-2023-48795,CVE-2023-51385