summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShubham Kulkarni <skulkarni@mvista.com>2023-09-06 13:28:50 +0530
committerSteve Sakoman <steve@sakoman.com>2023-09-15 03:47:11 -1000
commit0485ee7a6b889f7161732435bb1136bd86954f44 (patch)
treee81c430345c3559ae9cf1b99729898bd3e34b3b0
parent90175073f614c8430e1ed694501df4e5474d57aa (diff)
downloadpoky-0485ee7a6b889f7161732435bb1136bd86954f44.tar.gz
openssh: Securiry fix for CVE-2023-38408
The PKCS#11 feature in ssh-agent in OpenSSH before 9.3p2 has an insufficiently trustworthy search path, leading to remote code execution if an agent is forwarded to an attacker-controlled system. (Code in /usr/lib is not necessarily safe for loading into ssh-agent.) NOTE: this issue exists because of an incomplete fix for CVE-2016-10009. References: https://nvd.nist.gov/vuln/detail/CVE-2023-38408 Upstream patches: https://github.com/openssh/openssh-portable/commit/dee22129, https://github.com/openssh/openssh-portable/commit/099cdf59, https://github.com/openssh/openssh-portable/commit/29ef8a04, https://github.com/openssh/openssh-portable/commit/892506b1, https://github.com/openssh/openssh-portable/commit/0c111eb8, https://github.com/openssh/openssh-portable/commit/52a03e9f, https://github.com/openssh/openssh-portable/commit/1fe16fd6, https://github.com/openssh/openssh-portable/commit/e0e8bee8, https://github.com/openssh/openssh-portable/commit/8afaa7d7, https://github.com/openssh/openssh-portable/commit/1a4b9275, https://github.com/openssh/openssh-portable/commit/4c1e3ce8, https://github.com/openssh/openssh-portable/commit/1f2731f5. (From OE-Core rev: 9242b8218858d2bebb3235929fea7e7235cd40f3) Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-01.patch189
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-02.patch581
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-03.patch171
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-04.patch34
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch194
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-06.patch73
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-07.patch125
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-08.patch315
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-09.patch38
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-10.patch39
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-11.patch307
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-12.patch120
-rw-r--r--meta/recipes-connectivity/openssh/openssh_8.2p1.bb12
13 files changed, 2198 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-01.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-01.patch
new file mode 100644
index 0000000000..c899056337
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-01.patch
@@ -0,0 +1,189 @@
1From f6213e03887237714eb5bcfc9089c707069f87c5 Mon Sep 17 00:00:00 2001
2From: Damien Miller <djm@mindrot.org>
3Date: Fri, 1 Oct 2021 16:35:49 +1000
4Subject: [PATCH 01/12] make OPENSSL_HAS_ECC checks more thorough
5
6ok dtucker
7
8Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/dee22129bbc61e25b1003adfa2bc584c5406ef2d]
9CVE: CVE-2023-38408
10Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
11---
12 ssh-pkcs11-client.c | 16 ++++++++--------
13 ssh-pkcs11.c | 26 +++++++++++++-------------
14 2 files changed, 21 insertions(+), 21 deletions(-)
15
16diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
17index 8a0ffef..41114c7 100644
18--- a/ssh-pkcs11-client.c
19+++ b/ssh-pkcs11-client.c
20@@ -163,7 +163,7 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
21 return (ret);
22 }
23
24-#ifdef HAVE_EC_KEY_METHOD_NEW
25+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
26 static ECDSA_SIG *
27 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
28 const BIGNUM *rp, EC_KEY *ec)
29@@ -220,12 +220,12 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
30 sshbuf_free(msg);
31 return (ret);
32 }
33-#endif /* HAVE_EC_KEY_METHOD_NEW */
34+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
35
36 static RSA_METHOD *helper_rsa;
37-#ifdef HAVE_EC_KEY_METHOD_NEW
38+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
39 static EC_KEY_METHOD *helper_ecdsa;
40-#endif /* HAVE_EC_KEY_METHOD_NEW */
41+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
42
43 /* redirect private key crypto operations to the ssh-pkcs11-helper */
44 static void
45@@ -233,10 +233,10 @@ wrap_key(struct sshkey *k)
46 {
47 if (k->type == KEY_RSA)
48 RSA_set_method(k->rsa, helper_rsa);
49-#ifdef HAVE_EC_KEY_METHOD_NEW
50+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
51 else if (k->type == KEY_ECDSA)
52 EC_KEY_set_method(k->ecdsa, helper_ecdsa);
53-#endif /* HAVE_EC_KEY_METHOD_NEW */
54+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
55 else
56 fatal("%s: unknown key type", __func__);
57 }
58@@ -247,7 +247,7 @@ pkcs11_start_helper_methods(void)
59 if (helper_rsa != NULL)
60 return (0);
61
62-#ifdef HAVE_EC_KEY_METHOD_NEW
63+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
64 int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
65 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
66 if (helper_ecdsa != NULL)
67@@ -257,7 +257,7 @@ pkcs11_start_helper_methods(void)
68 return (-1);
69 EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
70 EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
71-#endif /* HAVE_EC_KEY_METHOD_NEW */
72+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
73
74 if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
75 fatal("%s: RSA_meth_dup failed", __func__);
76diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
77index a302c79..b56a41b 100644
78--- a/ssh-pkcs11.c
79+++ b/ssh-pkcs11.c
80@@ -78,7 +78,7 @@ struct pkcs11_key {
81
82 int pkcs11_interactive = 0;
83
84-#ifdef HAVE_EC_KEY_METHOD_NEW
85+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
86 static void
87 ossl_error(const char *msg)
88 {
89@@ -89,7 +89,7 @@ ossl_error(const char *msg)
90 error("%s: libcrypto error: %.100s", __func__,
91 ERR_error_string(e, NULL));
92 }
93-#endif /* HAVE_EC_KEY_METHOD_NEW */
94+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
95
96 int
97 pkcs11_init(int interactive)
98@@ -190,10 +190,10 @@ pkcs11_del_provider(char *provider_id)
99
100 static RSA_METHOD *rsa_method;
101 static int rsa_idx = 0;
102-#ifdef HAVE_EC_KEY_METHOD_NEW
103+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
104 static EC_KEY_METHOD *ec_key_method;
105 static int ec_key_idx = 0;
106-#endif
107+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
108
109 /* release a wrapped object */
110 static void
111@@ -492,7 +492,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
112 return (0);
113 }
114
115-#ifdef HAVE_EC_KEY_METHOD_NEW
116+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
117 /* openssl callback doing the actual signing operation */
118 static ECDSA_SIG *
119 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
120@@ -604,7 +604,7 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
121
122 return (0);
123 }
124-#endif /* HAVE_EC_KEY_METHOD_NEW */
125+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
126
127 /* remove trailing spaces */
128 static void
129@@ -679,7 +679,7 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
130 return (0);
131 }
132
133-#ifdef HAVE_EC_KEY_METHOD_NEW
134+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
135 static struct sshkey *
136 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
137 CK_OBJECT_HANDLE *obj)
138@@ -802,7 +802,7 @@ fail:
139
140 return (key);
141 }
142-#endif /* HAVE_EC_KEY_METHOD_NEW */
143+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
144
145 static struct sshkey *
146 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
147@@ -910,7 +910,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
148 #endif
149 struct sshkey *key = NULL;
150 int i;
151-#ifdef HAVE_EC_KEY_METHOD_NEW
152+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
153 int nid;
154 #endif
155 const u_char *cp;
156@@ -999,7 +999,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
157 key->type = KEY_RSA;
158 key->flags |= SSHKEY_FLAG_EXT;
159 rsa = NULL; /* now owned by key */
160-#ifdef HAVE_EC_KEY_METHOD_NEW
161+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
162 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
163 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
164 error("invalid x509; no ec key");
165@@ -1030,7 +1030,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
166 key->type = KEY_ECDSA;
167 key->flags |= SSHKEY_FLAG_EXT;
168 ec = NULL; /* now owned by key */
169-#endif /* HAVE_EC_KEY_METHOD_NEW */
170+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
171 } else {
172 error("unknown certificate key type");
173 goto out;
174@@ -1237,11 +1237,11 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
175 case CKK_RSA:
176 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
177 break;
178-#ifdef HAVE_EC_KEY_METHOD_NEW
179+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
180 case CKK_ECDSA:
181 key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
182 break;
183-#endif /* HAVE_EC_KEY_METHOD_NEW */
184+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
185 default:
186 /* XXX print key type? */
187 key = NULL;
188--
1892.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-02.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-02.patch
new file mode 100644
index 0000000000..25ba921869
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-02.patch
@@ -0,0 +1,581 @@
1From 92cebfbcc221c9ef3f6bbb78da3d7699c0ae56be Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Wed, 19 Jul 2023 14:03:45 +0000
4Subject: [PATCH 02/12] upstream: Separate ssh-pkcs11-helpers for each p11
5 module
6
7Make ssh-pkcs11-client start an independent helper for each provider,
8providing better isolation between modules and reliability if a single
9module misbehaves.
10
11This also implements reference counting of PKCS#11-hosted keys,
12allowing ssh-pkcs11-helper subprocesses to be automatically reaped
13when no remaining keys reference them. This fixes some bugs we have
14that make PKCS11 keys unusable after they have been deleted, e.g.
15https://bugzilla.mindrot.org/show_bug.cgi?id=3125
16
17ok markus@
18
19OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e
20
21Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/099cdf59ce1e72f55d421c8445bf6321b3004755]
22CVE: CVE-2023-38408
23Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
24---
25 ssh-pkcs11-client.c | 372 +++++++++++++++++++++++++++++++++-----------
26 1 file changed, 282 insertions(+), 90 deletions(-)
27
28diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
29index 41114c7..4f3c6ed 100644
30--- a/ssh-pkcs11-client.c
31+++ b/ssh-pkcs11-client.c
32@@ -1,4 +1,4 @@
33-/* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */
34+/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */
35 /*
36 * Copyright (c) 2010 Markus Friedl. All rights reserved.
37 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
38@@ -30,12 +30,11 @@
39 #include <string.h>
40 #include <unistd.h>
41 #include <errno.h>
42+#include <limits.h>
43
44 #include <openssl/ecdsa.h>
45 #include <openssl/rsa.h>
46
47-#include "openbsd-compat/openssl-compat.h"
48-
49 #include "pathnames.h"
50 #include "xmalloc.h"
51 #include "sshbuf.h"
52@@ -47,18 +46,140 @@
53 #include "ssh-pkcs11.h"
54 #include "ssherr.h"
55
56+#include "openbsd-compat/openssl-compat.h"
57+
58 /* borrows code from sftp-server and ssh-agent */
59
60-static int fd = -1;
61-static pid_t pid = -1;
62+/*
63+ * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up
64+ * by provider path or their unique EC/RSA METHOD pointers.
65+ */
66+struct helper {
67+ char *path;
68+ pid_t pid;
69+ int fd;
70+ RSA_METHOD *rsa_meth;
71+ EC_KEY_METHOD *ec_meth;
72+ int (*rsa_finish)(RSA *rsa);
73+ void (*ec_finish)(EC_KEY *key);
74+ size_t nrsa, nec; /* number of active keys of each type */
75+};
76+static struct helper **helpers;
77+static size_t nhelpers;
78+
79+static struct helper *
80+helper_by_provider(const char *path)
81+{
82+ size_t i;
83+
84+ for (i = 0; i < nhelpers; i++) {
85+ if (helpers[i] == NULL || helpers[i]->path == NULL ||
86+ helpers[i]->fd == -1)
87+ continue;
88+ if (strcmp(helpers[i]->path, path) == 0)
89+ return helpers[i];
90+ }
91+ return NULL;
92+}
93+
94+static struct helper *
95+helper_by_rsa(const RSA *rsa)
96+{
97+ size_t i;
98+ const RSA_METHOD *meth;
99+
100+ if ((meth = RSA_get_method(rsa)) == NULL)
101+ return NULL;
102+ for (i = 0; i < nhelpers; i++) {
103+ if (helpers[i] != NULL && helpers[i]->rsa_meth == meth)
104+ return helpers[i];
105+ }
106+ return NULL;
107+
108+}
109+
110+static struct helper *
111+helper_by_ec(const EC_KEY *ec)
112+{
113+ size_t i;
114+ const EC_KEY_METHOD *meth;
115+
116+ if ((meth = EC_KEY_get_method(ec)) == NULL)
117+ return NULL;
118+ for (i = 0; i < nhelpers; i++) {
119+ if (helpers[i] != NULL && helpers[i]->ec_meth == meth)
120+ return helpers[i];
121+ }
122+ return NULL;
123+
124+}
125+
126+static void
127+helper_free(struct helper *helper)
128+{
129+ size_t i;
130+ int found = 0;
131+
132+ if (helper == NULL)
133+ return;
134+ if (helper->path == NULL || helper->ec_meth == NULL ||
135+ helper->rsa_meth == NULL)
136+ fatal("%s: inconsistent helper", __func__);
137+ debug3("%s: free helper for provider %s", __func__ , helper->path);
138+ for (i = 0; i < nhelpers; i++) {
139+ if (helpers[i] == helper) {
140+ if (found)
141+ fatal("%s: helper recorded more than once", __func__);
142+ found = 1;
143+ }
144+ else if (found)
145+ helpers[i - 1] = helpers[i];
146+ }
147+ if (found) {
148+ helpers = xrecallocarray(helpers, nhelpers,
149+ nhelpers - 1, sizeof(*helpers));
150+ nhelpers--;
151+ }
152+ free(helper->path);
153+ EC_KEY_METHOD_free(helper->ec_meth);
154+ RSA_meth_free(helper->rsa_meth);
155+ free(helper);
156+}
157+
158+static void
159+helper_terminate(struct helper *helper)
160+{
161+ if (helper == NULL) {
162+ return;
163+ } else if (helper->fd == -1) {
164+ debug3("%s: already terminated", __func__);
165+ } else {
166+ debug3("terminating helper for %s; "
167+ "remaining %zu RSA %zu ECDSA", __func__,
168+ helper->path, helper->nrsa, helper->nec);
169+ close(helper->fd);
170+ /* XXX waitpid() */
171+ helper->fd = -1;
172+ helper->pid = -1;
173+ }
174+ /*
175+ * Don't delete the helper entry until there are no remaining keys
176+ * that reference it. Otherwise, any signing operation would call
177+ * a free'd METHOD pointer and that would be bad.
178+ */
179+ if (helper->nrsa == 0 && helper->nec == 0)
180+ helper_free(helper);
181+}
182
183 static void
184-send_msg(struct sshbuf *m)
185+send_msg(int fd, struct sshbuf *m)
186 {
187 u_char buf[4];
188 size_t mlen = sshbuf_len(m);
189 int r;
190
191+ if (fd == -1)
192+ return;
193 POKE_U32(buf, mlen);
194 if (atomicio(vwrite, fd, buf, 4) != 4 ||
195 atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
196@@ -69,12 +190,15 @@ send_msg(struct sshbuf *m)
197 }
198
199 static int
200-recv_msg(struct sshbuf *m)
201+recv_msg(int fd, struct sshbuf *m)
202 {
203 u_int l, len;
204 u_char c, buf[1024];
205 int r;
206
207+ sshbuf_reset(m);
208+ if (fd == -1)
209+ return 0; /* XXX */
210 if ((len = atomicio(read, fd, buf, 4)) != 4) {
211 error("read from helper failed: %u", len);
212 return (0); /* XXX */
213@@ -83,7 +207,6 @@ recv_msg(struct sshbuf *m)
214 if (len > 256 * 1024)
215 fatal("response too long: %u", len);
216 /* read len bytes into m */
217- sshbuf_reset(m);
218 while (len > 0) {
219 l = len;
220 if (l > sizeof(buf))
221@@ -104,14 +227,17 @@ recv_msg(struct sshbuf *m)
222 int
223 pkcs11_init(int interactive)
224 {
225- return (0);
226+ return 0;
227 }
228
229 void
230 pkcs11_terminate(void)
231 {
232- if (fd >= 0)
233- close(fd);
234+ size_t i;
235+
236+ debug3("%s: terminating %zu helpers", __func__, nhelpers);
237+ for (i = 0; i < nhelpers; i++)
238+ helper_terminate(helpers[i]);
239 }
240
241 static int
242@@ -122,7 +248,11 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
243 u_char *blob = NULL, *signature = NULL;
244 size_t blen, slen = 0;
245 int r, ret = -1;
246+ struct helper *helper;
247
248+ if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1)
249+ fatal("%s: no helper for PKCS11 key", __func__);
250+ debug3("%s: signing with PKCS11 provider %s", __func__, helper->path);
251 if (padding != RSA_PKCS1_PADDING)
252 goto fail;
253 key = sshkey_new(KEY_UNSPEC);
254@@ -144,10 +274,10 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
255 (r = sshbuf_put_string(msg, from, flen)) != 0 ||
256 (r = sshbuf_put_u32(msg, 0)) != 0)
257 fatal("%s: buffer error: %s", __func__, ssh_err(r));
258- send_msg(msg);
259+ send_msg(helper->fd, msg);
260 sshbuf_reset(msg);
261
262- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
263+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
264 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
265 fatal("%s: buffer error: %s", __func__, ssh_err(r));
266 if (slen <= (size_t)RSA_size(rsa)) {
267@@ -163,7 +293,26 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
268 return (ret);
269 }
270
271-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
272+static int
273+rsa_finish(RSA *rsa)
274+{
275+ struct helper *helper;
276+
277+ if ((helper = helper_by_rsa(rsa)) == NULL)
278+ fatal("%s: no helper for PKCS11 key", __func__);
279+ debug3("%s: free PKCS11 RSA key for provider %s", __func__, helper->path);
280+ if (helper->rsa_finish != NULL)
281+ helper->rsa_finish(rsa);
282+ if (helper->nrsa == 0)
283+ fatal("%s: RSA refcount error", __func__);
284+ helper->nrsa--;
285+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
286+ helper->path, helper->nrsa, helper->nec);
287+ if (helper->nrsa == 0 && helper->nec == 0)
288+ helper_terminate(helper);
289+ return 1;
290+}
291+
292 static ECDSA_SIG *
293 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
294 const BIGNUM *rp, EC_KEY *ec)
295@@ -175,7 +324,11 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
296 u_char *blob = NULL, *signature = NULL;
297 size_t blen, slen = 0;
298 int r, nid;
299+ struct helper *helper;
300
301+ if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1)
302+ fatal("%s: no helper for PKCS11 key", __func__);
303+ debug3("%s: signing with PKCS11 provider %s", __func__, helper->path);
304 nid = sshkey_ecdsa_key_to_nid(ec);
305 if (nid < 0) {
306 error("%s: couldn't get curve nid", __func__);
307@@ -203,10 +356,10 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
308 (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
309 (r = sshbuf_put_u32(msg, 0)) != 0)
310 fatal("%s: buffer error: %s", __func__, ssh_err(r));
311- send_msg(msg);
312+ send_msg(helper->fd, msg);
313 sshbuf_reset(msg);
314
315- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
316+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
317 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
318 fatal("%s: buffer error: %s", __func__, ssh_err(r));
319 cp = signature;
320@@ -220,75 +373,110 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
321 sshbuf_free(msg);
322 return (ret);
323 }
324-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
325
326-static RSA_METHOD *helper_rsa;
327-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
328-static EC_KEY_METHOD *helper_ecdsa;
329-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
330+static void
331+ecdsa_do_finish(EC_KEY *ec)
332+{
333+ struct helper *helper;
334+
335+ if ((helper = helper_by_ec(ec)) == NULL)
336+ fatal("%s: no helper for PKCS11 key", __func__);
337+ debug3("%s: free PKCS11 ECDSA key for provider %s", __func__, helper->path);
338+ if (helper->ec_finish != NULL)
339+ helper->ec_finish(ec);
340+ if (helper->nec == 0)
341+ fatal("%s: ECDSA refcount error", __func__);
342+ helper->nec--;
343+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
344+ helper->path, helper->nrsa, helper->nec);
345+ if (helper->nrsa == 0 && helper->nec == 0)
346+ helper_terminate(helper);
347+}
348
349 /* redirect private key crypto operations to the ssh-pkcs11-helper */
350 static void
351-wrap_key(struct sshkey *k)
352+wrap_key(struct helper *helper, struct sshkey *k)
353 {
354- if (k->type == KEY_RSA)
355- RSA_set_method(k->rsa, helper_rsa);
356-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
357- else if (k->type == KEY_ECDSA)
358- EC_KEY_set_method(k->ecdsa, helper_ecdsa);
359-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
360- else
361+ debug3("%s: wrap %s for provider %s", __func__, sshkey_type(k), helper->path);
362+ if (k->type == KEY_RSA) {
363+ RSA_set_method(k->rsa, helper->rsa_meth);
364+ if (helper->nrsa++ >= INT_MAX)
365+ fatal("%s: RSA refcount error", __func__);
366+ } else if (k->type == KEY_ECDSA) {
367+ EC_KEY_set_method(k->ecdsa, helper->ec_meth);
368+ if (helper->nec++ >= INT_MAX)
369+ fatal("%s: EC refcount error", __func__);
370+ } else
371 fatal("%s: unknown key type", __func__);
372+ k->flags |= SSHKEY_FLAG_EXT;
373+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
374+ helper->path, helper->nrsa, helper->nec);
375 }
376
377 static int
378-pkcs11_start_helper_methods(void)
379+pkcs11_start_helper_methods(struct helper *helper)
380 {
381- if (helper_rsa != NULL)
382- return (0);
383-
384-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
385- int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
386+ int (*ec_init)(EC_KEY *key);
387+ int (*ec_copy)(EC_KEY *dest, const EC_KEY *src);
388+ int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp);
389+ int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key);
390+ int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key);
391+ int (*ec_sign)(int, const unsigned char *, int, unsigned char *,
392 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
393- if (helper_ecdsa != NULL)
394- return (0);
395- helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
396- if (helper_ecdsa == NULL)
397- return (-1);
398- EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
399- EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
400-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
401-
402- if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
403+ RSA_METHOD *rsa_meth;
404+ EC_KEY_METHOD *ec_meth;
405+
406+ if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL)
407+ return -1;
408+ EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL);
409+ EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign);
410+ EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish,
411+ &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public);
412+ EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish,
413+ ec_copy, ec_set_group, ec_set_private, ec_set_public);
414+
415+ if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL)
416 fatal("%s: RSA_meth_dup failed", __func__);
417- if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
418- !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
419+ helper->rsa_finish = RSA_meth_get_finish(rsa_meth);
420+ if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") ||
421+ !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) ||
422+ !RSA_meth_set_finish(rsa_meth, rsa_finish))
423 fatal("%s: failed to prepare method", __func__);
424
425- return (0);
426+ helper->ec_meth = ec_meth;
427+ helper->rsa_meth = rsa_meth;
428+ return 0;
429 }
430
431-static int
432-pkcs11_start_helper(void)
433+static struct helper *
434+pkcs11_start_helper(const char *path)
435 {
436 int pair[2];
437- char *helper, *verbosity = NULL;
438-
439- if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
440- verbosity = "-vvv";
441-
442- if (pkcs11_start_helper_methods() == -1) {
443- error("pkcs11_start_helper_methods failed");
444- return (-1);
445- }
446+ char *prog, *verbosity = NULL;
447+ struct helper *helper;
448+ pid_t pid;
449
450+ if (nhelpers >= INT_MAX)
451+ fatal("%s: too many helpers", __func__);
452+ debug3("%s: start helper for %s", __func__, path);
453 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
454 error("socketpair: %s", strerror(errno));
455- return (-1);
456+ return NULL;
457+ }
458+ helper = xcalloc(1, sizeof(*helper));
459+ if (pkcs11_start_helper_methods(helper) == -1) {
460+ error("pkcs11_start_helper_methods failed");
461+ goto fail;
462 }
463 if ((pid = fork()) == -1) {
464 error("fork: %s", strerror(errno));
465- return (-1);
466+ fail:
467+ close(pair[0]);
468+ close(pair[1]);
469+ RSA_meth_free(helper->rsa_meth);
470+ EC_KEY_METHOD_free(helper->ec_meth);
471+ free(helper);
472+ return NULL;
473 } else if (pid == 0) {
474 if ((dup2(pair[1], STDIN_FILENO) == -1) ||
475 (dup2(pair[1], STDOUT_FILENO) == -1)) {
476@@ -297,18 +485,27 @@ pkcs11_start_helper(void)
477 }
478 close(pair[0]);
479 close(pair[1]);
480- helper = getenv("SSH_PKCS11_HELPER");
481- if (helper == NULL || strlen(helper) == 0)
482- helper = _PATH_SSH_PKCS11_HELPER;
483+ prog = getenv("SSH_PKCS11_HELPER");
484+ if (prog == NULL || strlen(prog) == 0)
485+ prog = _PATH_SSH_PKCS11_HELPER;
486+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
487+ verbosity = "-vvv";
488 debug("%s: starting %s %s", __func__, helper,
489 verbosity == NULL ? "" : verbosity);
490- execlp(helper, helper, verbosity, (char *)NULL);
491- fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
492+ execlp(prog, prog, verbosity, (char *)NULL);
493+ fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno));
494 _exit(1);
495 }
496 close(pair[1]);
497- fd = pair[0];
498- return (0);
499+ helper->fd = pair[0];
500+ helper->path = xstrdup(path);
501+ helper->pid = pid;
502+ debug3("%s: helper %zu for \"%s\" on fd %d pid %ld", __func__, nhelpers,
503+ helper->path, helper->fd, (long)helper->pid);
504+ helpers = xrecallocarray(helpers, nhelpers,
505+ nhelpers + 1, sizeof(*helpers));
506+ helpers[nhelpers++] = helper;
507+ return helper;
508 }
509
510 int
511@@ -322,9 +519,11 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
512 size_t blen;
513 u_int nkeys, i;
514 struct sshbuf *msg;
515+ struct helper *helper;
516
517- if (fd < 0 && pkcs11_start_helper() < 0)
518- return (-1);
519+ if ((helper = helper_by_provider(name)) == NULL &&
520+ (helper = pkcs11_start_helper(name)) == NULL)
521+ return -1;
522
523 if ((msg = sshbuf_new()) == NULL)
524 fatal("%s: sshbuf_new failed", __func__);
525@@ -332,10 +531,10 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
526 (r = sshbuf_put_cstring(msg, name)) != 0 ||
527 (r = sshbuf_put_cstring(msg, pin)) != 0)
528 fatal("%s: buffer error: %s", __func__, ssh_err(r));
529- send_msg(msg);
530+ send_msg(helper->fd, msg);
531 sshbuf_reset(msg);
532
533- type = recv_msg(msg);
534+ type = recv_msg(helper->fd, msg);
535 if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
536 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
537 fatal("%s: buffer error: %s", __func__, ssh_err(r));
538@@ -350,7 +549,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
539 __func__, ssh_err(r));
540 if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
541 fatal("%s: bad key: %s", __func__, ssh_err(r));
542- wrap_key(k);
543+ wrap_key(helper, k);
544 (*keysp)[i] = k;
545 if (labelsp)
546 (*labelsp)[i] = label;
547@@ -371,22 +570,15 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
548 int
549 pkcs11_del_provider(char *name)
550 {
551- int r, ret = -1;
552- struct sshbuf *msg;
553-
554- if ((msg = sshbuf_new()) == NULL)
555- fatal("%s: sshbuf_new failed", __func__);
556- if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
557- (r = sshbuf_put_cstring(msg, name)) != 0 ||
558- (r = sshbuf_put_cstring(msg, "")) != 0)
559- fatal("%s: buffer error: %s", __func__, ssh_err(r));
560- send_msg(msg);
561- sshbuf_reset(msg);
562-
563- if (recv_msg(msg) == SSH_AGENT_SUCCESS)
564- ret = 0;
565- sshbuf_free(msg);
566- return (ret);
567+ struct helper *helper;
568+
569+ /*
570+ * ssh-agent deletes keys before calling this, so the helper entry
571+ * should be gone before we get here.
572+ */
573+ debug3("%s: delete %s", __func__, name);
574+ if ((helper = helper_by_provider(name)) != NULL)
575+ helper_terminate(helper);
576+ return 0;
577 }
578-
579 #endif /* ENABLE_PKCS11 */
580--
5812.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-03.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-03.patch
new file mode 100644
index 0000000000..e16e5e245e
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-03.patch
@@ -0,0 +1,171 @@
1From 2f1be98e83feb90665b9292eff8bb734537fd491 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Wed, 19 Jul 2023 14:02:27 +0000
4Subject: [PATCH 03/12] upstream: Ensure FIDO/PKCS11 libraries contain expected
5 symbols
6
7This checks via nlist(3) that candidate provider libraries contain one
8of the symbols that we will require prior to dlopen(), which can cause
9a number of side effects, including execution of constructors.
10
11Feedback deraadt; ok markus
12
13OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe
14
15Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/29ef8a04866ca14688d5b7fed7b8b9deab851f77]
16CVE: CVE-2023-38408
17Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
18---
19 misc.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
20 misc.h | 1 +
21 ssh-pkcs11.c | 4 +++
22 ssh-sk.c | 6 ++--
23 4 files changed, 86 insertions(+), 2 deletions(-)
24
25diff --git a/misc.c b/misc.c
26index 3a31d5c..8a107e4 100644
27--- a/misc.c
28+++ b/misc.c
29@@ -28,6 +28,7 @@
30
31 #include <sys/types.h>
32 #include <sys/ioctl.h>
33+#include <sys/mman.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37@@ -41,6 +42,9 @@
38 #ifdef HAVE_POLL_H
39 #include <poll.h>
40 #endif
41+#ifdef HAVE_NLIST_H
42+#include <nlist.h>
43+#endif
44 #include <signal.h>
45 #include <stdarg.h>
46 #include <stdio.h>
47@@ -2266,3 +2270,76 @@ ssh_signal(int signum, sshsig_t handler)
48 }
49 return osa.sa_handler;
50 }
51+
52+
53+/*
54+ * Returns zero if the library at 'path' contains symbol 's', nonzero
55+ * otherwise.
56+ */
57+int
58+lib_contains_symbol(const char *path, const char *s)
59+{
60+#ifdef HAVE_NLIST_H
61+ struct nlist nl[2];
62+ int ret = -1, r;
63+
64+ memset(nl, 0, sizeof(nl));
65+ nl[0].n_name = xstrdup(s);
66+ nl[1].n_name = NULL;
67+ if ((r = nlist(path, nl)) == -1) {
68+ error("%s: nlist failed for %s", __func__, path);
69+ goto out;
70+ }
71+ if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) {
72+ error("%s: library %s does not contain symbol %s", __func__, path, s);
73+ goto out;
74+ }
75+ /* success */
76+ ret = 0;
77+ out:
78+ free(nl[0].n_name);
79+ return ret;
80+#else /* HAVE_NLIST_H */
81+ int fd, ret = -1;
82+ struct stat st;
83+ void *m = NULL;
84+ size_t sz = 0;
85+
86+ memset(&st, 0, sizeof(st));
87+ if ((fd = open(path, O_RDONLY)) < 0) {
88+ error("%s: open %s: %s", __func__, path, strerror(errno));
89+ return -1;
90+ }
91+ if (fstat(fd, &st) != 0) {
92+ error("%s: fstat %s: %s", __func__, path, strerror(errno));
93+ goto out;
94+ }
95+ if (!S_ISREG(st.st_mode)) {
96+ error("%s: %s is not a regular file", __func__, path);
97+ goto out;
98+ }
99+ if (st.st_size < 0 ||
100+ (size_t)st.st_size < strlen(s) ||
101+ st.st_size >= INT_MAX/2) {
102+ error("%s: %s bad size %lld", __func__, path, (long long)st.st_size);
103+ goto out;
104+ }
105+ sz = (size_t)st.st_size;
106+ if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED ||
107+ m == NULL) {
108+ error("%s: mmap %s: %s", __func__, path, strerror(errno));
109+ goto out;
110+ }
111+ if (memmem(m, sz, s, strlen(s)) == NULL) {
112+ error("%s: %s does not contain expected string %s", __func__, path, s);
113+ goto out;
114+ }
115+ /* success */
116+ ret = 0;
117+ out:
118+ if (m != NULL && m != MAP_FAILED)
119+ munmap(m, sz);
120+ close(fd);
121+ return ret;
122+#endif /* HAVE_NLIST_H */
123+}
124diff --git a/misc.h b/misc.h
125index 4a05db2..3f9f4db 100644
126--- a/misc.h
127+++ b/misc.h
128@@ -86,6 +86,7 @@ const char *atoi_err(const char *, int *);
129 int parse_absolute_time(const char *, uint64_t *);
130 void format_absolute_time(uint64_t, char *, size_t);
131 int path_absolute(const char *);
132+int lib_contains_symbol(const char *, const char *);
133
134 void sock_set_v6only(int);
135
136diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
137index b56a41b..639a6f7 100644
138--- a/ssh-pkcs11.c
139+++ b/ssh-pkcs11.c
140@@ -1499,6 +1499,10 @@ pkcs11_register_provider(char *provider_id, char *pin,
141 __func__, provider_id);
142 goto fail;
143 }
144+ if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
145+ error("provider %s is not a PKCS11 library", provider_id);
146+ goto fail;
147+ }
148 /* open shared pkcs11-library */
149 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
150 error("dlopen %s failed: %s", provider_id, dlerror());
151diff --git a/ssh-sk.c b/ssh-sk.c
152index 5ff9381..9df12cc 100644
153--- a/ssh-sk.c
154+++ b/ssh-sk.c
155@@ -119,10 +119,12 @@ sshsk_open(const char *path)
156 #endif
157 return ret;
158 }
159- if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
160- error("Provider \"%s\" dlopen failed: %s", path, dlerror());
161+ if (lib_contains_symbol(path, "sk_api_version") != 0) {
162+ error("provider %s is not an OpenSSH FIDO library", path);
163 goto fail;
164 }
165+ if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL)
166+ fatal("Provider \"%s\" dlopen failed: %s", path, dlerror());
167 if ((ret->sk_api_version = dlsym(ret->dlhandle,
168 "sk_api_version")) == NULL) {
169 error("Provider \"%s\" dlsym(sk_api_version) failed: %s",
170--
1712.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-04.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-04.patch
new file mode 100644
index 0000000000..5e8040c9bf
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-04.patch
@@ -0,0 +1,34 @@
1From 0862f338941bfdfb2cadee87de6d5fdca1b8f457 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Wed, 19 Jul 2023 13:55:53 +0000
4Subject: [PATCH 04/12] upstream: terminate process if requested to load a
5 PKCS#11 provider that isn't a PKCS#11 provider; from / ok markus@
6
7OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c
8
9Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/892506b13654301f69f9545f48213fc210e5c5cc]
10CVE: CVE-2023-38408
11Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
12---
13 ssh-pkcs11.c | 6 ++----
14 1 file changed, 2 insertions(+), 4 deletions(-)
15
16diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
17index 639a6f7..7530acc 100644
18--- a/ssh-pkcs11.c
19+++ b/ssh-pkcs11.c
20@@ -1508,10 +1508,8 @@ pkcs11_register_provider(char *provider_id, char *pin,
21 error("dlopen %s failed: %s", provider_id, dlerror());
22 goto fail;
23 }
24- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
25- error("dlsym(C_GetFunctionList) failed: %s", dlerror());
26- goto fail;
27- }
28+ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
29+ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
30 p = xcalloc(1, sizeof(*p));
31 p->name = xstrdup(provider_id);
32 p->handle = handle;
33--
342.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch
new file mode 100644
index 0000000000..0ddbdc68d4
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch
@@ -0,0 +1,194 @@
1From a6cee3905edf070c0de135d3f2ee5b74da1dbd28 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Tue, 26 May 2020 01:26:58 +0000
4Subject: [PATCH 05/12] upstream: Restrict ssh-agent from signing web
5 challenges for FIDO
6
7keys.
8
9When signing messages in ssh-agent using a FIDO key that has an
10application string that does not start with "ssh:", ensure that the
11message being signed is one of the forms expected for the SSH protocol
12(currently pubkey authentication and sshsig signatures).
13
14This prevents ssh-agent forwarding on a host that has FIDO keys
15attached granting the ability for the remote side to sign challenges
16for web authentication using those keys too.
17
18Note that the converse case of web browsers signing SSH challenges is
19already precluded because no web RP can have the "ssh:" prefix in the
20application string that we require.
21
22ok markus@
23
24OpenBSD-Commit-ID: 9ab6012574ed0352d2f097d307f4a988222d1b19
25
26Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/0c111eb84efba7c2a38b2cc3278901a0123161b9]
27CVE: CVE-2023-38408
28Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
29---
30 ssh-agent.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-----
31 1 file changed, 100 insertions(+), 10 deletions(-)
32
33diff --git a/ssh-agent.c b/ssh-agent.c
34index ceb348c..1794f35 100644
35--- a/ssh-agent.c
36+++ b/ssh-agent.c
37@@ -1,4 +1,4 @@
38-/* $OpenBSD: ssh-agent.c,v 1.255 2020/02/06 22:30:54 naddy Exp $ */
39+/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */
40 /*
41 * Author: Tatu Ylonen <ylo@cs.hut.fi>
42 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
43@@ -77,6 +77,7 @@
44
45 #include "xmalloc.h"
46 #include "ssh.h"
47+#include "ssh2.h"
48 #include "sshbuf.h"
49 #include "sshkey.h"
50 #include "authfd.h"
51@@ -167,6 +168,9 @@ static long lifetime = 0;
52
53 static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
54
55+/* Refuse signing of non-SSH messages for web-origin FIDO keys */
56+static int restrict_websafe = 1;
57+
58 static void
59 close_socket(SocketEntry *e)
60 {
61@@ -282,6 +286,80 @@ agent_decode_alg(struct sshkey *key, u_int flags)
62 return NULL;
63 }
64
65+/*
66+ * This function inspects a message to be signed by a FIDO key that has a
67+ * web-like application string (i.e. one that does not begin with "ssh:".
68+ * It checks that the message is one of those expected for SSH operations
69+ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
70+ * for the web.
71+ */
72+static int
73+check_websafe_message_contents(struct sshkey *key,
74+ const u_char *msg, size_t len)
75+{
76+ int matched = 0;
77+ struct sshbuf *b;
78+ u_char m, n;
79+ char *cp1 = NULL, *cp2 = NULL;
80+ int r;
81+ struct sshkey *mkey = NULL;
82+
83+ if ((b = sshbuf_from(msg, len)) == NULL)
84+ fatal("%s: sshbuf_new", __func__);
85+
86+ /* SSH userauth request */
87+ if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */
88+ (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */
89+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */
90+ (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */
91+ (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */
92+ (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */
93+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */
94+ (r = sshkey_froms(b, &mkey)) == 0 && /* key */
95+ sshbuf_len(b) == 0) {
96+ debug("%s: parsed userauth", __func__);
97+ if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 &&
98+ strcmp(cp1, "ssh-connection") == 0 &&
99+ strcmp(cp2, "publickey") == 0 &&
100+ sshkey_equal(key, mkey)) {
101+ debug("%s: well formed userauth", __func__);
102+ matched = 1;
103+ }
104+ }
105+ free(cp1);
106+ free(cp2);
107+ sshkey_free(mkey);
108+ sshbuf_free(b);
109+ if (matched)
110+ return 1;
111+
112+ if ((b = sshbuf_from(msg, len)) == NULL)
113+ fatal("%s: sshbuf_new", __func__);
114+ cp1 = cp2 = NULL;
115+ mkey = NULL;
116+
117+ /* SSHSIG */
118+ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 &&
119+ (r = sshbuf_consume(b, 6)) == 0 &&
120+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */
121+ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */
122+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */
123+ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */
124+ sshbuf_len(b) == 0) {
125+ debug("%s: parsed sshsig", __func__);
126+ matched = 1;
127+ }
128+
129+ sshbuf_free(b);
130+ if (matched)
131+ return 1;
132+
133+ /* XXX CA signature operation */
134+
135+ error("web-origin key attempting to sign non-SSH message");
136+ return 0;
137+}
138+
139 /* ssh2 only */
140 static void
141 process_sign_request2(SocketEntry *e)
142@@ -314,14 +392,20 @@ process_sign_request2(SocketEntry *e)
143 verbose("%s: user refused key", __func__);
144 goto send;
145 }
146- if (sshkey_is_sk(id->key) &&
147- (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
148- if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
149- SSH_FP_DEFAULT)) == NULL)
150- fatal("%s: fingerprint failed", __func__);
151- notifier = notify_start(0,
152- "Confirm user presence for key %s %s",
153- sshkey_type(id->key), fp);
154+ if (sshkey_is_sk(id->key)) {
155+ if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
156+ !check_websafe_message_contents(key, data, dlen)) {
157+ /* error already logged */
158+ goto send;
159+ }
160+ if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
161+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
162+ SSH_FP_DEFAULT)) == NULL)
163+ fatal("%s: fingerprint failed", __func__);
164+ notifier = notify_start(0,
165+ "Confirm user presence for key %s %s",
166+ sshkey_type(id->key), fp);
167+ }
168 }
169 if ((r = sshkey_sign(id->key, &signature, &slen,
170 data, dlen, agent_decode_alg(key, flags),
171@@ -1214,7 +1298,7 @@ main(int ac, char **av)
172 __progname = ssh_get_progname(av[0]);
173 seed_rng();
174
175- while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
176+ while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
177 switch (ch) {
178 case 'E':
179 fingerprint_hash = ssh_digest_alg_by_name(optarg);
180@@ -1229,6 +1313,12 @@ main(int ac, char **av)
181 case 'k':
182 k_flag++;
183 break;
184+ case 'O':
185+ if (strcmp(optarg, "no-restrict-websafe") == 0)
186+ restrict_websafe = 0;
187+ else
188+ fatal("Unknown -O option");
189+ break;
190 case 'P':
191 if (provider_whitelist != NULL)
192 fatal("-P option already specified");
193--
1942.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-06.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-06.patch
new file mode 100644
index 0000000000..ac494aab0b
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-06.patch
@@ -0,0 +1,73 @@
1From a5d845b7b42861d18f43e83de9f24c7374d1b458 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 18 Sep 2020 08:16:38 +0000
4Subject: [PATCH 06/12] upstream: handle multiple messages in a single read()
5
6PR#183 by Dennis Kaarsemaker; feedback and ok markus@
7
8OpenBSD-Commit-ID: 8570bb4d02d00cf70b98590716ea6a7d1cce68d1
9
10Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/52a03e9fca2d74eef953ddd4709250f365ca3975]
11CVE: CVE-2023-38408
12Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
13---
14 ssh-agent.c | 19 +++++++++++++------
15 1 file changed, 13 insertions(+), 6 deletions(-)
16
17diff --git a/ssh-agent.c b/ssh-agent.c
18index 1794f35..78f7268 100644
19--- a/ssh-agent.c
20+++ b/ssh-agent.c
21@@ -1,4 +1,4 @@
22-/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */
23+/* $OpenBSD: ssh-agent.c,v 1.264 2020/09/18 08:16:38 djm Exp $ */
24 /*
25 * Author: Tatu Ylonen <ylo@cs.hut.fi>
26 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
27@@ -853,8 +853,10 @@ send:
28 }
29 #endif /* ENABLE_PKCS11 */
30
31-/* dispatch incoming messages */
32-
33+/*
34+ * dispatch incoming message.
35+ * returns 1 on success, 0 for incomplete messages or -1 on error.
36+ */
37 static int
38 process_message(u_int socknum)
39 {
40@@ -908,7 +910,7 @@ process_message(u_int socknum)
41 /* send a fail message for all other request types */
42 send_status(e, 0);
43 }
44- return 0;
45+ return 1;
46 }
47
48 switch (type) {
49@@ -952,7 +954,7 @@ process_message(u_int socknum)
50 send_status(e, 0);
51 break;
52 }
53- return 0;
54+ return 1;
55 }
56
57 static void
58@@ -1043,7 +1045,12 @@ handle_conn_read(u_int socknum)
59 if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
60 fatal("%s: buffer error: %s", __func__, ssh_err(r));
61 explicit_bzero(buf, sizeof(buf));
62- process_message(socknum);
63+ for (;;) {
64+ if ((r = process_message(socknum)) == -1)
65+ return -1;
66+ else if (r == 0)
67+ break;
68+ }
69 return 0;
70 }
71
72--
732.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-07.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-07.patch
new file mode 100644
index 0000000000..0dcf23ae17
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-07.patch
@@ -0,0 +1,125 @@
1From 653cc18c922fc387b3d3aa1b081c5e5283cce28a Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Tue, 26 Jan 2021 00:47:47 +0000
4Subject: [PATCH 07/12] upstream: use recallocarray to allocate the agent
5 sockets table;
6
7also clear socket entries that are being marked as unused.
8
9spinkle in some debug2() spam to make it easier to watch an agent
10do its thing.
11
12ok markus
13
14OpenBSD-Commit-ID: 74582c8e82e96afea46f6c7b6813a429cbc75922
15
16Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1fe16fd61bb53944ec510882acc0491abd66ff76]
17CVE: CVE-2023-38408
18Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
19---
20 ssh-agent.c | 20 ++++++++++++++++----
21 1 file changed, 16 insertions(+), 4 deletions(-)
22
23diff --git a/ssh-agent.c b/ssh-agent.c
24index 78f7268..2635bc5 100644
25--- a/ssh-agent.c
26+++ b/ssh-agent.c
27@@ -1,4 +1,4 @@
28-/* $OpenBSD: ssh-agent.c,v 1.264 2020/09/18 08:16:38 djm Exp $ */
29+/* $OpenBSD: ssh-agent.c,v 1.269 2021/01/26 00:47:47 djm Exp $ */
30 /*
31 * Author: Tatu Ylonen <ylo@cs.hut.fi>
32 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
33@@ -175,11 +175,12 @@ static void
34 close_socket(SocketEntry *e)
35 {
36 close(e->fd);
37- e->fd = -1;
38- e->type = AUTH_UNUSED;
39 sshbuf_free(e->input);
40 sshbuf_free(e->output);
41 sshbuf_free(e->request);
42+ memset(e, '\0', sizeof(*e));
43+ e->fd = -1;
44+ e->type = AUTH_UNUSED;
45 }
46
47 static void
48@@ -249,6 +250,8 @@ process_request_identities(SocketEntry *e)
49 struct sshbuf *msg;
50 int r;
51
52+ debug2("%s: entering", __func__);
53+
54 if ((msg = sshbuf_new()) == NULL)
55 fatal("%s: sshbuf_new failed", __func__);
56 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
57@@ -441,6 +444,7 @@ process_remove_identity(SocketEntry *e)
58 struct sshkey *key = NULL;
59 Identity *id;
60
61+ debug2("%s: entering", __func__);
62 if ((r = sshkey_froms(e->request, &key)) != 0) {
63 error("%s: get key: %s", __func__, ssh_err(r));
64 goto done;
65@@ -467,6 +471,7 @@ process_remove_all_identities(SocketEntry *e)
66 {
67 Identity *id;
68
69+ debug2("%s: entering", __func__);
70 /* Loop over all identities and clear the keys. */
71 for (id = TAILQ_FIRST(&idtab->idlist); id;
72 id = TAILQ_FIRST(&idtab->idlist)) {
73@@ -520,6 +525,7 @@ process_add_identity(SocketEntry *e)
74 u_char ctype;
75 int r = SSH_ERR_INTERNAL_ERROR;
76
77+ debug2("%s: entering", __func__);
78 if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
79 k == NULL ||
80 (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
81@@ -667,6 +673,7 @@ process_lock_agent(SocketEntry *e, int lock)
82 static u_int fail_count = 0;
83 size_t pwlen;
84
85+ debug2("%s: entering", __func__);
86 /*
87 * This is deliberately fatal: the user has requested that we lock,
88 * but we can't parse their request properly. The only safe thing to
89@@ -738,6 +745,7 @@ process_add_smartcard_key(SocketEntry *e)
90 struct sshkey **keys = NULL, *k;
91 Identity *id;
92
93+ debug2("%s: entering", __func__);
94 if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
95 (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
96 error("%s: buffer error: %s", __func__, ssh_err(r));
97@@ -818,6 +826,7 @@ process_remove_smartcard_key(SocketEntry *e)
98 int r, success = 0;
99 Identity *id, *nxt;
100
101+ debug2("%s: entering", __func__);
102 if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
103 (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
104 error("%s: buffer error: %s", __func__, ssh_err(r));
105@@ -962,6 +971,8 @@ new_socket(sock_type type, int fd)
106 {
107 u_int i, old_alloc, new_alloc;
108
109+ debug("%s: type = %s", __func__, type == AUTH_CONNECTION ? "CONNECTION" :
110+ (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
111 set_nonblock(fd);
112
113 if (fd > max_fd)
114@@ -981,7 +992,8 @@ new_socket(sock_type type, int fd)
115 }
116 old_alloc = sockets_alloc;
117 new_alloc = sockets_alloc + 10;
118- sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
119+ sockets = xrecallocarray(sockets, old_alloc, new_alloc,
120+ sizeof(sockets[0]));
121 for (i = old_alloc; i < new_alloc; i++)
122 sockets[i].type = AUTH_UNUSED;
123 sockets_alloc = new_alloc;
124--
1252.41.0
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
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-09.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-09.patch
new file mode 100644
index 0000000000..b519ccce42
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-09.patch
@@ -0,0 +1,38 @@
1From 7adba46611e5d076d7d12d9f4162dd4cabd5ff50 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 29 Jan 2021 06:28:10 +0000
4Subject: [PATCH 09/12] upstream: give typedef'd struct a struct name; makes
5 the fuzzer I'm
6
7writing a bit easier
8
9OpenBSD-Commit-ID: 1052ab521505a4d8384d67acb3974ef81b8896cb
10
11Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/8afaa7d7918419d3da6c0477b83db2159879cb33]
12CVE: CVE-2023-38408
13Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
14---
15 ssh-agent.c | 4 ++--
16 1 file changed, 2 insertions(+), 2 deletions(-)
17
18diff --git a/ssh-agent.c b/ssh-agent.c
19index 7ad323c..c99927c 100644
20--- a/ssh-agent.c
21+++ b/ssh-agent.c
22@@ -1,4 +1,4 @@
23-/* $OpenBSD: ssh-agent.c,v 1.270 2021/01/26 00:53:31 djm Exp $ */
24+/* $OpenBSD: ssh-agent.c,v 1.274 2021/01/29 06:28:10 djm Exp $ */
25 /*
26 * Author: Tatu Ylonen <ylo@cs.hut.fi>
27 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
28@@ -108,7 +108,7 @@ typedef enum {
29 AUTH_CONNECTION
30 } sock_type;
31
32-typedef struct {
33+typedef struct socket_entry {
34 int fd;
35 sock_type type;
36 struct sshbuf *input;
37--
382.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-10.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-10.patch
new file mode 100644
index 0000000000..27b2eadfae
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-10.patch
@@ -0,0 +1,39 @@
1From 343e2a2c0ef754a7a86118016b248f7a73f8d510 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 29 Jan 2021 06:29:46 +0000
4Subject: [PATCH 10/12] upstream: fix the values of enum sock_type
5
6OpenBSD-Commit-ID: 18d048f4dbfbb159ff500cfc2700b8fb1407facd
7
8Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1a4b92758690faa12f49079dd3b72567f909466d]
9CVE: CVE-2023-38408
10Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
11---
12 ssh-agent.c | 8 ++++----
13 1 file changed, 4 insertions(+), 4 deletions(-)
14
15diff --git a/ssh-agent.c b/ssh-agent.c
16index c99927c..7f1e14b 100644
17--- a/ssh-agent.c
18+++ b/ssh-agent.c
19@@ -1,4 +1,4 @@
20-/* $OpenBSD: ssh-agent.c,v 1.274 2021/01/29 06:28:10 djm Exp $ */
21+/* $OpenBSD: ssh-agent.c,v 1.275 2021/01/29 06:29:46 djm Exp $ */
22 /*
23 * Author: Tatu Ylonen <ylo@cs.hut.fi>
24 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
25@@ -103,9 +103,9 @@
26 #define AGENT_RBUF_LEN (4096)
27
28 typedef enum {
29- AUTH_UNUSED,
30- AUTH_SOCKET,
31- AUTH_CONNECTION
32+ AUTH_UNUSED = 0,
33+ AUTH_SOCKET = 1,
34+ AUTH_CONNECTION = 2,
35 } sock_type;
36
37 typedef struct socket_entry {
38--
392.41.0
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
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-12.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-12.patch
new file mode 100644
index 0000000000..934775bdec
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-12.patch
@@ -0,0 +1,120 @@
1From 4fe3d0fbd3d6dc1f19354e0d73a3231c461ed044 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Wed, 19 Jul 2023 13:56:33 +0000
4Subject: [PATCH 12/12] upstream: Disallow remote addition of FIDO/PKCS11
5 provider libraries to ssh-agent by default.
6
7The old behaviour of allowing remote clients from loading providers
8can be restored using `ssh-agent -O allow-remote-pkcs11`.
9
10Detection of local/remote clients requires a ssh(1) that supports
11the `session-bind@openssh.com` extension. Forwarding access to a
12ssh-agent socket using non-OpenSSH tools may circumvent this control.
13
14ok markus@
15
16OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c
17
18Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1f2731f5d7a8f8a8385c6031667ed29072c0d92a]
19CVE: CVE-2023-38408
20Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
21---
22 ssh-agent.1 | 20 ++++++++++++++++++++
23 ssh-agent.c | 26 ++++++++++++++++++++++++--
24 2 files changed, 44 insertions(+), 2 deletions(-)
25
26diff --git a/ssh-agent.1 b/ssh-agent.1
27index fff0db6..a0f1e21 100644
28--- a/ssh-agent.1
29+++ b/ssh-agent.1
30@@ -97,6 +97,26 @@ The default is
31 Kill the current agent (given by the
32 .Ev SSH_AGENT_PID
33 environment variable).
34+Currently two options are supported:
35+.Cm allow-remote-pkcs11
36+and
37+.Pp
38+The
39+.Cm allow-remote-pkcs11
40+option allows clients of a forwarded
41+.Nm
42+to load PKCS#11 or FIDO provider libraries.
43+By default only local clients may perform this operation.
44+Note that signalling that a
45+.Nm
46+client remote is performed by
47+.Xr ssh 1 ,
48+and use of other tools to forward access to the agent socket may circumvent
49+this restriction.
50+.Pp
51+The
52+.Cm no-restrict-websafe ,
53+instructs
54 .It Fl P Ar provider_whitelist
55 Specify a pattern-list of acceptable paths for PKCS#11 and FIDO authenticator
56 shared libraries that may be used with the
57diff --git a/ssh-agent.c b/ssh-agent.c
58index 01c7f2b..40c1b6b 100644
59--- a/ssh-agent.c
60+++ b/ssh-agent.c
61@@ -1,4 +1,4 @@
62-/* $OpenBSD: ssh-agent.c,v 1.280 2021/12/19 22:09:23 djm Exp $ */
63+/* $OpenBSD: ssh-agent.c,v 1.300 2023/07/19 13:56:33 djm Exp $ */
64 /*
65 * Author: Tatu Ylonen <ylo@cs.hut.fi>
66 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
67@@ -167,6 +167,12 @@ char socket_dir[PATH_MAX];
68 /* PKCS#11/Security key path whitelist */
69 static char *provider_whitelist;
70
71+/*
72+ * Allows PKCS11 providers or SK keys that use non-internal providers to
73+ * be added over a remote connection (identified by session-bind@openssh.com).
74+ */
75+static int remote_add_provider;
76+
77 /* locking */
78 #define LOCK_SIZE 32
79 #define LOCK_SALT_SIZE 16
80@@ -736,6 +742,15 @@ process_add_identity(SocketEntry *e)
81 if (strcasecmp(sk_provider, "internal") == 0) {
82 debug("%s: internal provider", __func__);
83 } else {
84+ if (e->nsession_ids != 0 && !remote_add_provider) {
85+ verbose("failed add of SK provider \"%.100s\": "
86+ "remote addition of providers is disabled",
87+ sk_provider);
88+ free(sk_provider);
89+ free(comment);
90+ sshkey_free(k);
91+ goto send;
92+ }
93 if (realpath(sk_provider, canonical_provider) == NULL) {
94 verbose("failed provider \"%.100s\": "
95 "realpath: %s", sk_provider,
96@@ -901,6 +916,11 @@ process_add_smartcard_key(SocketEntry *e)
97 goto send;
98 }
99 }
100+ if (e->nsession_ids != 0 && !remote_add_provider) {
101+ verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
102+ "providers is disabled", provider);
103+ goto send;
104+ }
105 if (realpath(provider, canonical_provider) == NULL) {
106 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
107 provider, strerror(errno));
108@@ -1556,7 +1576,9 @@ main(int ac, char **av)
109 break;
110 case 'O':
111 if (strcmp(optarg, "no-restrict-websafe") == 0)
112- restrict_websafe = 0;
113+ restrict_websafe = 0;
114+ else if (strcmp(optarg, "allow-remote-pkcs11") == 0)
115+ remote_add_provider = 1;
116 else
117 fatal("Unknown -O option");
118 break;
119--
1202.41.0
diff --git a/meta/recipes-connectivity/openssh/openssh_8.2p1.bb b/meta/recipes-connectivity/openssh/openssh_8.2p1.bb
index 79dba121ff..bc4b922301 100644
--- a/meta/recipes-connectivity/openssh/openssh_8.2p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_8.2p1.bb
@@ -27,6 +27,18 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
27 file://CVE-2020-14145.patch \ 27 file://CVE-2020-14145.patch \
28 file://CVE-2021-28041.patch \ 28 file://CVE-2021-28041.patch \
29 file://CVE-2021-41617.patch \ 29 file://CVE-2021-41617.patch \
30 file://CVE-2023-38408-01.patch \
31 file://CVE-2023-38408-02.patch \
32 file://CVE-2023-38408-03.patch \
33 file://CVE-2023-38408-04.patch \
34 file://CVE-2023-38408-05.patch \
35 file://CVE-2023-38408-06.patch \
36 file://CVE-2023-38408-07.patch \
37 file://CVE-2023-38408-08.patch \
38 file://CVE-2023-38408-09.patch \
39 file://CVE-2023-38408-10.patch \
40 file://CVE-2023-38408-11.patch \
41 file://CVE-2023-38408-12.patch \
30 " 42 "
31SRC_URI[md5sum] = "3076e6413e8dbe56d33848c1054ac091" 43SRC_URI[md5sum] = "3076e6413e8dbe56d33848c1054ac091"
32SRC_URI[sha256sum] = "43925151e6cf6cee1450190c0e9af4dc36b41c12737619edff8bcebdff64e671" 44SRC_URI[sha256sum] = "43925151e6cf6cee1450190c0e9af4dc36b41c12737619edff8bcebdff64e671"