summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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