summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornikhil <nikhilar2410@gmail.com>2024-05-07 17:45:09 +0530
committerArmin Kuster <akuster808@gmail.com>2024-05-26 15:22:08 -0400
commit31d0f02673018a0d0a2555be181aaceb5db63da2 (patch)
tree9fb4b1df441c48d48ff6fc6b7e4fd98f9ee7ad83
parent9c9224811bef48b95711f9367ab59897db119e29 (diff)
downloadmeta-openembedded-31d0f02673018a0d0a2555be181aaceb5db63da2.tar.gz
libssh: Fix CVE CVE-2023-6004
A flaw was found in libssh. By utilizing the ProxyCommand or ProxyJump feature, users can exploit unchecked hostname syntax on the client. This issue may allow an attacker to inject malicious code into the command of the features mentioned through the hostname parameter Signed-off-by: Nikhil R <nikhil.r@kpit.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-support/libssh/libssh/0001-config-Move-common-parser-functions-to-config_parser.patch464
-rw-r--r--meta-oe/recipes-support/libssh/libssh/001_CVE-2023-6004.patch30
-rw-r--r--meta-oe/recipes-support/libssh/libssh/002_CVE-2023-6004.patch83
-rw-r--r--meta-oe/recipes-support/libssh/libssh/003_CVE-2023-6004.patch117
-rw-r--r--meta-oe/recipes-support/libssh/libssh/004_CVE-2023-6004.patch57
-rw-r--r--meta-oe/recipes-support/libssh/libssh/005_CVE-2023-6004.patch142
-rw-r--r--meta-oe/recipes-support/libssh/libssh/006_CVE-2023-6004.patch117
-rw-r--r--meta-oe/recipes-support/libssh/libssh_0.8.9.bb7
8 files changed, 1017 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/libssh/libssh/0001-config-Move-common-parser-functions-to-config_parser.patch b/meta-oe/recipes-support/libssh/libssh/0001-config-Move-common-parser-functions-to-config_parser.patch
new file mode 100644
index 0000000000..f26b644102
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/0001-config-Move-common-parser-functions-to-config_parser.patch
@@ -0,0 +1,464 @@
1From 79049981a513f9a10fac0f153e9b0b588326021f Mon Sep 17 00:00:00 2001
2From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
3Date: Fri, 22 Feb 2019 13:06:49 +0100
4Subject: [PATCH] config: Move common parser functions to config_parser.c
5
6This will allow the moved functions to be used in the server side
7configuration parser implementation.
8
9Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
10Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
11
12CVE:CVE-2023-6004
13Upstream-Status: Backport [https://git.libssh.org/projects/libssh.git/commit/?id=79049981a513f9a10fac0f153e9b0b588326021f]
14Signed-off-by: nikhil r <nikhil.r@kpit.com>
15Comment: Removed 1 hunk from config.c as the function was intoduced in
16later version
17
18---
19 include/libssh/config_parser.h | 57 ++++++++
20 src/CMakeLists.txt | 1 +
21 src/config.c | 216 +-----------------------------
22 src/config_parser.c | 238 +++++++++++++++++++++++++++++++++
23 4 files changed, 297 insertions(+), 215 deletions(-)
24 create mode 100644 include/libssh/config_parser.h
25 create mode 100644 src/config_parser.c
26
27diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h
28new file mode 100644
29index 00000000..e974917c
30--- /dev/null
31+++ b/include/libssh/config_parser.h
32@@ -0,0 +1,57 @@
33+/*
34+ * config_parser.h - Common configuration file parser functions
35+ *
36+ * This file is part of the SSH Library
37+ *
38+ * Copyright (c) 2019 by Red Hat, Inc.
39+ *
40+ * Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
41+ *
42+ * The SSH Library is free software; you can redistribute it and/or modify
43+ * it under the terms of the GNU Lesser General Public License as published by
44+ * the Free Software Foundation; either version 2.1 of the License, or (at your
45+ * option) any later version.
46+ *
47+ * The SSH Library is distributed in the hope that it will be useful, but
48+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
49+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
50+ * License for more details.
51+ *
52+ * You should have received a copy of the GNU Lesser General Public License
53+ * along with the SSH Library; see the file COPYING. If not, write to
54+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
55+ * MA 02111-1307, USA.
56+ */
57+
58+#ifndef CONFIG_PARSER_H_
59+#define CONFIG_PARSER_H_
60+
61+char *ssh_config_get_cmd(char **str);
62+
63+char *ssh_config_get_token(char **str);
64+
65+long ssh_config_get_long(char **str, long notfound);
66+
67+const char *ssh_config_get_str_tok(char **str, const char *def);
68+
69+int ssh_config_get_yesno(char **str, int notfound);
70+
71+/* @brief Parse SSH URI in format [user@]host[:port] from the given string
72+ *
73+ * @param[in] tok String to parse
74+ * @param[out] username Pointer to the location, where the new username will
75+ * be stored or NULL if we do not care about the result.
76+ * @param[out] hostname Pointer to the location, where the new hostname will
77+ * be stored or NULL if we do not care about the result.
78+ * @param[out] port Pointer to the location, where the new port will
79+ * be stored or NULL if we do not care about the result.
80+ *
81+ * @returns SSH_OK if the provided string is in format of SSH URI,
82+ * SSH_ERROR on failure
83+ */
84+int ssh_config_parse_uri(const char *tok,
85+ char **username,
86+ char **hostname,
87+ char **port);
88+
89+#endif /* LIBSSH_CONFIG_H_ */
90diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
91index fdb53baf..de66f056 100644
92--- a/src/CMakeLists.txt
93+++ b/src/CMakeLists.txt
94@@ -163,6 +163,7 @@ set(libssh_SRCS
95 external/poly1305.c
96 external/sc25519.c
97 chachapoly.c
98+ config_parser.c
99 )
100
101 if (CMAKE_USE_PTHREADS_INIT)
102diff --git a/src/config.c b/src/config.c
103index 85ecd96a..4268545d 100644
104--- a/src/config.c
105+++ b/src/config.c
106@@ -22,7 +22,7 @@
107 */
108
109 #include "config.h"
110-
111+#include "libssh/config_parser.h"
112 #include <ctype.h>
113 #include <stdio.h>
114 #include <string.h>
115@@ -228,102 +228,6 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
116 return SOC_UNKNOWN;
117 }
118
119-static char *ssh_config_get_cmd(char **str) {
120- register char *c;
121- char *r;
122-
123- /* Ignore leading spaces */
124- for (c = *str; *c; c++) {
125- if (! isblank(*c)) {
126- break;
127- }
128- }
129-
130- if (*c == '\"') {
131- for (r = ++c; *c; c++) {
132- if (*c == '\"') {
133- *c = '\0';
134- goto out;
135- }
136- }
137- }
138-
139- for (r = c; *c; c++) {
140- if (*c == '\n') {
141- *c = '\0';
142- goto out;
143- }
144- }
145-
146-out:
147- *str = c + 1;
148-
149- return r;
150-}
151-
152-static char *ssh_config_get_token(char **str) {
153- register char *c;
154- char *r;
155-
156- c = ssh_config_get_cmd(str);
157-
158- for (r = c; *c; c++) {
159- if (isblank(*c) || *c == '=') {
160- *c = '\0';
161- goto out;
162- }
163- }
164-
165-out:
166- *str = c + 1;
167-
168- return r;
169-}
170-
171-static long ssh_config_get_long(char **str, long notfound) {
172- char *p, *endp;
173- long i;
174-
175- p = ssh_config_get_token(str);
176- if (p && *p) {
177- i = strtol(p, &endp, 10);
178- if (p == endp) {
179- return notfound;
180- }
181- return i;
182- }
183-
184- return notfound;
185-}
186-
187-static const char *ssh_config_get_str_tok(char **str, const char *def) {
188- char *p;
189-
190- p = ssh_config_get_token(str);
191- if (p && *p) {
192- return p;
193- }
194-
195- return def;
196-}
197-
198-static int ssh_config_get_yesno(char **str, int notfound) {
199- const char *p;
200-
201- p = ssh_config_get_str_tok(str, NULL);
202- if (p == NULL) {
203- return notfound;
204- }
205-
206- if (strncasecmp(p, "yes", 3) == 0) {
207- return 1;
208- } else if (strncasecmp(p, "no", 2) == 0) {
209- return 0;
210- }
211-
212- return notfound;
213-}
214-
215 static void local_parse_file(ssh_session session, const char *filename, int *parsing, int seen[]) {
216 FILE *f;
217 char line[MAX_LINE_SIZE] = {0};
218diff --git a/src/config_parser.c b/src/config_parser.c
219new file mode 100644
220index 00000000..ae2aa2c8
221--- /dev/null
222+++ b/src/config_parser.c
223@@ -0,0 +1,238 @@
224+/*
225+ * config_parser.c - Common configuration file parser functions
226+ *
227+ * This file is part of the SSH Library
228+ *
229+ * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
230+ *
231+ * The SSH Library is free software; you can redistribute it and/or modify
232+ * it under the terms of the GNU Lesser General Public License as published by
233+ * the Free Software Foundation; either version 2.1 of the License, or (at your
234+ * option) any later version.
235+ *
236+ * The SSH Library is distributed in the hope that it will be useful, but
237+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
238+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
239+ * License for more details.
240+ *
241+ * You should have received a copy of the GNU Lesser General Public License
242+ * along with the SSH Library; see the file COPYING. If not, write to
243+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
244+ * MA 02111-1307, USA.
245+ */
246+
247+#include "config.h"
248+
249+#include <ctype.h>
250+#include <stdio.h>
251+#include <string.h>
252+#include <stdlib.h>
253+
254+#include "libssh/config_parser.h"
255+#include "libssh/priv.h"
256+
257+char *ssh_config_get_cmd(char **str)
258+{
259+ register char *c;
260+ char *r;
261+
262+ /* Ignore leading spaces */
263+ for (c = *str; *c; c++) {
264+ if (! isblank(*c)) {
265+ break;
266+ }
267+ }
268+
269+ if (*c == '\"') {
270+ for (r = ++c; *c; c++) {
271+ if (*c == '\"') {
272+ *c = '\0';
273+ goto out;
274+ }
275+ }
276+ }
277+
278+ for (r = c; *c; c++) {
279+ if (*c == '\n') {
280+ *c = '\0';
281+ goto out;
282+ }
283+ }
284+
285+out:
286+ *str = c + 1;
287+
288+ return r;
289+}
290+
291+char *ssh_config_get_token(char **str)
292+{
293+ register char *c;
294+ char *r;
295+
296+ c = ssh_config_get_cmd(str);
297+
298+ for (r = c; *c; c++) {
299+ if (isblank(*c) || *c == '=') {
300+ *c = '\0';
301+ goto out;
302+ }
303+ }
304+
305+out:
306+ *str = c + 1;
307+
308+ return r;
309+}
310+
311+long ssh_config_get_long(char **str, long notfound)
312+{
313+ char *p, *endp;
314+ long i;
315+
316+ p = ssh_config_get_token(str);
317+ if (p && *p) {
318+ i = strtol(p, &endp, 10);
319+ if (p == endp) {
320+ return notfound;
321+ }
322+ return i;
323+ }
324+
325+ return notfound;
326+}
327+
328+const char *ssh_config_get_str_tok(char **str, const char *def)
329+{
330+ char *p;
331+
332+ p = ssh_config_get_token(str);
333+ if (p && *p) {
334+ return p;
335+ }
336+
337+ return def;
338+}
339+
340+int ssh_config_get_yesno(char **str, int notfound)
341+{
342+ const char *p;
343+
344+ p = ssh_config_get_str_tok(str, NULL);
345+ if (p == NULL) {
346+ return notfound;
347+ }
348+
349+ if (strncasecmp(p, "yes", 3) == 0) {
350+ return 1;
351+ } else if (strncasecmp(p, "no", 2) == 0) {
352+ return 0;
353+ }
354+
355+ return notfound;
356+}
357+
358+int ssh_config_parse_uri(const char *tok,
359+ char **username,
360+ char **hostname,
361+ char **port)
362+{
363+ char *endp = NULL;
364+ long port_n;
365+
366+ /* Sanitize inputs */
367+ if (username != NULL) {
368+ *username = NULL;
369+ }
370+ if (hostname != NULL) {
371+ *hostname = NULL;
372+ }
373+ if (port != NULL) {
374+ *port = NULL;
375+ }
376+
377+ /* Username part (optional) */
378+ endp = strchr(tok, '@');
379+ if (endp != NULL) {
380+ /* Zero-length username is not valid */
381+ if (tok == endp) {
382+ goto error;
383+ }
384+ if (username != NULL) {
385+ *username = strndup(tok, endp - tok);
386+ if (*username == NULL) {
387+ goto error;
388+ }
389+ }
390+ tok = endp + 1;
391+ /* If there is second @ character, this does not look like our URI */
392+ endp = strchr(tok, '@');
393+ if (endp != NULL) {
394+ goto error;
395+ }
396+ }
397+
398+ /* Hostname */
399+ if (*tok == '[') {
400+ /* IPv6 address is enclosed with square brackets */
401+ tok++;
402+ endp = strchr(tok, ']');
403+ if (endp == NULL) {
404+ goto error;
405+ }
406+ } else {
407+ /* Hostnames or aliases expand to the last colon or to the end */
408+ endp = strrchr(tok, ':');
409+ if (endp == NULL) {
410+ endp = strchr(tok, '\0');
411+ }
412+ }
413+ if (tok == endp) {
414+ /* Zero-length hostnames are not valid */
415+ goto error;
416+ }
417+ if (hostname != NULL) {
418+ *hostname = strndup(tok, endp - tok);
419+ if (*hostname == NULL) {
420+ goto error;
421+ }
422+ }
423+ /* Skip also the closing bracket */
424+ if (*endp == ']') {
425+ endp++;
426+ }
427+
428+ /* Port (optional) */
429+ if (*endp != '\0') {
430+ char *port_end = NULL;
431+
432+ /* Verify the port is valid positive number */
433+ port_n = strtol(endp + 1, &port_end, 10);
434+ if (port_n < 1 || *port_end != '\0') {
435+ SSH_LOG(SSH_LOG_WARN, "Failed to parse port number."
436+ " The value '%ld' is invalid or there are some"
437+ " trailing characters: '%s'", port_n, port_end);
438+ goto error;
439+ }
440+ if (port != NULL) {
441+ *port = strdup(endp + 1);
442+ if (*port == NULL) {
443+ goto error;
444+ }
445+ }
446+ }
447+
448+ return SSH_OK;
449+
450+error:
451+ if (username != NULL) {
452+ SAFE_FREE(*username);
453+ }
454+ if (hostname != NULL) {
455+ SAFE_FREE(*hostname);
456+ }
457+ if (port != NULL) {
458+ SAFE_FREE(*port);
459+ }
460+ return SSH_ERROR;
461+}
462--
4632.25.1
464
diff --git a/meta-oe/recipes-support/libssh/libssh/001_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/001_CVE-2023-6004.patch
new file mode 100644
index 0000000000..e02cae182a
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/001_CVE-2023-6004.patch
@@ -0,0 +1,30 @@
1From a66b4a6eae6614d200a3625862d77565b96a7cd3 Mon Sep 17 00:00:00 2001
2From: Norbert Pocs <norbertpocs0@gmail.com>
3Date: Wed, 1 Nov 2023 11:24:43 +0100
4Subject: [PATCH] CVE-2023-6004: config_parser: Allow multiple '@' in usernames
5
6Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
7Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
8Reviewed-by: Jakub Jelen <jjelen@redhat.com>
9
10CVE: CVE-2023-6004
11Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/a66b4a6eae6614d200a3625862d77565b96a7cd3]
12Signed-off-by: nikhil r <nikhil.r@kpit.com>
13
14---
15 src/config_parser.c | 2 +-
16 1 file changed, 1 insertion(+), 1 deletion(-)
17
18diff --git a/src/config_parser.c b/src/config_parser.c
19index 0d988fec0..cf83e2c5e 100644
20--- a/src/config_parser.c
21+++ b/src/config_parser.c
22@@ -180,7 +180,7 @@ int ssh_config_parse_uri(const char *tok,
23 }
24
25 /* Username part (optional) */
26- endp = strchr(tok, '@');
27+ endp = strrchr(tok, '@');
28 if (endp != NULL) {
29 /* Zero-length username is not valid */
30 if (tok == endp) {
diff --git a/meta-oe/recipes-support/libssh/libssh/002_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/002_CVE-2023-6004.patch
new file mode 100644
index 0000000000..a77783453a
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/002_CVE-2023-6004.patch
@@ -0,0 +1,83 @@
1From 8615c24647f773a5e04203c7459512715d698be1 Mon Sep 17 00:00:00 2001
2From: Norbert Pocs <norbertpocs0@gmail.com>
3Date: Tue, 31 Oct 2023 09:48:52 +0100
4Subject: [PATCH] CVE-2023-6004: options: Simplify the hostname parsing in
5 ssh_options_set
6
7Using ssh_config_parse_uri can simplify the parsing of the host
8parsing inside the function of ssh_options_set
9
10Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
11Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
12Reviewed-by: Jakub Jelen <jjelen@redhat.com>
13
14CVE: CVE-2023-6004
15Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/8615c24647f773a5e04203c7459512715d698be1]
16Signed-off-by: nikhil r <nikhil.r@kpit.com>
17Comment: Refreshed hunk 2 from option.c
18
19---
20 src/options.c | 40 ++++++++++++++++------------------------
21 1 file changed, 16 insertions(+), 24 deletions(-)
22
23diff --git a/src/options.c b/src/options.c
24index 6f2c9397e..385114555 100644
25--- a/src/options.c
26+++ b/src/options.c
27@@ -36,6 +36,7 @@
28 #include "libssh/session.h"
29 #include "libssh/misc.h"
30 #include "libssh/options.h"
31+#include "libssh/config_parser.h"
32 #ifdef WITH_SERVER
33 #include "libssh/server.h"
34 #include "libssh/bind.h"
35@@ -415,33 +416,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
36 ssh_set_error_invalid(session);
37 return -1;
38 } else {
39- q = strdup(value);
40- if (q == NULL) {
41- ssh_set_error_oom(session);
42+ char *username = NULL, *hostname = NULL, *port = NULL;
43+ rc = ssh_config_parse_uri(value, &username, &hostname, &port);
44+ if (rc != SSH_OK) {
45 return -1;
46 }
47- p = strchr(q, '@');
48-
49- SAFE_FREE(session->opts.host);
50-
51- if (p) {
52- *p = '\0';
53- session->opts.host = strdup(p + 1);
54- if (session->opts.host == NULL) {
55- SAFE_FREE(q);
56- ssh_set_error_oom(session);
57- return -1;
58- }
59-
60+ if (port != NULL) {
61+ SAFE_FREE(username);
62+ SAFE_FREE(hostname);
63+ SAFE_FREE(port);
64+ return -1;
65+ }
66+ if (username != NULL) {
67 SAFE_FREE(session->opts.username);
68- session->opts.username = strdup(q);
69- SAFE_FREE(q);
70- if (session->opts.username == NULL) {
71- ssh_set_error_oom(session);
72- return -1;
73- }
74- } else {
75- session->opts.host = q;
76+ session->opts.username = username;
77+ }
78+ if (hostname != NULL) {
79+ SAFE_FREE(session->opts.host);
80+ session->opts.host = hostname;
81 }
82 }
83 break;
diff --git a/meta-oe/recipes-support/libssh/libssh/003_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/003_CVE-2023-6004.patch
new file mode 100644
index 0000000000..a4e790ed0c
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/003_CVE-2023-6004.patch
@@ -0,0 +1,117 @@
1From c6180409677c765e6b9ae2b18a3a7a9671ac1dbe Mon Sep 17 00:00:00 2001
2From: Norbert Pocs <norbertpocs0@gmail.com>
3Date: Tue, 10 Oct 2023 12:44:16 +0200
4Subject: [PATCH] CVE-2023-6004: misc: Add function to check allowed characters
5 of a hostname
6
7The hostname can be a domain name or an ip address. The colon has to be
8allowed because of IPv6 even it is prohibited in domain names.
9
10Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
11Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
12Reviewed-by: Jakub Jelen <jjelen@redhat.com>
13
14CVE: CVE-2023-6004
15Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/c6180409677c765e6b9ae2b18a3a7a9671ac1dbe]
16Signed-off-by: nikhil r <nikhil.r@kpit.com>
17Comment: Refreshed hunk 1 from misc.h and hunk 2 from misc.c
18---
19 include/libssh/misc.h | 3 ++
20 src/misc.c | 68 +++++++++++++++++++++++++++++++++++++++++++
21 2 files changed, 71 insertions(+)
22
23diff --git a/include/libssh/misc.h b/include/libssh/misc.h
24index 924da5336..0924ba7fb 100644
25--- a/include/libssh/misc.h
26+++ b/include/libssh/misc.h
27@@ -89,4 +89,6 @@ int ssh_match_group(const char *group, const char *object);
28
29 int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
30
31+int ssh_check_hostname_syntax(const char *hostname);
32+
33 #endif /* MISC_H_ */
34
35diff --git a/src/misc.c b/src/misc.c
36index 7c478a773..be6ee836e 100644
37--- a/src/misc.c
38+++ b/src/misc.c
39@@ -94,6 +94,8 @@
40 #define ZLIB_STRING ""
41 #endif
42
43+#define ARPA_DOMAIN_MAX_LEN 63
44+
45 /**
46 * @defgroup libssh_misc The SSH helper functions.
47 * @ingroup libssh
48@@ -1292,4 +1294,69 @@ error:
49 return SSH_ERROR;
50 }
51
52+/**
53+ * @brief Checks syntax of a domain name
54+ *
55+ * The check is made based on the RFC1035 section 2.3.1
56+ * Allowed characters are: hyphen, period, digits (0-9) and letters (a-zA-Z)
57+ *
58+ * The label should be no longer than 63 characters
59+ * The label should start with a letter and end with a letter or number
60+ * The label in this implementation can start with a number to allow virtual
61+ * URLs to pass. Note that this will make IPv4 addresses to pass
62+ * this check too.
63+ *
64+ * @param hostname The domain name to be checked, has to be null terminated
65+ *
66+ * @return SSH_OK if the hostname passes syntax check
67+ * SSH_ERROR otherwise or if hostname is NULL or empty string
68+ */
69+int ssh_check_hostname_syntax(const char *hostname)
70+{
71+ char *it = NULL, *s = NULL, *buf = NULL;
72+ size_t it_len;
73+ char c;
74+
75+ if (hostname == NULL || strlen(hostname) == 0) {
76+ return SSH_ERROR;
77+ }
78+
79+ /* strtok_r writes into the string, keep the input clean */
80+ s = strdup(hostname);
81+ if (s == NULL) {
82+ return SSH_ERROR;
83+ }
84+
85+ it = strtok_r(s, ".", &buf);
86+ /* if the token has 0 length */
87+ if (it == NULL) {
88+ free(s);
89+ return SSH_ERROR;
90+ }
91+ do {
92+ it_len = strlen(it);
93+ if (it_len > ARPA_DOMAIN_MAX_LEN ||
94+ /* the first char must be a letter, but some virtual urls start
95+ * with a number */
96+ isalnum(it[0]) == 0 ||
97+ isalnum(it[it_len - 1]) == 0) {
98+ free(s);
99+ return SSH_ERROR;
100+ }
101+ while (*it != '\0') {
102+ c = *it;
103+ /* the "." is allowed too, but tokenization removes it from the
104+ * string */
105+ if (isalnum(c) == 0 && c != '-') {
106+ free(s);
107+ return SSH_ERROR;
108+ }
109+ it++;
110+ }
111+ } while ((it = strtok_r(NULL, ".", &buf)) != NULL);
112+
113+ free(s);
114+
115+ return SSH_OK;
116+}
117 /** @} */
diff --git a/meta-oe/recipes-support/libssh/libssh/004_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/004_CVE-2023-6004.patch
new file mode 100644
index 0000000000..39e6d94788
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/004_CVE-2023-6004.patch
@@ -0,0 +1,57 @@
1From 22492b69bba22b102342afc574800d354a08e405 Mon Sep 17 00:00:00 2001
2From: Norbert Pocs <norbertpocs0@gmail.com>
3Date: Tue, 10 Oct 2023 18:33:56 +0200
4Subject: [PATCH] CVE-2023-6004: config_parser: Check for valid syntax of a
5 hostname if it is a domain name
6
7This prevents code injection.
8The domain name syntax checker is based on RFC1035.
9
10Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
11Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
12Reviewed-by: Jakub Jelen <jjelen@redhat.com>
13
14CVE: CVE-2023-6004
15Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/22492b69bba22b102342afc574800d354a08e405]
16Signed-off-by: nikhil r <nikhil.r@kpit.com>
17Comment: Refreshed hunk 2 and 3 from config_parser.c
18
19---
20 src/config_parser.c | 12 +++++++++++-
21 1 file changed, 11 insertions(+), 1 deletion(-)
22
23diff --git a/src/config_parser.c b/src/config_parser.c
24index cf83e2c5e..b8b94611a 100644
25--- a/src/config_parser.c
26+++ b/src/config_parser.c
27@@ -30,6 +30,7 @@
28
29 #include "libssh/config_parser.h"
30 #include "libssh/priv.h"
31+#include "libssh/misc.h"
32
33 char *ssh_config_get_cmd(char **str)
34 {
35@@ -139,6 +140,7 @@ int ssh_config_parse_uri(const char *tok,
36 {
37 char *endp = NULL;
38 long port_n;
39+ int rc;
40
41 /* Sanitize inputs */
42 if (username != NULL) {
43@@ -196,6 +198,14 @@ int ssh_config_parse_uri(const char *tok,
44 if (*hostname == NULL) {
45 goto error;
46 }
47+ /* if not an ip, check syntax */
48+ rc = ssh_is_ipaddr(*hostname);
49+ if (rc == 0) {
50+ rc = ssh_check_hostname_syntax(*hostname);
51+ if (rc != SSH_OK) {
52+ goto error;
53+ }
54+ }
55 }
56 /* Skip also the closing bracket */
57 if (*endp == ']') {
diff --git a/meta-oe/recipes-support/libssh/libssh/005_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/005_CVE-2023-6004.patch
new file mode 100644
index 0000000000..c86aba4d88
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/005_CVE-2023-6004.patch
@@ -0,0 +1,142 @@
1From cea841d71c025f9c998b7d5fc9f2a2839df62921 Mon Sep 17 00:00:00 2001
2From: Norbert Pocs <norbertpocs0@gmail.com>
3Date: Tue, 28 Nov 2023 15:26:45 +0100
4Subject: [PATCH] CVE-2023-6004 misc: Add ipv6 link-local check for an ip
5 address
6
7Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
8Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
9Reviewed-by: Jakub Jelen <jjelen@redhat.com>
10
11CVE: CVE-2023-6004
12Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/cea841d71c025f9c998b7d5fc9f2a2839df62921]
13Signed-off-by: nikhil r <nikhil.r@kpit.com>
14Comment: Refreshed hunk 1 from CMakeLists.txt, hunk 1 from connect.c and
15hunks 2,3,4 from misc.c
16---
17 src/CMakeLists.txt | 1 +
18 src/connect.c | 2 +-
19 src/misc.c | 44 ++++++++++++++++++++++++++++++++++++++------
20 3 files changed, 40 insertions(+), 7 deletions(-)
21
22diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
23index d6245c0db..807313b59 100644
24--- a/src/CMakeLists.txt
25+++ b/src/CMakeLists.txt
26@@ -14,6 +14,7 @@ set(LIBSSH_LINK_LIBRARIES
27 if (WIN32)
28 set(LIBSSH_LINK_LIBRARIES
29 ${LIBSSH_LINK_LIBRARIES}
30+ iphlpapi
31 ws2_32
32 )
33 endif (WIN32)
34diff --git a/src/connect.c b/src/connect.c
35index 57e37e634..15cae6444 100644
36--- a/src/connect.c
37+++ b/src/connect.c
38@@ -130,7 +130,7 @@ static int getai(const char *host, int port, struct addrinfo **ai) {
39 #endif
40 }
41
42- if (ssh_is_ipaddr(host)) {
43+ if (ssh_is_ipaddr(host) == 1) {
44 /* this is an IP address */
45 SSH_LOG(SSH_LOG_PACKET,"host %s matches an IP address",host);
46 hints.ai_flags |= AI_NUMERICHOST;
47diff --git a/src/misc.c b/src/misc.c
48index be6ee836e..7081f12ae 100644
49--- a/src/misc.c
50+++ b/src/misc.c
51@@ -32,6 +32,7 @@
52 #include <sys/socket.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55+#include <net/if.h>
56
57 #endif /* _WIN32 */
58
59@@ -59,6 +60,7 @@
60 #include <ws2tcpip.h>
61 #include <shlobj.h>
62 #include <direct.h>
63+#include <netioapi.h>
64
65 #ifdef HAVE_IO_H
66 #include <io.h>
67@@ -191,22 +191,37 @@ int ssh_is_ipaddr_v4(const char *str) {
68
69 int ssh_is_ipaddr(const char *str) {
70 int rc = SOCKET_ERROR;
71+ char *s = strdup(str);
72
73- if (strchr(str, ':')) {
74+ if (s == NULL) {
75+ return -1;
76+ }
77+ if (strchr(s, ':')) {
78 struct sockaddr_storage ss;
79 int sslen = sizeof(ss);
80+ char *network_interface = strchr(s, '%');
81
82- /* TODO link-local (IP:v6:addr%ifname). */
83- rc = WSAStringToAddressA((LPSTR) str,
84+ /* link-local (IP:v6:addr%ifname). */
85+ if (network_interface != NULL) {
86+ rc = if_nametoindex(network_interface + 1);
87+ if (rc == 0) {
88+ free(s);
89+ return 0;
90+ }
91+ *network_interface = '\0';
92+ }
93+ rc = WSAStringToAddressA((LPSTR) s,
94 AF_INET6,
95 NULL,
96 (struct sockaddr*)&ss,
97 &sslen);
98 if (rc == 0) {
99+ free(s);
100 return 1;
101 }
102 }
103
104+ free(s);
105 return ssh_is_ipaddr_v4(str);
106 }
107 #else /* _WIN32 */
108@@ -285,17 +300,32 @@ int ssh_is_ipaddr_v4(const char *str) {
109
110 int ssh_is_ipaddr(const char *str) {
111 int rc = -1;
112+ char *s = strdup(str);
113
114- if (strchr(str, ':')) {
115+ if (s == NULL) {
116+ return -1;
117+ }
118+ if (strchr(s, ':')) {
119 struct in6_addr dest6;
120+ char *network_interface = strchr(s, '%');
121
122- /* TODO link-local (IP:v6:addr%ifname). */
123- rc = inet_pton(AF_INET6, str, &dest6);
124+ /* link-local (IP:v6:addr%ifname). */
125+ if (network_interface != NULL) {
126+ rc = if_nametoindex(network_interface + 1);
127+ if (rc == 0) {
128+ free(s);
129+ return 0;
130+ }
131+ *network_interface = '\0';
132+ }
133+ rc = inet_pton(AF_INET6, s, &dest6);
134 if (rc > 0) {
135+ free(s);
136 return 1;
137 }
138 }
139
140+ free(s);
141 return ssh_is_ipaddr_v4(str);
142 }
diff --git a/meta-oe/recipes-support/libssh/libssh/006_CVE-2023-6004.patch b/meta-oe/recipes-support/libssh/libssh/006_CVE-2023-6004.patch
new file mode 100644
index 0000000000..f3cb2b998e
--- /dev/null
+++ b/meta-oe/recipes-support/libssh/libssh/006_CVE-2023-6004.patch
@@ -0,0 +1,117 @@
1From 1a02364b5107a4125ea3cb76fcdb6beabaebf3be Mon Sep 17 00:00:00 2001
2From: Jakub Jelen <jjelen@redhat.com>
3Date: Fri, 22 Dec 2023 10:32:40 +0100
4Subject: [PATCH] Fix regression in IPv6 addresses in hostname parsing
5
6Signed-off-by: Jakub Jelen <jjelen@redhat.com>
7Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
8(cherry picked from commit 4f997aee7c7d7ea346b3e8ba505da0b7601ff318)
9
10CVE: CVE-2023-6004
11Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/1a02364b5107a4125ea3cb76fcdb6beabaebf3be]
12Signed-off-by: nikhil r <nikhil.r@kpit.com>
13Comment: Removed 1 hunk from config_parser.c as the function was intoduced in
14later version
15
16---
17 include/libssh/config_parser.h | 11 ++++++++---
18 src/config.c | 4 ++--
19 src/config_parser.c | 16 +++++++++++-----
20 src/options.c | 10 ++--------
21 4 files changed, 23 insertions(+), 18 deletions(-)
22
23diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h
24index a7dd42a2c..ca353432b 100644
25--- a/include/libssh/config_parser.h
26+++ b/include/libssh/config_parser.h
27@@ -26,6 +26,8 @@
28 #ifndef CONFIG_PARSER_H_
29 #define CONFIG_PARSER_H_
30
31+#include <stdbool.h>
32+
33 char *ssh_config_get_cmd(char **str);
34
35 char *ssh_config_get_token(char **str);
36@@ -45,13 +47,16 @@ int ssh_config_get_yesno(char **str, int notfound);
37 * be stored or NULL if we do not care about the result.
38 * @param[out] port Pointer to the location, where the new port will
39 * be stored or NULL if we do not care about the result.
40+ * @param[in] ignore_port Set to true if the we should not attempt to parse
41+ * port number.
42 *
43 * @returns SSH_OK if the provided string is in format of SSH URI,
44 * SSH_ERROR on failure
45 */
46 int ssh_config_parse_uri(const char *tok,
47- char **username,
48- char **hostname,
49- char **port);
50+ char **username,
51+ char **hostname,
52+ char **port,
53+ bool ignore_port);
54
55 #endif /* LIBSSH_CONFIG_H_ */
56diff --git a/src/config_parser.c b/src/config_parser.c
57index b8b94611a..d4b2d2c3b 100644
58--- a/src/config_parser.c
59+++ b/src/config_parser.c
60@@ -162,9 +162,10 @@ int ssh_config_get_yesno(char **str, int notfound)
61 }
62
63 int ssh_config_parse_uri(const char *tok,
64- char **username,
65- char **hostname,
66- char **port)
67+ char **username,
68+ char **hostname,
69+ char **port,
70+ bool ignore_port)
71 {
72 char *endp = NULL;
73 long port_n;
74@@ -210,12 +211,17 @@ int ssh_config_parse_uri(const char *tok,
75 if (endp == NULL) {
76 goto error;
77 }
78- } else {
79- /* Hostnames or aliases expand to the last colon or to the end */
80+ } else if (!ignore_port) {
81+ /* Hostnames or aliases expand to the last colon (if port is requested)
82+ * or to the end */
83 endp = strrchr(tok, ':');
84 if (endp == NULL) {
85 endp = strchr(tok, '\0');
86 }
87+ } else {
88+ /* If no port is requested, expand to the end of line
89+ * (to accommodate the IPv6 addresses) */
90+ endp = strchr(tok, '\0');
91 }
92 if (tok == endp) {
93 /* Zero-length hostnames are not valid */
94diff --git a/src/options.c b/src/options.c
95index 385114555..b3ecffe15 100644
96--- a/src/options.c
97+++ b/src/options.c
98@@ -416,17 +416,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
99 ssh_set_error_invalid(session);
100 return -1;
101 } else {
102- char *username = NULL, *hostname = NULL, *port = NULL;
103- rc = ssh_config_parse_uri(value, &username, &hostname, &port);
104+ char *username = NULL, *hostname = NULL;
105+ rc = ssh_config_parse_uri(value, &username, &hostname, NULL, true);
106 if (rc != SSH_OK) {
107 return -1;
108 }
109- if (port != NULL) {
110- SAFE_FREE(username);
111- SAFE_FREE(hostname);
112- SAFE_FREE(port);
113- return -1;
114- }
115 if (username != NULL) {
116 SAFE_FREE(session->opts.username);
117 session->opts.username = username;
diff --git a/meta-oe/recipes-support/libssh/libssh_0.8.9.bb b/meta-oe/recipes-support/libssh/libssh_0.8.9.bb
index 530dda1f4a..98910d3068 100644
--- a/meta-oe/recipes-support/libssh/libssh_0.8.9.bb
+++ b/meta-oe/recipes-support/libssh/libssh_0.8.9.bb
@@ -11,6 +11,13 @@ SRC_URI = "git://git.libssh.org/projects/libssh.git;protocol=https;branch=stable
11 file://CVE-2023-48795-1.patch \ 11 file://CVE-2023-48795-1.patch \
12 file://CVE-2023-48795-2.patch \ 12 file://CVE-2023-48795-2.patch \
13 file://CVE-2023-48795-3.patch \ 13 file://CVE-2023-48795-3.patch \
14 file://0001-config-Move-common-parser-functions-to-config_parser.patch \
15 file://001_CVE-2023-6004.patch \
16 file://002_CVE-2023-6004.patch \
17 file://003_CVE-2023-6004.patch \
18 file://004_CVE-2023-6004.patch \
19 file://005_CVE-2023-6004.patch \
20 file://006_CVE-2023-6004.patch \
14 " 21 "
15SRCREV = "04685a74df9ce1db1bc116a83a0da78b4f4fa1f8" 22SRCREV = "04685a74df9ce1db1bc116a83a0da78b4f4fa1f8"
16 23