summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch')
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch307
1 files changed, 307 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch
new file mode 100644
index 0000000000..c300393ebf
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch
@@ -0,0 +1,307 @@
1From 2b3b369c8cf71f9ef5942a5e074e6f86e7ca1e0c Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Sun, 19 Dec 2021 22:09:23 +0000
4Subject: [PATCH 11/12] upstream: ssh-agent side of binding
5
6record session ID/hostkey/forwarding status for each active socket.
7
8Attempt to parse data-to-be-signed at signature request time and extract
9session ID from the blob if it is a pubkey userauth request.
10
11ok markus@
12
13OpenBSD-Commit-ID: a80fd41e292b18b67508362129e9fed549abd318
14
15Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/4c1e3ce85e183a9d0c955c88589fed18e4d6a058]
16CVE: CVE-2023-38408
17Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
18---
19 authfd.h | 3 +
20 ssh-agent.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++---
21 2 files changed, 170 insertions(+), 8 deletions(-)
22
23diff --git a/authfd.h b/authfd.h
24index c3bf625..9cc9807 100644
25--- a/authfd.h
26+++ b/authfd.h
27@@ -76,6 +76,9 @@ int ssh_agent_sign(int sock, const struct sshkey *key,
28 #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
29 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
30
31+/* generic extension mechanism */
32+#define SSH_AGENTC_EXTENSION 27
33+
34 #define SSH_AGENT_CONSTRAIN_LIFETIME 1
35 #define SSH_AGENT_CONSTRAIN_CONFIRM 2
36 #define SSH_AGENT_CONSTRAIN_MAXSIGN 3
37diff --git a/ssh-agent.c b/ssh-agent.c
38index 7f1e14b..01c7f2b 100644
39--- a/ssh-agent.c
40+++ b/ssh-agent.c
41@@ -1,4 +1,4 @@
42-/* $OpenBSD: ssh-agent.c,v 1.275 2021/01/29 06:29:46 djm Exp $ */
43+/* $OpenBSD: ssh-agent.c,v 1.280 2021/12/19 22:09:23 djm Exp $ */
44 /*
45 * Author: Tatu Ylonen <ylo@cs.hut.fi>
46 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
47@@ -98,9 +98,15 @@
48 #endif
49
50 /* Maximum accepted message length */
51-#define AGENT_MAX_LEN (256*1024)
52+#define AGENT_MAX_LEN (256*1024)
53 /* Maximum bytes to read from client socket */
54-#define AGENT_RBUF_LEN (4096)
55+#define AGENT_RBUF_LEN (4096)
56+/* Maximum number of recorded session IDs/hostkeys per connection */
57+#define AGENT_MAX_SESSION_IDS 16
58+/* Maximum size of session ID */
59+#define AGENT_MAX_SID_LEN 128
60+
61+/* XXX store hostkey_sid in a refcounted tree */
62
63 typedef enum {
64 AUTH_UNUSED = 0,
65@@ -108,12 +114,20 @@ typedef enum {
66 AUTH_CONNECTION = 2,
67 } sock_type;
68
69+struct hostkey_sid {
70+ struct sshkey *key;
71+ struct sshbuf *sid;
72+ int forwarded;
73+};
74+
75 typedef struct socket_entry {
76 int fd;
77 sock_type type;
78 struct sshbuf *input;
79 struct sshbuf *output;
80 struct sshbuf *request;
81+ size_t nsession_ids;
82+ struct hostkey_sid *session_ids;
83 } SocketEntry;
84
85 u_int sockets_alloc = 0;
86@@ -174,10 +188,17 @@ static int restrict_websafe = 1;
87 static void
88 close_socket(SocketEntry *e)
89 {
90+ size_t i;
91+
92 close(e->fd);
93 sshbuf_free(e->input);
94 sshbuf_free(e->output);
95 sshbuf_free(e->request);
96+ for (i = 0; i < e->nsession_ids; i++) {
97+ sshkey_free(e->session_ids[i].key);
98+ sshbuf_free(e->session_ids[i].sid);
99+ }
100+ free(e->session_ids);
101 memset(e, '\0', sizeof(*e));
102 e->fd = -1;
103 e->type = AUTH_UNUSED;
104@@ -423,6 +444,18 @@ check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
105 return 0;
106 }
107
108+static int
109+buf_equal(const struct sshbuf *a, const struct sshbuf *b)
110+{
111+ if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL)
112+ return SSH_ERR_INVALID_ARGUMENT;
113+ if (sshbuf_len(a) != sshbuf_len(b))
114+ return SSH_ERR_INVALID_FORMAT;
115+ if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0)
116+ return SSH_ERR_INVALID_FORMAT;
117+ return 0;
118+}
119+
120 /* ssh2 only */
121 static void
122 process_sign_request2(SocketEntry *e)
123@@ -431,8 +464,8 @@ process_sign_request2(SocketEntry *e)
124 size_t i, slen = 0;
125 u_int compat = 0, flags;
126 int r, ok = -1;
127- char *fp = NULL;
128- struct sshbuf *msg = NULL, *data = NULL;
129+ char *fp = NULL, *user = NULL, *sig_dest = NULL;
130+ struct sshbuf *msg = NULL, *data = NULL, *sid = NULL;
131 struct sshkey *key = NULL;
132 struct identity *id;
133 struct notifier_ctx *notifier = NULL;
134@@ -452,7 +485,33 @@ process_sign_request2(SocketEntry *e)
135 verbose("%s: %s key not found", __func__, sshkey_type(key));
136 goto send;
137 }
138- if (id->confirm && confirm_key(id, NULL) != 0) {
139+ /*
140+ * If session IDs were recorded for this socket, then use them to
141+ * annotate the confirmation messages with the host keys.
142+ */
143+ if (e->nsession_ids > 0 &&
144+ parse_userauth_request(data, key, &user, &sid) == 0) {
145+ /*
146+ * session ID from userauth request should match the final
147+ * ID in the list recorded in the socket, unless the ssh
148+ * client at that point lacks the binding extension (or if
149+ * an attacker is trying to steal use of the agent).
150+ */
151+ i = e->nsession_ids - 1;
152+ if (buf_equal(sid, e->session_ids[i].sid) == 0) {
153+ if ((fp = sshkey_fingerprint(e->session_ids[i].key,
154+ SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL)
155+ fatal("%s: fingerprint failed", __func__);
156+ debug3("%s: destination %s %s (slot %zu)", __func__,
157+ sshkey_type(e->session_ids[i].key), fp, i);
158+ xasprintf(&sig_dest, "public key request for "
159+ "target user \"%s\" to %s %s", user,
160+ sshkey_type(e->session_ids[i].key), fp);
161+ free(fp);
162+ fp = NULL;
163+ }
164+ }//
165+ if (id->confirm && confirm_key(id, sig_dest) != 0) {
166 verbose("%s: user refused key", __func__);
167 goto send;
168 }
169@@ -467,8 +526,10 @@ process_sign_request2(SocketEntry *e)
170 SSH_FP_DEFAULT)) == NULL)
171 fatal("%s: fingerprint failed", __func__);
172 notifier = notify_start(0,
173- "Confirm user presence for key %s %s",
174- sshkey_type(id->key), fp);
175+ "Confirm user presence for key %s %s%s%s",
176+ sshkey_type(id->key), fp,
177+ sig_dest == NULL ? "" : "\n",
178+ sig_dest == NULL ? "" : sig_dest);
179 }
180 }
181 if ((r = sshkey_sign(id->key, &signature, &slen,
182@@ -492,11 +553,14 @@ process_sign_request2(SocketEntry *e)
183 if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
184 fatal("%s: buffer error: %s", __func__, ssh_err(r));
185
186+ sshbuf_free(sid);
187 sshbuf_free(data);
188 sshbuf_free(msg);
189 sshkey_free(key);
190 free(fp);
191 free(signature);
192+ free(sig_dest);
193+ free(user);
194 }
195
196 /* shared */
197@@ -925,6 +989,98 @@ send:
198 }
199 #endif /* ENABLE_PKCS11 */
200
201+static int
202+process_ext_session_bind(SocketEntry *e)
203+{
204+ int r, sid_match, key_match;
205+ struct sshkey *key = NULL;
206+ struct sshbuf *sid = NULL, *sig = NULL;
207+ char *fp = NULL;
208+ u_char fwd;
209+ size_t i;
210+
211+ debug2("%s: entering", __func__);
212+ if ((r = sshkey_froms(e->request, &key)) != 0 ||
213+ (r = sshbuf_froms(e->request, &sid)) != 0 ||
214+ (r = sshbuf_froms(e->request, &sig)) != 0 ||
215+ (r = sshbuf_get_u8(e->request, &fwd)) != 0) {
216+ error("%s: parse: %s", __func__, ssh_err(r));
217+ goto out;
218+ }
219+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
220+ SSH_FP_DEFAULT)) == NULL)
221+ fatal("%s: fingerprint failed", __func__);
222+ /* check signature with hostkey on session ID */
223+ if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig),
224+ sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) {
225+ error("%s: sshkey_verify for %s %s: %s", __func__, sshkey_type(key), fp, ssh_err(r));
226+ goto out;
227+ }
228+ /* check whether sid/key already recorded */
229+ for (i = 0; i < e->nsession_ids; i++) {
230+ sid_match = buf_equal(sid, e->session_ids[i].sid) == 0;
231+ key_match = sshkey_equal(key, e->session_ids[i].key);
232+ if (sid_match && key_match) {
233+ debug("%s: session ID already recorded for %s %s", __func__,
234+ sshkey_type(key), fp);
235+ r = 0;
236+ goto out;
237+ } else if (sid_match) {
238+ error("%s: session ID recorded against different key "
239+ "for %s %s", __func__, sshkey_type(key), fp);
240+ r = -1;
241+ goto out;
242+ }
243+ /*
244+ * new sid with previously-seen key can happen, e.g. multiple
245+ * connections to the same host.
246+ */
247+ }
248+ /* record new key/sid */
249+ if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) {
250+ error("%s: too many session IDs recorded", __func__);
251+ goto out;
252+ }
253+ e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids,
254+ e->nsession_ids + 1, sizeof(*e->session_ids));
255+ i = e->nsession_ids++;
256+ debug("%s: recorded %s %s (slot %zu of %d)", __func__, sshkey_type(key), fp, i,
257+ AGENT_MAX_SESSION_IDS);
258+ e->session_ids[i].key = key;
259+ e->session_ids[i].forwarded = fwd != 0;
260+ key = NULL; /* transferred */
261+ /* can't transfer sid; it's refcounted and scoped to request's life */
262+ if ((e->session_ids[i].sid = sshbuf_new()) == NULL)
263+ fatal("%s: sshbuf_new", __func__);
264+ if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0)
265+ fatal("%s: sshbuf_putb session ID: %s", __func__, ssh_err(r));
266+ /* success */
267+ r = 0;
268+ out:
269+ sshkey_free(key);
270+ sshbuf_free(sid);
271+ sshbuf_free(sig);
272+ return r == 0 ? 1 : 0;
273+}
274+
275+static void
276+process_extension(SocketEntry *e)
277+{
278+ int r, success = 0;
279+ char *name;
280+
281+ debug2("%s: entering", __func__);
282+ if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) {
283+ error("%s: parse: %s", __func__, ssh_err(r));
284+ goto send;
285+ }
286+ if (strcmp(name, "session-bind@openssh.com") == 0)
287+ success = process_ext_session_bind(e);
288+ else
289+ debug("%s: unsupported extension \"%s\"", __func__, name);
290+send:
291+ send_status(e, success);
292+}
293 /*
294 * dispatch incoming message.
295 * returns 1 on success, 0 for incomplete messages or -1 on error.
296@@ -1019,6 +1175,9 @@ process_message(u_int socknum)
297 process_remove_smartcard_key(e);
298 break;
299 #endif /* ENABLE_PKCS11 */
300+ case SSH_AGENTC_EXTENSION:
301+ process_extension(e);
302+ break;
303 default:
304 /* Unknown message. Respond with failure. */
305 error("Unknown message %d", type);
306--
3072.41.0