summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0001.patch585
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0002.patch173
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0003.patch36
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0004.patch114
-rw-r--r--meta/recipes-connectivity/openssh/openssh_8.9p1.bb4
5 files changed, 912 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0001.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0001.patch
new file mode 100644
index 0000000000..2ee344cb27
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0001.patch
@@ -0,0 +1,585 @@
1From 099cdf59ce1e72f55d421c8445bf6321b3004755 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 1/4] upstream: Separate ssh-pkcs11-helpers for each p11 module
5
6Make ssh-pkcs11-client start an independent helper for each provider,
7providing better isolation between modules and reliability if a single
8module misbehaves.
9
10This also implements reference counting of PKCS#11-hosted keys,
11allowing ssh-pkcs11-helper subprocesses to be automatically reaped
12when no remaining keys reference them. This fixes some bugs we have
13that make PKCS11 keys unusable after they have been deleted, e.g.
14https://bugzilla.mindrot.org/show_bug.cgi?id=3125
15
16ok markus@
17
18OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e
19
20Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/099cdf59ce1e72f55d421c8445bf6321b3004755]
21
22CVE: CVE-2023-38408
23
24Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
25---
26 ssh-pkcs11-client.c | 378 +++++++++++++++++++++++++++++++++-----------
27 1 file changed, 285 insertions(+), 93 deletions(-)
28
29diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
30index cfd833d..7db6c6c 100644
31--- a/ssh-pkcs11-client.c
32+++ b/ssh-pkcs11-client.c
33@@ -1,4 +1,4 @@
34-/* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */
35+/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */
36 /*
37 * Copyright (c) 2010 Markus Friedl. All rights reserved.
38 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
39@@ -30,12 +30,11 @@
40 #include <string.h>
41 #include <unistd.h>
42 #include <errno.h>
43+#include <limits.h>
44
45 #include <openssl/ecdsa.h>
46 #include <openssl/rsa.h>
47
48-#include "openbsd-compat/openssl-compat.h"
49-
50 #include "pathnames.h"
51 #include "xmalloc.h"
52 #include "sshbuf.h"
53@@ -47,18 +46,140 @@
54 #include "ssh-pkcs11.h"
55 #include "ssherr.h"
56
57+#include "openbsd-compat/openssl-compat.h"
58+
59 /* borrows code from sftp-server and ssh-agent */
60
61-static int fd = -1;
62-static pid_t pid = -1;
63+/*
64+ * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up
65+ * by provider path or their unique EC/RSA METHOD pointers.
66+ */
67+struct helper {
68+ char *path;
69+ pid_t pid;
70+ int fd;
71+ RSA_METHOD *rsa_meth;
72+ EC_KEY_METHOD *ec_meth;
73+ int (*rsa_finish)(RSA *rsa);
74+ void (*ec_finish)(EC_KEY *key);
75+ size_t nrsa, nec; /* number of active keys of each type */
76+};
77+static struct helper **helpers;
78+static size_t nhelpers;
79+
80+static struct helper *
81+helper_by_provider(const char *path)
82+{
83+ size_t i;
84+
85+ for (i = 0; i < nhelpers; i++) {
86+ if (helpers[i] == NULL || helpers[i]->path == NULL ||
87+ helpers[i]->fd == -1)
88+ continue;
89+ if (strcmp(helpers[i]->path, path) == 0)
90+ return helpers[i];
91+ }
92+ return NULL;
93+}
94+
95+static struct helper *
96+helper_by_rsa(const RSA *rsa)
97+{
98+ size_t i;
99+ const RSA_METHOD *meth;
100+
101+ if ((meth = RSA_get_method(rsa)) == NULL)
102+ return NULL;
103+ for (i = 0; i < nhelpers; i++) {
104+ if (helpers[i] != NULL && helpers[i]->rsa_meth == meth)
105+ return helpers[i];
106+ }
107+ return NULL;
108+
109+}
110+
111+static struct helper *
112+helper_by_ec(const EC_KEY *ec)
113+{
114+ size_t i;
115+ const EC_KEY_METHOD *meth;
116+
117+ if ((meth = EC_KEY_get_method(ec)) == NULL)
118+ return NULL;
119+ for (i = 0; i < nhelpers; i++) {
120+ if (helpers[i] != NULL && helpers[i]->ec_meth == meth)
121+ return helpers[i];
122+ }
123+ return NULL;
124+
125+}
126+
127+static void
128+helper_free(struct helper *helper)
129+{
130+ size_t i;
131+ int found = 0;
132+
133+ if (helper == NULL)
134+ return;
135+ if (helper->path == NULL || helper->ec_meth == NULL ||
136+ helper->rsa_meth == NULL)
137+ fatal_f("inconsistent helper");
138+ debug3_f("free helper for provider %s", helper->path);
139+ for (i = 0; i < nhelpers; i++) {
140+ if (helpers[i] == helper) {
141+ if (found)
142+ fatal_f("helper recorded more than once");
143+ found = 1;
144+ }
145+ else if (found)
146+ helpers[i - 1] = helpers[i];
147+ }
148+ if (found) {
149+ helpers = xrecallocarray(helpers, nhelpers,
150+ nhelpers - 1, sizeof(*helpers));
151+ nhelpers--;
152+ }
153+ free(helper->path);
154+ EC_KEY_METHOD_free(helper->ec_meth);
155+ RSA_meth_free(helper->rsa_meth);
156+ free(helper);
157+}
158+
159+static void
160+helper_terminate(struct helper *helper)
161+{
162+ if (helper == NULL) {
163+ return;
164+ } else if (helper->fd == -1) {
165+ debug3_f("already terminated");
166+ } else {
167+ debug3_f("terminating helper for %s; "
168+ "remaining %zu RSA %zu ECDSA",
169+ helper->path, helper->nrsa, helper->nec);
170+ close(helper->fd);
171+ /* XXX waitpid() */
172+ helper->fd = -1;
173+ helper->pid = -1;
174+ }
175+ /*
176+ * Don't delete the helper entry until there are no remaining keys
177+ * that reference it. Otherwise, any signing operation would call
178+ * a free'd METHOD pointer and that would be bad.
179+ */
180+ if (helper->nrsa == 0 && helper->nec == 0)
181+ helper_free(helper);
182+}
183
184 static void
185-send_msg(struct sshbuf *m)
186+send_msg(int fd, struct sshbuf *m)
187 {
188 u_char buf[4];
189 size_t mlen = sshbuf_len(m);
190 int r;
191
192+ if (fd == -1)
193+ return;
194 POKE_U32(buf, mlen);
195 if (atomicio(vwrite, fd, buf, 4) != 4 ||
196 atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
197@@ -69,12 +190,15 @@ send_msg(struct sshbuf *m)
198 }
199
200 static int
201-recv_msg(struct sshbuf *m)
202+recv_msg(int fd, struct sshbuf *m)
203 {
204 u_int l, len;
205 u_char c, buf[1024];
206 int r;
207
208+ sshbuf_reset(m);
209+ if (fd == -1)
210+ return 0; /* XXX */
211 if ((len = atomicio(read, fd, buf, 4)) != 4) {
212 error("read from helper failed: %u", len);
213 return (0); /* XXX */
214@@ -83,7 +207,6 @@ recv_msg(struct sshbuf *m)
215 if (len > 256 * 1024)
216 fatal("response too long: %u", len);
217 /* read len bytes into m */
218- sshbuf_reset(m);
219 while (len > 0) {
220 l = len;
221 if (l > sizeof(buf))
222@@ -104,14 +227,17 @@ recv_msg(struct sshbuf *m)
223 int
224 pkcs11_init(int interactive)
225 {
226- return (0);
227+ return 0;
228 }
229
230 void
231 pkcs11_terminate(void)
232 {
233- if (fd >= 0)
234- close(fd);
235+ size_t i;
236+
237+ debug3_f("terminating %zu helpers", nhelpers);
238+ for (i = 0; i < nhelpers; i++)
239+ helper_terminate(helpers[i]);
240 }
241
242 static int
243@@ -122,7 +248,11 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
244 u_char *blob = NULL, *signature = NULL;
245 size_t blen, slen = 0;
246 int r, ret = -1;
247+ struct helper *helper;
248
249+ if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1)
250+ fatal_f("no helper for PKCS11 key");
251+ debug3_f("signing with PKCS11 provider %s", helper->path);
252 if (padding != RSA_PKCS1_PADDING)
253 goto fail;
254 key = sshkey_new(KEY_UNSPEC);
255@@ -144,10 +274,10 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
256 (r = sshbuf_put_string(msg, from, flen)) != 0 ||
257 (r = sshbuf_put_u32(msg, 0)) != 0)
258 fatal_fr(r, "compose");
259- send_msg(msg);
260+ send_msg(helper->fd, msg);
261 sshbuf_reset(msg);
262
263- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
264+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
265 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
266 fatal_fr(r, "parse");
267 if (slen <= (size_t)RSA_size(rsa)) {
268@@ -163,7 +293,26 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
269 return (ret);
270 }
271
272-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
273+static int
274+rsa_finish(RSA *rsa)
275+{
276+ struct helper *helper;
277+
278+ if ((helper = helper_by_rsa(rsa)) == NULL)
279+ fatal_f("no helper for PKCS11 key");
280+ debug3_f("free PKCS11 RSA key for provider %s", helper->path);
281+ if (helper->rsa_finish != NULL)
282+ helper->rsa_finish(rsa);
283+ if (helper->nrsa == 0)
284+ fatal_f("RSA refcount error");
285+ helper->nrsa--;
286+ debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
287+ helper->path, helper->nrsa, helper->nec);
288+ if (helper->nrsa == 0 && helper->nec == 0)
289+ helper_terminate(helper);
290+ return 1;
291+}
292+
293 static ECDSA_SIG *
294 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
295 const BIGNUM *rp, EC_KEY *ec)
296@@ -175,7 +324,11 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
297 u_char *blob = NULL, *signature = NULL;
298 size_t blen, slen = 0;
299 int r, nid;
300+ struct helper *helper;
301
302+ if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1)
303+ fatal_f("no helper for PKCS11 key");
304+ debug3_f("signing with PKCS11 provider %s", helper->path);
305 nid = sshkey_ecdsa_key_to_nid(ec);
306 if (nid < 0) {
307 error_f("couldn't get curve nid");
308@@ -203,10 +356,10 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
309 (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
310 (r = sshbuf_put_u32(msg, 0)) != 0)
311 fatal_fr(r, "compose");
312- send_msg(msg);
313+ send_msg(helper->fd, msg);
314 sshbuf_reset(msg);
315
316- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
317+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
318 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
319 fatal_fr(r, "parse");
320 cp = signature;
321@@ -220,75 +373,110 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
322 sshbuf_free(msg);
323 return (ret);
324 }
325-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
326
327-static RSA_METHOD *helper_rsa;
328-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
329-static EC_KEY_METHOD *helper_ecdsa;
330-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
331+static void
332+ecdsa_do_finish(EC_KEY *ec)
333+{
334+ struct helper *helper;
335+
336+ if ((helper = helper_by_ec(ec)) == NULL)
337+ fatal_f("no helper for PKCS11 key");
338+ debug3_f("free PKCS11 ECDSA key for provider %s", helper->path);
339+ if (helper->ec_finish != NULL)
340+ helper->ec_finish(ec);
341+ if (helper->nec == 0)
342+ fatal_f("ECDSA refcount error");
343+ helper->nec--;
344+ debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
345+ helper->path, helper->nrsa, helper->nec);
346+ if (helper->nrsa == 0 && helper->nec == 0)
347+ helper_terminate(helper);
348+}
349
350 /* redirect private key crypto operations to the ssh-pkcs11-helper */
351 static void
352-wrap_key(struct sshkey *k)
353+wrap_key(struct helper *helper, struct sshkey *k)
354 {
355- if (k->type == KEY_RSA)
356- RSA_set_method(k->rsa, helper_rsa);
357-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
358- else if (k->type == KEY_ECDSA)
359- EC_KEY_set_method(k->ecdsa, helper_ecdsa);
360-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
361- else
362+ debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path);
363+ if (k->type == KEY_RSA) {
364+ RSA_set_method(k->rsa, helper->rsa_meth);
365+ if (helper->nrsa++ >= INT_MAX)
366+ fatal_f("RSA refcount error");
367+ } else if (k->type == KEY_ECDSA) {
368+ EC_KEY_set_method(k->ecdsa, helper->ec_meth);
369+ if (helper->nec++ >= INT_MAX)
370+ fatal_f("EC refcount error");
371+ } else
372 fatal_f("unknown key type");
373+ k->flags |= SSHKEY_FLAG_EXT;
374+ debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
375+ helper->path, helper->nrsa, helper->nec);
376 }
377
378 static int
379-pkcs11_start_helper_methods(void)
380+pkcs11_start_helper_methods(struct helper *helper)
381 {
382- if (helper_rsa != NULL)
383- return (0);
384-
385-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
386- int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
387+ int (*ec_init)(EC_KEY *key);
388+ int (*ec_copy)(EC_KEY *dest, const EC_KEY *src);
389+ int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp);
390+ int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key);
391+ int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key);
392+ int (*ec_sign)(int, const unsigned char *, int, unsigned char *,
393 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
394- if (helper_ecdsa != NULL)
395- return (0);
396- helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
397- if (helper_ecdsa == NULL)
398- return (-1);
399- EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
400- EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
401-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
402-
403- if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
404+ RSA_METHOD *rsa_meth;
405+ EC_KEY_METHOD *ec_meth;
406+
407+ if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL)
408+ return -1;
409+ EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL);
410+ EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign);
411+ EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish,
412+ &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public);
413+ EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish,
414+ ec_copy, ec_set_group, ec_set_private, ec_set_public);
415+
416+ if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL)
417 fatal_f("RSA_meth_dup failed");
418- if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
419- !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
420+ helper->rsa_finish = RSA_meth_get_finish(rsa_meth);
421+ if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") ||
422+ !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) ||
423+ !RSA_meth_set_finish(rsa_meth, rsa_finish))
424 fatal_f("failed to prepare method");
425
426- return (0);
427+ helper->ec_meth = ec_meth;
428+ helper->rsa_meth = rsa_meth;
429+ return 0;
430 }
431
432-static int
433-pkcs11_start_helper(void)
434+static struct helper *
435+pkcs11_start_helper(const char *path)
436 {
437 int pair[2];
438- char *helper, *verbosity = NULL;
439-
440- if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
441- verbosity = "-vvv";
442-
443- if (pkcs11_start_helper_methods() == -1) {
444- error("pkcs11_start_helper_methods failed");
445- return (-1);
446- }
447+ char *prog, *verbosity = NULL;
448+ struct helper *helper;
449+ pid_t pid;
450
451+ if (nhelpers >= INT_MAX)
452+ fatal_f("too many helpers");
453+ debug3_f("start helper for %s", path);
454 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
455- error("socketpair: %s", strerror(errno));
456- return (-1);
457+ error_f("socketpair: %s", strerror(errno));
458+ return NULL;
459+ }
460+ helper = xcalloc(1, sizeof(*helper));
461+ if (pkcs11_start_helper_methods(helper) == -1) {
462+ error_f("pkcs11_start_helper_methods failed");
463+ goto fail;
464 }
465 if ((pid = fork()) == -1) {
466- error("fork: %s", strerror(errno));
467- return (-1);
468+ error_f("fork: %s", strerror(errno));
469+ fail:
470+ close(pair[0]);
471+ close(pair[1]);
472+ RSA_meth_free(helper->rsa_meth);
473+ EC_KEY_METHOD_free(helper->ec_meth);
474+ free(helper);
475+ return NULL;
476 } else if (pid == 0) {
477 if ((dup2(pair[1], STDIN_FILENO) == -1) ||
478 (dup2(pair[1], STDOUT_FILENO) == -1)) {
479@@ -297,18 +485,27 @@ pkcs11_start_helper(void)
480 }
481 close(pair[0]);
482 close(pair[1]);
483- helper = getenv("SSH_PKCS11_HELPER");
484- if (helper == NULL || strlen(helper) == 0)
485- helper = _PATH_SSH_PKCS11_HELPER;
486- debug_f("starting %s %s", helper,
487+ prog = getenv("SSH_PKCS11_HELPER");
488+ if (prog == NULL || strlen(prog) == 0)
489+ prog = _PATH_SSH_PKCS11_HELPER;
490+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
491+ verbosity = "-vvv";
492+ debug_f("starting %s %s", prog,
493 verbosity == NULL ? "" : verbosity);
494- execlp(helper, helper, verbosity, (char *)NULL);
495- fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
496+ execlp(prog, prog, verbosity, (char *)NULL);
497+ fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno));
498 _exit(1);
499 }
500 close(pair[1]);
501- fd = pair[0];
502- return (0);
503+ helper->fd = pair[0];
504+ helper->path = xstrdup(path);
505+ helper->pid = pid;
506+ debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers,
507+ helper->path, helper->fd, (long)helper->pid);
508+ helpers = xrecallocarray(helpers, nhelpers,
509+ nhelpers + 1, sizeof(*helpers));
510+ helpers[nhelpers++] = helper;
511+ return helper;
512 }
513
514 int
515@@ -322,9 +519,11 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
516 size_t blen;
517 u_int nkeys, i;
518 struct sshbuf *msg;
519+ struct helper *helper;
520
521- if (fd < 0 && pkcs11_start_helper() < 0)
522- return (-1);
523+ if ((helper = helper_by_provider(name)) == NULL &&
524+ (helper = pkcs11_start_helper(name)) == NULL)
525+ return -1;
526
527 if ((msg = sshbuf_new()) == NULL)
528 fatal_f("sshbuf_new failed");
529@@ -332,10 +531,10 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
530 (r = sshbuf_put_cstring(msg, name)) != 0 ||
531 (r = sshbuf_put_cstring(msg, pin)) != 0)
532 fatal_fr(r, "compose");
533- send_msg(msg);
534+ send_msg(helper->fd, msg);
535 sshbuf_reset(msg);
536
537- type = recv_msg(msg);
538+ type = recv_msg(helper->fd, msg);
539 if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
540 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
541 fatal_fr(r, "parse nkeys");
542@@ -349,7 +548,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
543 fatal_fr(r, "parse key");
544 if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
545 fatal_fr(r, "decode key");
546- wrap_key(k);
547+ wrap_key(helper, k);
548 (*keysp)[i] = k;
549 if (labelsp)
550 (*labelsp)[i] = label;
551@@ -370,22 +569,15 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
552 int
553 pkcs11_del_provider(char *name)
554 {
555- int r, ret = -1;
556- struct sshbuf *msg;
557-
558- if ((msg = sshbuf_new()) == NULL)
559- fatal_f("sshbuf_new failed");
560- if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
561- (r = sshbuf_put_cstring(msg, name)) != 0 ||
562- (r = sshbuf_put_cstring(msg, "")) != 0)
563- fatal_fr(r, "compose");
564- send_msg(msg);
565- sshbuf_reset(msg);
566-
567- if (recv_msg(msg) == SSH_AGENT_SUCCESS)
568- ret = 0;
569- sshbuf_free(msg);
570- return (ret);
571+ struct helper *helper;
572+
573+ /*
574+ * ssh-agent deletes keys before calling this, so the helper entry
575+ * should be gone before we get here.
576+ */
577+ debug3_f("delete %s", name);
578+ if ((helper = helper_by_provider(name)) != NULL)
579+ helper_terminate(helper);
580+ return 0;
581 }
582-
583 #endif /* ENABLE_PKCS11 */
584--
5852.40.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0002.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0002.patch
new file mode 100644
index 0000000000..81f4cc5fba
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0002.patch
@@ -0,0 +1,173 @@
1From 29ef8a04866ca14688d5b7fed7b8b9deab851f77 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 2/4] 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]
16
17CVE: CVE-2023-38408
18
19Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
20---
21 misc.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
22 misc.h | 1 +
23 ssh-pkcs11.c | 4 +++
24 ssh-sk.c | 6 ++--
25 4 files changed, 86 insertions(+), 2 deletions(-)
26
27diff --git a/misc.c b/misc.c
28index 417498d..d0270e7 100644
29--- a/misc.c
30+++ b/misc.c
31@@ -22,6 +22,7 @@
32
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35+#include <sys/mman.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <sys/time.h>
39@@ -35,6 +36,9 @@
40 #ifdef HAVE_POLL_H
41 #include <poll.h>
42 #endif
43+#ifdef HAVE_NLIST_H
44+#include <nlist.h>
45+#endif
46 #include <signal.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49@@ -2784,3 +2788,76 @@ lookup_env_in_list(const char *env, char * const *envs, size_t nenvs)
50 }
51 return NULL;
52 }
53+
54+
55+/*
56+ * Returns zero if the library at 'path' contains symbol 's', nonzero
57+ * otherwise.
58+ */
59+int
60+lib_contains_symbol(const char *path, const char *s)
61+{
62+#ifdef HAVE_NLIST_H
63+ struct nlist nl[2];
64+ int ret = -1, r;
65+
66+ memset(nl, 0, sizeof(nl));
67+ nl[0].n_name = xstrdup(s);
68+ nl[1].n_name = NULL;
69+ if ((r = nlist(path, nl)) == -1) {
70+ error_f("nlist failed for %s", path);
71+ goto out;
72+ }
73+ if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) {
74+ error_f("library %s does not contain symbol %s", path, s);
75+ goto out;
76+ }
77+ /* success */
78+ ret = 0;
79+ out:
80+ free(nl[0].n_name);
81+ return ret;
82+#else /* HAVE_NLIST_H */
83+ int fd, ret = -1;
84+ struct stat st;
85+ void *m = NULL;
86+ size_t sz = 0;
87+
88+ memset(&st, 0, sizeof(st));
89+ if ((fd = open(path, O_RDONLY)) < 0) {
90+ error_f("open %s: %s", path, strerror(errno));
91+ return -1;
92+ }
93+ if (fstat(fd, &st) != 0) {
94+ error_f("fstat %s: %s", path, strerror(errno));
95+ goto out;
96+ }
97+ if (!S_ISREG(st.st_mode)) {
98+ error_f("%s is not a regular file", path);
99+ goto out;
100+ }
101+ if (st.st_size < 0 ||
102+ (size_t)st.st_size < strlen(s) ||
103+ st.st_size >= INT_MAX/2) {
104+ error_f("%s bad size %lld", path, (long long)st.st_size);
105+ goto out;
106+ }
107+ sz = (size_t)st.st_size;
108+ if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED ||
109+ m == NULL) {
110+ error_f("mmap %s: %s", path, strerror(errno));
111+ goto out;
112+ }
113+ if (memmem(m, sz, s, strlen(s)) == NULL) {
114+ error_f("%s does not contain expected string %s", path, s);
115+ goto out;
116+ }
117+ /* success */
118+ ret = 0;
119+ out:
120+ if (m != NULL && m != MAP_FAILED)
121+ munmap(m, sz);
122+ close(fd);
123+ return ret;
124+#endif /* HAVE_NLIST_H */
125+}
126diff --git a/misc.h b/misc.h
127index 2e1b5fe..3f48315 100644
128--- a/misc.h
129+++ b/misc.h
130@@ -96,6 +96,7 @@ int parse_absolute_time(const char *, uint64_t *);
131 void format_absolute_time(uint64_t, char *, size_t);
132 int path_absolute(const char *);
133 int stdfd_devnull(int, int, int);
134+int lib_contains_symbol(const char *, const char *);
135
136 void sock_set_v6only(int);
137
138diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
139index b2e2b32..5eb28e9 100644
140--- a/ssh-pkcs11.c
141+++ b/ssh-pkcs11.c
142@@ -1532,6 +1532,10 @@ pkcs11_register_provider(char *provider_id, char *pin,
143 debug_f("provider already registered: %s", provider_id);
144 goto fail;
145 }
146+ if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
147+ error("provider %s is not a PKCS11 library", provider_id);
148+ goto fail;
149+ }
150 /* open shared pkcs11-library */
151 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
152 error("dlopen %s failed: %s", provider_id, dlerror());
153diff --git a/ssh-sk.c b/ssh-sk.c
154index a1ff5cc..1042bf6 100644
155--- a/ssh-sk.c
156+++ b/ssh-sk.c
157@@ -132,10 +132,12 @@ sshsk_open(const char *path)
158 #endif
159 return ret;
160 }
161- if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
162- error("Provider \"%s\" dlopen failed: %s", path, dlerror());
163+ if (lib_contains_symbol(path, "sk_api_version") != 0) {
164+ error("provider %s is not an OpenSSH FIDO library", path);
165 goto fail;
166 }
167+ if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL)
168+ fatal("Provider \"%s\" dlopen failed: %s", path, dlerror());
169 if ((ret->sk_api_version = dlsym(ret->dlhandle,
170 "sk_api_version")) == NULL) {
171 error("Provider \"%s\" dlsym(sk_api_version) failed: %s",
172--
1732.40.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0003.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0003.patch
new file mode 100644
index 0000000000..f226f12edc
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0003.patch
@@ -0,0 +1,36 @@
1From 892506b13654301f69f9545f48213fc210e5c5cc 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 3/4] 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]
10
11CVE: CVE-2023-38408
12
13Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
14---
15 ssh-pkcs11.c | 6 ++----
16 1 file changed, 2 insertions(+), 4 deletions(-)
17
18diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
19index 5eb28e9..0aef379 100644
20--- a/ssh-pkcs11.c
21+++ b/ssh-pkcs11.c
22@@ -1541,10 +1541,8 @@ pkcs11_register_provider(char *provider_id, char *pin,
23 error("dlopen %s failed: %s", provider_id, dlerror());
24 goto fail;
25 }
26- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
27- error("dlsym(C_GetFunctionList) failed: %s", dlerror());
28- goto fail;
29- }
30+ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
31+ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
32 p = xcalloc(1, sizeof(*p));
33 p->name = xstrdup(provider_id);
34 p->handle = handle;
35--
362.40.0
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0004.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0004.patch
new file mode 100644
index 0000000000..1ff8505938
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-0004.patch
@@ -0,0 +1,114 @@
1From 1f2731f5d7a8f8a8385c6031667ed29072c0d92a 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 4/4] 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]
19
20CVE: CVE-2023-38408
21
22Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
23---
24 ssh-agent.1 | 21 +++++++++++++++++++++
25 ssh-agent.c | 21 ++++++++++++++++++++-
26 2 files changed, 41 insertions(+), 1 deletion(-)
27
28diff --git a/ssh-agent.1 b/ssh-agent.1
29index ed8c870..15d0a47 100644
30--- a/ssh-agent.1
31+++ b/ssh-agent.1
32@@ -102,6 +102,27 @@ The default is
33 Kill the current agent (given by the
34 .Ev SSH_AGENT_PID
35 environment variable).
36+Currently two options are supported:
37+.Cm allow-remote-pkcs11
38+and
39+.Cm no-restrict-websafe .
40+.Pp
41+The
42+.Cm allow-remote-pkcs11
43+option allows clients of a forwarded
44+.Nm
45+to load PKCS#11 or FIDO provider libraries.
46+By default only local clients may perform this operation.
47+Note that signalling that a
48+.Nm
49+client remote is performed by
50+.Xr ssh 1 ,
51+and use of other tools to forward access to the agent socket may circumvent
52+this restriction.
53+.Pp
54+The
55+.Cm no-restrict-websafe ,
56+instructs
57 .It Fl P Ar allowed_providers
58 Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO
59 authenticator middleware shared libraries that may be used with the
60diff --git a/ssh-agent.c b/ssh-agent.c
61index 03ae2b0..19eeaae 100644
62--- a/ssh-agent.c
63+++ b/ssh-agent.c
64@@ -171,6 +171,12 @@ char socket_dir[PATH_MAX];
65 /* Pattern-list of allowed PKCS#11/Security key paths */
66 static char *allowed_providers;
67
68+/*
69+ * Allows PKCS11 providers or SK keys that use non-internal providers to
70+ * be added over a remote connection (identified by session-bind@openssh.com).
71+ */
72+static int remote_add_provider;
73+
74 /* locking */
75 #define LOCK_SIZE 32
76 #define LOCK_SALT_SIZE 16
77@@ -1239,6 +1245,12 @@ process_add_identity(SocketEntry *e)
78 if (strcasecmp(sk_provider, "internal") == 0) {
79 debug_f("internal provider");
80 } else {
81+ if (e->nsession_ids != 0 && !remote_add_provider) {
82+ verbose("failed add of SK provider \"%.100s\": "
83+ "remote addition of providers is disabled",
84+ sk_provider);
85+ goto out;
86+ }
87 if (realpath(sk_provider, canonical_provider) == NULL) {
88 verbose("failed provider \"%.100s\": "
89 "realpath: %s", sk_provider,
90@@ -1402,6 +1414,11 @@ process_add_smartcard_key(SocketEntry *e)
91 error_f("failed to parse constraints");
92 goto send;
93 }
94+ if (e->nsession_ids != 0 && !remote_add_provider) {
95+ verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
96+ "providers is disabled", provider);
97+ goto send;
98+ }
99 if (realpath(provider, canonical_provider) == NULL) {
100 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
101 provider, strerror(errno));
102@@ -2061,7 +2078,9 @@ main(int ac, char **av)
103 break;
104 case 'O':
105 if (strcmp(optarg, "no-restrict-websafe") == 0)
106- restrict_websafe = 0;
107+ restrict_websafe = 0;
108+ else if (strcmp(optarg, "allow-remote-pkcs11") == 0)
109+ remote_add_provider = 1;
110 else
111 fatal("Unknown -O option");
112 break;
113--
1142.40.0
diff --git a/meta/recipes-connectivity/openssh/openssh_8.9p1.bb b/meta/recipes-connectivity/openssh/openssh_8.9p1.bb
index b403b355a6..da7ab7716c 100644
--- a/meta/recipes-connectivity/openssh/openssh_8.9p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_8.9p1.bb
@@ -28,6 +28,10 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
28 file://0001-Default-to-not-using-sandbox-when-cross-compiling.patch \ 28 file://0001-Default-to-not-using-sandbox-when-cross-compiling.patch \
29 file://7280401bdd77ca54be6867a154cc01e0d72612e0.patch \ 29 file://7280401bdd77ca54be6867a154cc01e0d72612e0.patch \
30 file://0001-upstream-include-destination-constraints-for-smartca.patch \ 30 file://0001-upstream-include-destination-constraints-for-smartca.patch \
31 file://CVE-2023-38408-0001.patch \
32 file://CVE-2023-38408-0002.patch \
33 file://CVE-2023-38408-0003.patch \
34 file://CVE-2023-38408-0004.patch \
31 " 35 "
32SRC_URI[sha256sum] = "fd497654b7ab1686dac672fb83dfb4ba4096e8b5ffcdaccd262380ae58bec5e7" 36SRC_URI[sha256sum] = "fd497654b7ab1686dac672fb83dfb4ba4096e8b5ffcdaccd262380ae58bec5e7"
33 37