summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch')
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch315
1 files changed, 315 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch
new file mode 100644
index 0000000000..141c8113bf
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch
@@ -0,0 +1,315 @@
1From c30158ea225cf8ad67c3dcc88fa9e4afbf8959a7 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Tue, 26 Jan 2021 00:53:31 +0000
4Subject: [PATCH 08/12] upstream: more ssh-agent refactoring
5
6Allow confirm_key() to accept an additional reason suffix
7
8Factor publickey userauth parsing out into its own function and allow
9it to optionally return things it parsed out of the message to its
10caller.
11
12feedback/ok markus@
13
14OpenBSD-Commit-ID: 29006515617d1aa2d8b85cd2bf667e849146477e
15
16Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/e0e8bee8024fa9e31974244d14f03d799e5c0775]
17CVE: CVE-2023-38408
18Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
19---
20 ssh-agent.c | 197 ++++++++++++++++++++++++++++++++++------------------
21 1 file changed, 130 insertions(+), 67 deletions(-)
22
23diff --git a/ssh-agent.c b/ssh-agent.c
24index 2635bc5..7ad323c 100644
25--- a/ssh-agent.c
26+++ b/ssh-agent.c
27@@ -1,4 +1,4 @@
28-/* $OpenBSD: ssh-agent.c,v 1.269 2021/01/26 00:47:47 djm Exp $ */
29+/* $OpenBSD: ssh-agent.c,v 1.270 2021/01/26 00:53:31 djm Exp $ */
30 /*
31 * Author: Tatu Ylonen <ylo@cs.hut.fi>
32 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
33@@ -216,15 +216,16 @@ lookup_identity(struct sshkey *key)
34
35 /* Check confirmation of keysign request */
36 static int
37-confirm_key(Identity *id)
38+confirm_key(Identity *id, const char *extra)
39 {
40 char *p;
41 int ret = -1;
42
43 p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
44 if (p != NULL &&
45- ask_permission("Allow use of key %s?\nKey fingerprint %s.",
46- id->comment, p))
47+ ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
48+ id->comment, p,
49+ extra == NULL ? "" : "\n", extra == NULL ? "" : extra))
50 ret = 0;
51 free(p);
52
53@@ -290,74 +291,133 @@ agent_decode_alg(struct sshkey *key, u_int flags)
54 }
55
56 /*
57- * This function inspects a message to be signed by a FIDO key that has a
58- * web-like application string (i.e. one that does not begin with "ssh:".
59- * It checks that the message is one of those expected for SSH operations
60- * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
61- * for the web.
62+ * Attempt to parse the contents of a buffer as a SSH publickey userauth
63+ * request, checking its contents for consistency and matching the embedded
64+ * key against the one that is being used for signing.
65+ * Note: does not modify msg buffer.
66+ * Optionally extract the username and session ID from the request.
67 */
68 static int
69-check_websafe_message_contents(struct sshkey *key,
70- const u_char *msg, size_t len)
71+parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
72+ char **userp, struct sshbuf **sess_idp)
73 {
74- int matched = 0;
75- struct sshbuf *b;
76- u_char m, n;
77- char *cp1 = NULL, *cp2 = NULL;
78+ struct sshbuf *b = NULL, *sess_id = NULL;
79+ char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
80 int r;
81+ u_char t, sig_follows;
82 struct sshkey *mkey = NULL;
83
84- if ((b = sshbuf_from(msg, len)) == NULL)
85- fatal("%s: sshbuf_new", __func__);
86+ if (userp != NULL)
87+ *userp = NULL;
88+ if (sess_idp != NULL)
89+ *sess_idp = NULL;
90+ if ((b = sshbuf_fromb(msg)) == NULL)
91+ fatal("%s: sshbuf_fromb", __func__);
92
93 /* SSH userauth request */
94- if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */
95- (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */
96- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */
97- (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */
98- (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */
99- (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */
100- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */
101- (r = sshkey_froms(b, &mkey)) == 0 && /* key */
102- sshbuf_len(b) == 0) {
103- debug("%s: parsed userauth", __func__);
104- if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 &&
105- strcmp(cp1, "ssh-connection") == 0 &&
106- strcmp(cp2, "publickey") == 0 &&
107- sshkey_equal(key, mkey)) {
108- debug("%s: well formed userauth", __func__);
109- matched = 1;
110- }
111+ if ((r = sshbuf_froms(b, &sess_id)) != 0)
112+ goto out;
113+ if (sshbuf_len(sess_id) == 0) {
114+ r = SSH_ERR_INVALID_FORMAT;
115+ goto out;
116 }
117- free(cp1);
118- free(cp2);
119- sshkey_free(mkey);
120+ if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
121+ (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */
122+ (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */
123+ (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */
124+ (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */
125+ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */
126+ (r = sshkey_froms(b, &mkey)) != 0) /* key */
127+ goto out;
128+ if (t != SSH2_MSG_USERAUTH_REQUEST ||
129+ sig_follows != 1 ||
130+ strcmp(service, "ssh-connection") != 0 ||
131+ !sshkey_equal(expected_key, mkey) ||
132+ sshkey_type_from_name(pkalg) != expected_key->type) {
133+ r = SSH_ERR_INVALID_FORMAT;
134+ goto out;
135+ }
136+ if (strcmp(method, "publickey") != 0) {
137+ r = SSH_ERR_INVALID_FORMAT;
138+ goto out;
139+ }
140+ if (sshbuf_len(b) != 0) {
141+ r = SSH_ERR_INVALID_FORMAT;
142+ goto out;
143+ }
144+ /* success */
145+ r = 0;
146+ debug("%s: well formed userauth", __func__);
147+ if (userp != NULL) {
148+ *userp = user;
149+ user = NULL;
150+ }
151+ if (sess_idp != NULL) {
152+ *sess_idp = sess_id;
153+ sess_id = NULL;
154+ }
155+ out:
156 sshbuf_free(b);
157- if (matched)
158- return 1;
159+ sshbuf_free(sess_id);
160+ free(user);
161+ free(service);
162+ free(method);
163+ free(pkalg);
164+ sshkey_free(mkey);
165+ return r;
166+}
167
168- if ((b = sshbuf_from(msg, len)) == NULL)
169- fatal("%s: sshbuf_new", __func__);
170- cp1 = cp2 = NULL;
171- mkey = NULL;
172-
173- /* SSHSIG */
174- if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 &&
175- (r = sshbuf_consume(b, 6)) == 0 &&
176- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */
177- (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */
178- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */
179- (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */
180- sshbuf_len(b) == 0) {
181- debug("%s: parsed sshsig", __func__);
182- matched = 1;
183- }
184+/*
185+ * Attempt to parse the contents of a buffer as a SSHSIG signature request.
186+ * Note: does not modify buffer.
187+ */
188+static int
189+parse_sshsig_request(struct sshbuf *msg)
190+{
191+ int r;
192+ struct sshbuf *b;
193
194+ if ((b = sshbuf_fromb(msg)) == NULL)
195+ fatal("%s: sshbuf_fromb", __func__);
196+
197+ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 ||
198+ (r = sshbuf_consume(b, 6)) != 0 ||
199+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */
200+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */
201+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */
202+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */
203+ goto out;
204+ if (sshbuf_len(b) != 0) {
205+ r = SSH_ERR_INVALID_FORMAT;
206+ goto out;
207+ }
208+ /* success */
209+ r = 0;
210+ out:
211 sshbuf_free(b);
212- if (matched)
213+ return r;
214+}
215+
216+/*
217+ * This function inspects a message to be signed by a FIDO key that has a
218+ * web-like application string (i.e. one that does not begin with "ssh:".
219+ * It checks that the message is one of those expected for SSH operations
220+ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
221+ * for the web.
222+ */
223+static int
224+check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
225+{
226+ if (parse_userauth_request(data, key, NULL, NULL) == 0) {
227+ debug("%s: signed data matches public key userauth request", __func__);
228 return 1;
229+ }
230+ if (parse_sshsig_request(data) == 0) {
231+ debug("%s: signed data matches SSHSIG signature request", __func__);
232+ return 1;
233+ }
234
235- /* XXX CA signature operation */
236+ /* XXX check CA signature operation */
237
238 error("web-origin key attempting to sign non-SSH message");
239 return 0;
240@@ -367,21 +427,22 @@ check_websafe_message_contents(struct sshkey *key,
241 static void
242 process_sign_request2(SocketEntry *e)
243 {
244- const u_char *data;
245 u_char *signature = NULL;
246- size_t dlen, slen = 0;
247+ size_t i, slen = 0;
248 u_int compat = 0, flags;
249 int r, ok = -1;
250 char *fp = NULL;
251- struct sshbuf *msg;
252+ struct sshbuf *msg = NULL, *data = NULL;
253 struct sshkey *key = NULL;
254 struct identity *id;
255 struct notifier_ctx *notifier = NULL;
256
257- if ((msg = sshbuf_new()) == NULL)
258+ debug("%s: entering", __func__);
259+
260+ if ((msg = sshbuf_new()) == NULL | (data = sshbuf_new()) == NULL)
261 fatal("%s: sshbuf_new failed", __func__);
262 if ((r = sshkey_froms(e->request, &key)) != 0 ||
263- (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
264+ (r = sshbuf_get_stringb(e->request, data)) != 0 ||
265 (r = sshbuf_get_u32(e->request, &flags)) != 0) {
266 error("%s: couldn't parse request: %s", __func__, ssh_err(r));
267 goto send;
268@@ -391,13 +452,13 @@ process_sign_request2(SocketEntry *e)
269 verbose("%s: %s key not found", __func__, sshkey_type(key));
270 goto send;
271 }
272- if (id->confirm && confirm_key(id) != 0) {
273+ if (id->confirm && confirm_key(id, NULL) != 0) {
274 verbose("%s: user refused key", __func__);
275 goto send;
276 }
277 if (sshkey_is_sk(id->key)) {
278 if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
279- !check_websafe_message_contents(key, data, dlen)) {
280+ !check_websafe_message_contents(key, data)) {
281 /* error already logged */
282 goto send;
283 }
284@@ -411,7 +472,7 @@ process_sign_request2(SocketEntry *e)
285 }
286 }
287 if ((r = sshkey_sign(id->key, &signature, &slen,
288- data, dlen, agent_decode_alg(key, flags),
289+ sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags),
290 id->sk_provider, compat)) != 0) {
291 error("%s: sshkey_sign: %s", __func__, ssh_err(r));
292 goto send;
293@@ -420,8 +481,7 @@ process_sign_request2(SocketEntry *e)
294 ok = 0;
295 send:
296 notify_complete(notifier);
297- sshkey_free(key);
298- free(fp);
299+
300 if (ok == 0) {
301 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
302 (r = sshbuf_put_string(msg, signature, slen)) != 0)
303@@ -432,7 +492,10 @@ process_sign_request2(SocketEntry *e)
304 if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
305 fatal("%s: buffer error: %s", __func__, ssh_err(r));
306
307+ sshbuf_free(data);
308 sshbuf_free(msg);
309+ sshkey_free(key);
310+ free(fp);
311 free(signature);
312 }
313
314--
3152.41.0