summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/openssh/openssh
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity/openssh/openssh')
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2020-14145.patch97
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2021-28041.patch20
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2021-41617.patch52
-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/CVE-2023-48795.patch468
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2023-51385.patch95
-rw-r--r--meta/recipes-connectivity/openssh/openssh/sshd.socket1
-rw-r--r--meta/recipes-connectivity/openssh/openssh/sshd@.service2
19 files changed, 2919 insertions, 2 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2020-14145.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2020-14145.patch
new file mode 100644
index 0000000000..3adb981fb4
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2020-14145.patch
@@ -0,0 +1,97 @@
1From b3855ff053f5078ec3d3c653cdaedefaa5fc362d Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 18 Sep 2020 05:23:03 +0000
4Subject: upstream: tweak the client hostkey preference ordering algorithm to
5
6prefer the default ordering if the user has a key that matches the
7best-preference default algorithm.
8
9feedback and ok markus@
10
11OpenBSD-Commit-ID: a92dd7d7520ddd95c0a16786a7519e6d0167d35f
12
13Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
14---
15 sshconnect2.c | 41 ++++++++++++++++++++++++++++++++++++++---
16 1 file changed, 38 insertions(+), 3 deletions(-)
17
18CVE: CVE-2020-14145
19Upstream-Status: Backport [https://anongit.mindrot.org/openssh.git/patch/?id=b3855ff053f5078ec3d3c653cdaedefaa5fc362d]
20Comment: Refreshed first hunk
21
22diff --git a/sshconnect2.c b/sshconnect2.c
23index 347e348c..f64aae66 100644
24--- a/sshconnect2.c
25+++ b/sshconnect2.c
26@@ -1,4 +1,4 @@
27-/* $OpenBSD: sshconnect2.c,v 1.320 2020/02/06 22:48:23 djm Exp $ */
28+/* $OpenBSD: sshconnect2.c,v 1.326 2020/09/18 05:23:03 djm Exp $ */
29 /*
30 * Copyright (c) 2000 Markus Friedl. All rights reserved.
31 * Copyright (c) 2008 Damien Miller. All rights reserved.
32@@ -102,12 +102,25 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
33 return 0;
34 }
35
36+/* Returns the first item from a comma-separated algorithm list */
37+static char *
38+first_alg(const char *algs)
39+{
40+ char *ret, *cp;
41+
42+ ret = xstrdup(algs);
43+ if ((cp = strchr(ret, ',')) != NULL)
44+ *cp = '\0';
45+ return ret;
46+}
47+
48 static char *
49 order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
50 {
51- char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
52+ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL;
53+ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL;
54 size_t maxlen;
55- struct hostkeys *hostkeys;
56+ struct hostkeys *hostkeys = NULL;
57 int ktype;
58 u_int i;
59
60@@ -119,6 +132,26 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
61 for (i = 0; i < options.num_system_hostfiles; i++)
62 load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
63
64+ /*
65+ * If a plain public key exists that matches the type of the best
66+ * preference HostkeyAlgorithms, then use the whole list as is.
67+ * Note that we ignore whether the best preference algorithm is a
68+ * certificate type, as sshconnect.c will downgrade certs to
69+ * plain keys if necessary.
70+ */
71+ best = first_alg(options.hostkeyalgorithms);
72+ if (lookup_key_in_hostkeys_by_type(hostkeys,
73+ sshkey_type_plain(sshkey_type_from_name(best)), NULL)) {
74+ debug3("%s: have matching best-preference key type %s, "
75+ "using HostkeyAlgorithms verbatim", __func__, best);
76+ ret = xstrdup(options.hostkeyalgorithms);
77+ goto out;
78+ }
79+
80+ /*
81+ * Otherwise, prefer the host key algorithms that match known keys
82+ * while keeping the ordering of HostkeyAlgorithms as much as possible.
83+ */
84 oavail = avail = xstrdup(options.hostkeyalgorithms);
85 maxlen = strlen(avail) + 1;
86 first = xmalloc(maxlen);
87@@ -159,6 +192,8 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
88 if (*first != '\0')
89 debug3("%s: prefer hostkeyalgs: %s", __func__, first);
90
91+ out:
92+ free(best);
93 free(first);
94 free(last);
95 free(hostname);
96--
97cgit v1.2.3
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2021-28041.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2021-28041.patch
new file mode 100644
index 0000000000..9fd7e932d1
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2021-28041.patch
@@ -0,0 +1,20 @@
1Description: fix double-free memory corruption in ssh-agent
2Author: Marc Deslauriers <marc.deslauriers@canonical.com>
3Origin: minimal fix for https://github.com/openssh/openssh-portable/commit/e04fd6dde16de1cdc5a4d9946397ff60d96568db
4
5Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
6
7CVE: CVE-2021-28041
8Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/o/openssh/openssh_8.2p1-4ubuntu0.3.debian.tar.xz]
9Comment: No change in any hunk
10
11--- a/ssh-agent.c
12+++ b/ssh-agent.c
13@@ -496,6 +496,7 @@ process_add_identity(SocketEntry *e)
14 goto err;
15 }
16 free(ext_name);
17+ ext_name = NULL;
18 break;
19 default:
20 error("%s: Unknown constraint %d", __func__, ctype);
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2021-41617.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2021-41617.patch
new file mode 100644
index 0000000000..bda896f581
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2021-41617.patch
@@ -0,0 +1,52 @@
1From a6414400ec94a17871081f7df24f910a6ee01b8b Mon Sep 17 00:00:00 2001
2From: Ali Abdallah <aabdallah@suse.de>
3Date: Wed, 24 Nov 2021 13:33:39 +0100
4Subject: [PATCH] CVE-2021-41617 fix
5
6backport of the following two upstream commits
7
8f3cbe43e28fe71427d41cfe3a17125b972710455
9bf944e3794eff5413f2df1ef37cddf96918c6bde
10
11CVE-2021-41617 failed to correctly initialise supplemental groups
12when executing an AuthorizedKeysCommand or AuthorizedPrincipalsCommand,
13where a AuthorizedKeysCommandUser or AuthorizedPrincipalsCommandUser
14directive has been set to run the command as a different user. Instead
15these commands would inherit the groups that sshd(8) was started with.
16---
17 auth.c | 8 ++++++++
18 1 file changed, 8 insertions(+)
19
20CVE: CVE-2021-41617
21Upstream-Status: Backport [https://bugzilla.suse.com/attachment.cgi?id=854015]
22Comment: No change in any hunk
23Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
24
25diff --git a/auth.c b/auth.c
26index 163038f..a47b267 100644
27--- a/auth.c
28+++ b/auth.c
29@@ -52,6 +52,7 @@
30 #include <limits.h>
31 #include <netdb.h>
32 #include <time.h>
33+#include <grp.h>
34
35 #include "xmalloc.h"
36 #include "match.h"
37@@ -851,6 +852,13 @@ subprocess(const char *tag, struct passwd *pw, const char *command,
38 }
39 closefrom(STDERR_FILENO + 1);
40
41+ if (geteuid() == 0 &&
42+ initgroups(pw->pw_name, pw->pw_gid) == -1) {
43+ error("%s: initgroups(%s, %u): %s", tag,
44+ pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
45+ _exit(1);
46+ }
47+
48 /* Don't use permanently_set_uid() here to avoid fatal() */
49 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
50 error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
51--
522.26.2
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/CVE-2023-48795.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-48795.patch
new file mode 100644
index 0000000000..57c45e3d93
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-48795.patch
@@ -0,0 +1,468 @@
1(modified to not remove ssh_packet_read_expect(), to add to
2KexAlgorithms in sshd.c and sshconnect2.c as this version pre-dates
3kex_proposal_populate_entries(), replace debug*_f() with debug*(),
4error*_f() with error*(), and fatal_f() with fatal())
5
6Backport of:
7
8From 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 Mon Sep 17 00:00:00 2001
9From: "djm@openbsd.org" <djm@openbsd.org>
10Date: Mon, 18 Dec 2023 14:45:17 +0000
11Subject: [PATCH] upstream: implement "strict key exchange" in ssh and sshd
12
13This adds a protocol extension to improve the integrity of the SSH
14transport protocol, particular in and around the initial key exchange
15(KEX) phase.
16
17Full details of the extension are in the PROTOCOL file.
18
19with markus@
20
21OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14
22
23Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/openssh/tree/debian/patches/CVE-2023-48795.patch?h=ubuntu/focal-security
24Upstream commit https://github.com/openssh/openssh-portable/commit/1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5]
25CVE: CVE-2023-48795
26Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
27---
28 PROTOCOL | 26 +++++++++++++++++
29 kex.c | 68 +++++++++++++++++++++++++++++++++-----------
30 kex.h | 1 +
31 packet.c | 78 ++++++++++++++++++++++++++++++++++++++-------------
32 sshconnect2.c | 14 +++------
33 sshd.c | 7 +++--
34 6 files changed, 146 insertions(+), 48 deletions(-)
35
36diff --git a/PROTOCOL b/PROTOCOL
37index f75c1c0..89bddfe 100644
38--- a/PROTOCOL
39+++ b/PROTOCOL
40@@ -102,6 +102,32 @@ OpenSSH supports the use of ECDH in Curve25519 for key exchange as
41 described at:
42 http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519
43
44+1.9 transport: strict key exchange extension
45+
46+OpenSSH supports a number of transport-layer hardening measures under
47+a "strict KEX" feature. This feature is signalled similarly to the
48+RFC8308 ext-info feature: by including a additional algorithm in the
49+initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append
50+"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server
51+may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms
52+are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored
53+if they are present in subsequent SSH2_MSG_KEXINIT packets.
54+
55+When an endpoint that supports this extension observes this algorithm
56+name in a peer's KEXINIT packet, it MUST make the following changes to
57+the the protocol:
58+
59+a) During initial KEX, terminate the connection if any unexpected or
60+ out-of-sequence packet is received. This includes terminating the
61+ connection if the first packet received is not SSH2_MSG_KEXINIT.
62+ Unexpected packets for the purpose of strict KEX include messages
63+ that are otherwise valid at any time during the connection such as
64+ SSH2_MSG_DEBUG and SSH2_MSG_IGNORE.
65+b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the
66+ packet sequence number to zero. This behaviour persists for the
67+ duration of the connection (i.e. not just the first
68+ SSH2_MSG_NEWKEYS).
69+
70 2. Connection protocol changes
71
72 2.1. connection: Channel write close extension "eow@openssh.com"
73diff --git a/kex.c b/kex.c
74index ce85f04..3129a4e 100644
75--- a/kex.c
76+++ b/kex.c
77@@ -63,7 +63,7 @@
78 #include "digest.h"
79
80 /* prototype */
81-static int kex_choose_conf(struct ssh *);
82+static int kex_choose_conf(struct ssh *, uint32_t seq);
83 static int kex_input_newkeys(int, u_int32_t, struct ssh *);
84
85 static const char *proposal_names[PROPOSAL_MAX] = {
86@@ -173,6 +173,18 @@ kex_names_valid(const char *names)
87 return 1;
88 }
89
90+/* returns non-zero if proposal contains any algorithm from algs */
91+static int
92+has_any_alg(const char *proposal, const char *algs)
93+{
94+ char *cp;
95+
96+ if ((cp = match_list(proposal, algs, NULL)) == NULL)
97+ return 0;
98+ free(cp);
99+ return 1;
100+}
101+
102 /*
103 * Concatenate algorithm names, avoiding duplicates in the process.
104 * Caller must free returned string.
105@@ -180,7 +192,7 @@ kex_names_valid(const char *names)
106 char *
107 kex_names_cat(const char *a, const char *b)
108 {
109- char *ret = NULL, *tmp = NULL, *cp, *p, *m;
110+ char *ret = NULL, *tmp = NULL, *cp, *p;
111 size_t len;
112
113 if (a == NULL || *a == '\0')
114@@ -197,10 +209,8 @@ kex_names_cat(const char *a, const char *b)
115 }
116 strlcpy(ret, a, len);
117 for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
118- if ((m = match_list(ret, p, NULL)) != NULL) {
119- free(m);
120+ if (has_any_alg(ret, p))
121 continue; /* Algorithm already present */
122- }
123 if (strlcat(ret, ",", len) >= len ||
124 strlcat(ret, p, len) >= len) {
125 free(tmp);
126@@ -409,7 +419,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
127 {
128 int r;
129
130- error("kex protocol error: type %d seq %u", type, seq);
131+ /* If in strict mode, any unexpected message is an error */
132+ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
133+ ssh_packet_disconnect(ssh, "strict KEX violation: "
134+ "unexpected packet type %u (seqnr %u)", type, seq);
135+ }
136+ error("type %u seq %u", type, seq);
137 if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
138 (r = sshpkt_put_u32(ssh, seq)) != 0 ||
139 (r = sshpkt_send(ssh)) != 0)
140@@ -481,6 +496,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
141 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
142 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
143 return r;
144+ if (ninfo >= 1024) {
145+ error("SSH2_MSG_EXT_INFO with too many entries, expected "
146+ "<=1024, received %u", ninfo);
147+ return dispatch_protocol_error(type, seq, ssh);
148+ }
149 for (i = 0; i < ninfo; i++) {
150 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
151 return r;
152@@ -581,7 +601,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
153 error("%s: no hex", __func__);
154 return SSH_ERR_INTERNAL_ERROR;
155 }
156- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
157+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
158 ptr = sshpkt_ptr(ssh, &dlen);
159 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
160 return r;
161@@ -617,7 +637,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
162 if (!(kex->flags & KEX_INIT_SENT))
163 if ((r = kex_send_kexinit(ssh)) != 0)
164 return r;
165- if ((r = kex_choose_conf(ssh)) != 0)
166+ if ((r = kex_choose_conf(ssh, seq)) != 0)
167 return r;
168
169 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
170@@ -880,7 +900,13 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
171 }
172
173 static int
174-kex_choose_conf(struct ssh *ssh)
175+kexalgs_contains(char **peer, const char *ext)
176+{
177+ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
178+}
179+
180+static int
181+kex_choose_conf(struct ssh *ssh, uint32_t seq)
182 {
183 struct kex *kex = ssh->kex;
184 struct newkeys *newkeys;
185@@ -905,13 +931,23 @@ kex_choose_conf(struct ssh *ssh)
186 sprop=peer;
187 }
188
189- /* Check whether client supports ext_info_c */
190- if (kex->server && (kex->flags & KEX_INITIAL)) {
191- char *ext;
192-
193- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
194- kex->ext_info_c = (ext != NULL);
195- free(ext);
196+ /* Check whether peer supports ext_info/kex_strict */
197+ if ((kex->flags & KEX_INITIAL) != 0) {
198+ if (kex->server) {
199+ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
200+ kex->kex_strict = kexalgs_contains(peer,
201+ "kex-strict-c-v00@openssh.com");
202+ } else {
203+ kex->kex_strict = kexalgs_contains(peer,
204+ "kex-strict-s-v00@openssh.com");
205+ }
206+ if (kex->kex_strict) {
207+ debug3("will use strict KEX ordering");
208+ if (seq != 0)
209+ ssh_packet_disconnect(ssh,
210+ "strict KEX violation: "
211+ "KEXINIT was not the first packet");
212+ }
213 }
214
215 /* Algorithm Negotiation */
216diff --git a/kex.h b/kex.h
217index a5ae6ac..cae38f7 100644
218--- a/kex.h
219+++ b/kex.h
220@@ -145,6 +145,7 @@ struct kex {
221 u_int kex_type;
222 char *server_sig_algs;
223 int ext_info_c;
224+ int kex_strict;
225 struct sshbuf *my;
226 struct sshbuf *peer;
227 struct sshbuf *client_version;
228diff --git a/packet.c b/packet.c
229index 6d3e917..43139f9 100644
230--- a/packet.c
231+++ b/packet.c
232@@ -1203,8 +1203,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
233 sshbuf_dump(state->output, stderr);
234 #endif
235 /* increment sequence number for outgoing packets */
236- if (++state->p_send.seqnr == 0)
237+ if (++state->p_send.seqnr == 0) {
238+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
239+ ssh_packet_disconnect(ssh, "outgoing sequence number "
240+ "wrapped during initial key exchange");
241+ }
242 logit("outgoing seqnr wraps around");
243+ }
244 if (++state->p_send.packets == 0)
245 if (!(ssh->compat & SSH_BUG_NOREKEY))
246 return SSH_ERR_NEED_REKEY;
247@@ -1212,6 +1217,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
248 state->p_send.bytes += len;
249 sshbuf_reset(state->outgoing_packet);
250
251+ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
252+ debug("resetting send seqnr %u", state->p_send.seqnr);
253+ state->p_send.seqnr = 0;
254+ }
255+
256 if (type == SSH2_MSG_NEWKEYS)
257 r = ssh_set_newkeys(ssh, MODE_OUT);
258 else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
259@@ -1345,8 +1355,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
260 /* Stay in the loop until we have received a complete packet. */
261 for (;;) {
262 /* Try to read a packet from the buffer. */
263- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
264- if (r != 0)
265+ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0)
266 break;
267 /* If we got a packet, return it. */
268 if (*typep != SSH_MSG_NONE)
269@@ -1633,10 +1642,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
270 if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
271 goto out;
272 }
273+
274 if (seqnr_p != NULL)
275 *seqnr_p = state->p_read.seqnr;
276- if (++state->p_read.seqnr == 0)
277+ if (++state->p_read.seqnr == 0) {
278+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
279+ ssh_packet_disconnect(ssh, "incoming sequence number "
280+ "wrapped during initial key exchange");
281+ }
282 logit("incoming seqnr wraps around");
283+ }
284 if (++state->p_read.packets == 0)
285 if (!(ssh->compat & SSH_BUG_NOREKEY))
286 return SSH_ERR_NEED_REKEY;
287@@ -1702,6 +1717,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
288 #endif
289 /* reset for next packet */
290 state->packlen = 0;
291+ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
292+ debug("resetting read seqnr %u", state->p_read.seqnr);
293+ state->p_read.seqnr = 0;
294+ }
295
296 /* do we need to rekey? */
297 if (ssh_packet_need_rekeying(ssh, 0)) {
298@@ -1726,10 +1745,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
299 r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
300 if (r != 0)
301 return r;
302- if (*typep) {
303- state->keep_alive_timeouts = 0;
304- DBG(debug("received packet type %d", *typep));
305+ if (*typep == 0) {
306+ /* no message ready */
307+ return 0;
308+ }
309+ state->keep_alive_timeouts = 0;
310+ DBG(debug("received packet type %d", *typep));
311+
312+ /* Always process disconnect messages */
313+ if (*typep == SSH2_MSG_DISCONNECT) {
314+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
315+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
316+ return r;
317+ /* Ignore normal client exit notifications */
318+ do_log2(ssh->state->server_side &&
319+ reason == SSH2_DISCONNECT_BY_APPLICATION ?
320+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
321+ "Received disconnect from %s port %d:"
322+ "%u: %.400s", ssh_remote_ipaddr(ssh),
323+ ssh_remote_port(ssh), reason, msg);
324+ free(msg);
325+ return SSH_ERR_DISCONNECTED;
326 }
327+
328+ /*
329+ * Do not implicitly handle any messages here during initial
330+ * KEX when in strict mode. They will be need to be allowed
331+ * explicitly by the KEX dispatch table or they will generate
332+ * protocol errors.
333+ */
334+ if (ssh->kex != NULL &&
335+ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict)
336+ return 0;
337+ /* Implicitly handle transport-level messages */
338 switch (*typep) {
339 case SSH2_MSG_IGNORE:
340 debug3("Received SSH2_MSG_IGNORE");
341@@ -1744,19 +1792,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
342 debug("Remote: %.900s", msg);
343 free(msg);
344 break;
345- case SSH2_MSG_DISCONNECT:
346- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
347- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
348- return r;
349- /* Ignore normal client exit notifications */
350- do_log2(ssh->state->server_side &&
351- reason == SSH2_DISCONNECT_BY_APPLICATION ?
352- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
353- "Received disconnect from %s port %d:"
354- "%u: %.400s", ssh_remote_ipaddr(ssh),
355- ssh_remote_port(ssh), reason, msg);
356- free(msg);
357- return SSH_ERR_DISCONNECTED;
358 case SSH2_MSG_UNIMPLEMENTED:
359 if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
360 return r;
361@@ -2235,6 +2270,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
362 (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
363 (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
364 (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
365+ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 ||
366 (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
367 (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
368 (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
369@@ -2397,6 +2433,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
370 (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
371 (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
372 (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
373+ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 ||
374 (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
375 (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
376 (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
377@@ -2724,6 +2761,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
378 vsnprintf(buf, sizeof(buf), fmt, args);
379 va_end(args);
380
381+ debug2("sending SSH2_MSG_DISCONNECT: %s", buf);
382 if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
383 (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
384 (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
385diff --git a/sshconnect2.c b/sshconnect2.c
386index 5df9477..617ed9f 100644
387--- a/sshconnect2.c
388+++ b/sshconnect2.c
389@@ -218,7 +218,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
390 fatal("%s: kex_assemble_namelist", __func__);
391 free(all_key);
392
393- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
394+ if ((s = kex_names_cat(options.kex_algorithms,
395+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
396 fatal("%s: kex_names_cat", __func__);
397 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
398 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
399@@ -343,7 +344,6 @@ struct cauthmethod {
400 };
401
402 static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
403-static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
404 static int input_userauth_success(int, u_int32_t, struct ssh *);
405 static int input_userauth_failure(int, u_int32_t, struct ssh *);
406 static int input_userauth_banner(int, u_int32_t, struct ssh *);
407@@ -460,7 +460,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
408
409 ssh->authctxt = &authctxt;
410 ssh_dispatch_init(ssh, &input_userauth_error);
411- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
412+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info);
413 ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
414 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */
415 pubkey_cleanup(ssh);
416@@ -505,13 +505,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
417 return r;
418 }
419
420-/* ARGSUSED */
421-static int
422-input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
423-{
424- return kex_input_ext_info(type, seqnr, ssh);
425-}
426-
427 void
428 userauth(struct ssh *ssh, char *authlist)
429 {
430@@ -593,6 +586,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
431 free(authctxt->methoddata);
432 authctxt->methoddata = NULL;
433 authctxt->success = 1; /* break out */
434+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error);
435 return 0;
436 }
437
438diff --git a/sshd.c b/sshd.c
439index 60b2aaf..ffea38c 100644
440--- a/sshd.c
441+++ b/sshd.c
442@@ -2323,11 +2323,13 @@ static void
443 do_ssh2_kex(struct ssh *ssh)
444 {
445 char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
446+ char *s;
447 struct kex *kex;
448 int r;
449
450- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
451- options.kex_algorithms);
452+ if ((s = kex_names_cat(options.kex_algorithms, "kex-strict-s-v00@openssh.com")) == NULL)
453+ fatal("kex_names_cat");
454+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
455 myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
456 options.ciphers);
457 myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
458@@ -2382,6 +2384,7 @@ do_ssh2_kex(struct ssh *ssh)
459 packet_send();
460 packet_write_wait();
461 #endif
462+ free(s);
463 debug("KEX done");
464 }
465
466--
4672.25.1
468
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-51385.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-51385.patch
new file mode 100644
index 0000000000..0ba8c312d0
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-51385.patch
@@ -0,0 +1,95 @@
1From 7ef3787c84b6b524501211b11a26c742f829af1a Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Mon, 18 Dec 2023 14:47:44 +0000
4Subject: [PATCH] upstream: ban user/hostnames with most shell metacharacters
5
6This makes ssh(1) refuse user or host names provided on the
7commandline that contain most shell metacharacters.
8
9Some programs that invoke ssh(1) using untrusted data do not filter
10metacharacters in arguments they supply. This could create
11interactions with user-specified ProxyCommand and other directives
12that allow shell injection attacks to occur.
13
14It's a mistake to invoke ssh(1) with arbitrary untrusted arguments,
15but getting this stuff right can be tricky, so this should prevent
16most obvious ways of creating risky situations. It however is not
17and cannot be perfect: ssh(1) has no practical way of interpreting
18what shell quoting rules are in use and how they interact with the
19user's specified ProxyCommand.
20
21To allow configurations that use strange user or hostnames to
22continue to work, this strictness is applied only to names coming
23from the commandline. Names specified using User or Hostname
24directives in ssh_config(5) are not affected.
25
26feedback/ok millert@ markus@ dtucker@ deraadt@
27
28OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9
29
30CVE: CVE-2023-51385
31Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/7ef3787c84b6b524501211b11a26c742f829af1a]
32Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
33Comment: Hunks refreshed to apply cleanly
34
35---
36 ssh.c | 41 ++++++++++++++++++++++++++++++++++++++++-
37 1 file changed, 40 insertions(+), 1 deletion(-)
38
39diff --git a/ssh.c b/ssh.c
40index 35c48e62d18..48d93ddf2a9 100644
41--- a/ssh.c
42+++ b/ssh.c
43@@ -583,6 +583,41 @@ set_addrinfo_port(struct addrinfo *addrs
44 }
45 }
46
47+static int
48+valid_hostname(const char *s)
49+{
50+ size_t i;
51+
52+ if (*s == '-')
53+ return 0;
54+ for (i = 0; s[i] != 0; i++) {
55+ if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL ||
56+ isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
57+ return 0;
58+ }
59+ return 1;
60+}
61+
62+static int
63+valid_ruser(const char *s)
64+{
65+ size_t i;
66+
67+ if (*s == '-')
68+ return 0;
69+ for (i = 0; s[i] != 0; i++) {
70+ if (strchr("'`\";&<>|(){}", s[i]) != NULL)
71+ return 0;
72+ /* Disallow '-' after whitespace */
73+ if (isspace((u_char)s[i]) && s[i + 1] == '-')
74+ return 0;
75+ /* Disallow \ in last position */
76+ if (s[i] == '\\' && s[i + 1] == '\0')
77+ return 0;
78+ }
79+ return 1;
80+}
81+
82 /*
83 * Main program for the ssh client.
84 */
85@@ -1069,6 +1104,10 @@ main(int ac, char **av)
86 if (!host)
87 usage();
88
89+ if (!valid_hostname(host))
90+ fatal("hostname contains invalid characters");
91+ if (options.user != NULL && !valid_ruser(options.user))
92+ fatal("remote username contains invalid characters");
93 host_arg = xstrdup(host);
94
95 /* Initialize the command to execute on remote host. */
diff --git a/meta/recipes-connectivity/openssh/openssh/sshd.socket b/meta/recipes-connectivity/openssh/openssh/sshd.socket
index 12c39b26b5..8d76d62309 100644
--- a/meta/recipes-connectivity/openssh/openssh/sshd.socket
+++ b/meta/recipes-connectivity/openssh/openssh/sshd.socket
@@ -1,5 +1,6 @@
1[Unit] 1[Unit]
2Conflicts=sshd.service 2Conflicts=sshd.service
3Wants=sshdgenkeys.service
3 4
4[Socket] 5[Socket]
5ExecStartPre=@BASE_BINDIR@/mkdir -p /var/run/sshd 6ExecStartPre=@BASE_BINDIR@/mkdir -p /var/run/sshd
diff --git a/meta/recipes-connectivity/openssh/openssh/sshd@.service b/meta/recipes-connectivity/openssh/openssh/sshd@.service
index 9d83dfb2bb..422450c7a1 100644
--- a/meta/recipes-connectivity/openssh/openssh/sshd@.service
+++ b/meta/recipes-connectivity/openssh/openssh/sshd@.service
@@ -1,13 +1,11 @@
1[Unit] 1[Unit]
2Description=OpenSSH Per-Connection Daemon 2Description=OpenSSH Per-Connection Daemon
3Wants=sshdgenkeys.service
4After=sshdgenkeys.service 3After=sshdgenkeys.service
5 4
6[Service] 5[Service]
7Environment="SSHD_OPTS=" 6Environment="SSHD_OPTS="
8EnvironmentFile=-/etc/default/ssh 7EnvironmentFile=-/etc/default/ssh
9ExecStart=-@SBINDIR@/sshd -i $SSHD_OPTS 8ExecStart=-@SBINDIR@/sshd -i $SSHD_OPTS
10ExecReload=@BASE_BINDIR@/kill -HUP $MAINPID
11StandardInput=socket 9StandardInput=socket
12StandardError=syslog 10StandardError=syslog
13KillMode=process 11KillMode=process