summaryrefslogtreecommitdiffstats
path: root/meta/recipes-support/curl/curl/CVE-2023-28321.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-support/curl/curl/CVE-2023-28321.patch')
-rw-r--r--meta/recipes-support/curl/curl/CVE-2023-28321.patch272
1 files changed, 272 insertions, 0 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2023-28321.patch b/meta/recipes-support/curl/curl/CVE-2023-28321.patch
new file mode 100644
index 0000000000..da1d1fdcd6
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2023-28321.patch
@@ -0,0 +1,272 @@
1Upstream-Status: Backport [import from ubuntu curl_7.68.0-1ubuntu2.20 with
2minor change to tests/data/test1397 part so the patch can be apply.
3upstream: https://github.com/curl/curl/commit/199f2d440d8659b42 ]
4CVE: CVE-2023-28321
5Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
6
7This backport was obtained from SUSE.
8
9From 199f2d440d8659b42670c1b796220792b01a97bf Mon Sep 17 00:00:00 2001
10From: Daniel Stenberg <daniel@haxx.se>
11Date: Mon, 24 Apr 2023 21:07:02 +0200
12Subject: [PATCH] hostcheck: fix host name wildcard checking
13
14The leftmost "label" of the host name can now only match against single
15'*'. Like the browsers have worked for a long time.
16
17- extended unit test 1397 for this
18- move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc
19
20Reported-by: Hiroki Kurosawa
21Closes #11018
22---
23 lib/hostcheck.c | 50 +++++++--------
24 tests/data/test1397 | 10 ++-
25 tests/unit/Makefile.am | 94 ----------------------------
26 tests/unit/Makefile.inc | 94 ++++++++++++++++++++++++++++
27 tests/unit/unit1397.c | 134 ++++++++++++++++++++++++----------------
28 5 files changed, 202 insertions(+), 180 deletions(-)
29
30--- a/lib/hostcheck.c
31+++ b/lib/hostcheck.c
32@@ -58,15 +58,19 @@
33 * apparent distinction between a name and an IP. We need to detect the use of
34 * an IP address and not wildcard match on such names.
35 *
36+ * Only match on "*" being used for the leftmost label, not "a*", "a*b" nor
37+ * "*b".
38+ *
39+ * @unittest: 1397
40+ *
41 * NOTE: hostmatch() gets called with copied buffers so that it can modify the
42 * contents at will.
43 */
44
45 static int hostmatch(char *hostname, char *pattern)
46 {
47- const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
48- int wildcard_enabled;
49- size_t prefixlen, suffixlen;
50+ const char *pattern_label_end, *hostname_label_end;
51+ size_t suffixlen;
52 struct in_addr ignored;
53 #ifdef ENABLE_IPV6
54 struct sockaddr_in6 si6;
55@@ -80,13 +84,12 @@ static int hostmatch(char *hostname, cha
56 if(pattern[len-1]=='.')
57 pattern[len-1] = 0;
58
59- pattern_wildcard = strchr(pattern, '*');
60- if(pattern_wildcard == NULL)
61+ if(strncmp(pattern, "*.", 2))
62 return strcasecompare(pattern, hostname) ?
63 CURL_HOST_MATCH : CURL_HOST_NOMATCH;
64
65 /* detect IP address as hostname and fail the match if so */
66- if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
67+ else if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
68 return CURL_HOST_NOMATCH;
69 #ifdef ENABLE_IPV6
70 if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
71@@ -95,14 +98,9 @@ static int hostmatch(char *hostname, cha
72
73 /* We require at least 2 dots in pattern to avoid too wide wildcard
74 match. */
75- wildcard_enabled = 1;
76 pattern_label_end = strchr(pattern, '.');
77- if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
78- pattern_wildcard > pattern_label_end ||
79- strncasecompare(pattern, "xn--", 4)) {
80- wildcard_enabled = 0;
81- }
82- if(!wildcard_enabled)
83+ if(pattern_label_end == NULL ||
84+ strchr(pattern_label_end + 1, '.') == NULL)
85 return strcasecompare(pattern, hostname) ?
86 CURL_HOST_MATCH : CURL_HOST_NOMATCH;
87
88@@ -117,11 +115,9 @@ static int hostmatch(char *hostname, cha
89 if(hostname_label_end - hostname < pattern_label_end - pattern)
90 return CURL_HOST_NOMATCH;
91
92- prefixlen = pattern_wildcard - pattern;
93- suffixlen = pattern_label_end - (pattern_wildcard + 1);
94- return strncasecompare(pattern, hostname, prefixlen) &&
95- strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen,
96- suffixlen) ?
97+ suffixlen = pattern_label_end - (pattern + 1);
98+ return strncasecompare(pattern + 1, hostname_label_end - suffixlen,
99+ suffixlen) ?
100 CURL_HOST_MATCH : CURL_HOST_NOMATCH;
101 }
102
103--- a/tests/data/test1397
104+++ b/tests/data/test1397
105@@ -2,8 +2,7 @@
106 <info>
107 <keywords>
108 unittest
109-ssl
110-wildcard
111+Curl_cert_hostcheck
112 </keywords>
113 </info>
114
115@@ -16,9 +15,8 @@ none
116 <features>
117 unittest
118 </features>
119- <name>
120-Check wildcard certificate matching function Curl_cert_hostcheck
121- </name>
122+<name>
123+Curl_cert_hostcheck unit tests
124+</name>
125 </client>
126-
127 </testcase>
128--- a/tests/unit/unit1397.c
129+++ b/tests/unit/unit1397.c
130@@ -21,8 +21,6 @@
131 ***************************************************************************/
132 #include "curlcheck.h"
133
134-#include "hostcheck.h" /* from the lib dir */
135-
136 static CURLcode unit_setup(void)
137 {
138 return CURLE_OK;
139@@ -30,50 +28,94 @@ static CURLcode unit_setup(void)
140
141 static void unit_stop(void)
142 {
143- /* done before shutting down and exiting */
144 }
145
146-UNITTEST_START
147+* only these backends define the tested functions */
148+#if defined(USE_OPENSSL) || defined(USE_GSKIT) || \
149+ defined(USE_SCHANNEL)
150+#include "hostcheck.h"
151+struct testcase {
152+ const char *host;
153+ const char *pattern;
154+ bool match;
155+};
156+
157+static struct testcase tests[] = {
158+ {"", "", FALSE},
159+ {"a", "", FALSE},
160+ {"", "b", FALSE},
161+ {"a", "b", FALSE},
162+ {"aa", "bb", FALSE},
163+ {"\xff", "\xff", TRUE},
164+ {"aa.aa.aa", "aa.aa.bb", FALSE},
165+ {"aa.aa.aa", "aa.aa.aa", TRUE},
166+ {"aa.aa.aa", "*.aa.bb", FALSE},
167+ {"aa.aa.aa", "*.aa.aa", TRUE},
168+ {"192.168.0.1", "192.168.0.1", TRUE},
169+ {"192.168.0.1", "*.168.0.1", FALSE},
170+ {"192.168.0.1", "*.0.1", FALSE},
171+ {"h.ello", "*.ello", FALSE},
172+ {"h.ello.", "*.ello", FALSE},
173+ {"h.ello", "*.ello.", FALSE},
174+ {"h.e.llo", "*.e.llo", TRUE},
175+ {"h.e.llo", " *.e.llo", FALSE},
176+ {" h.e.llo", "*.e.llo", TRUE},
177+ {"h.e.llo.", "*.e.llo", TRUE},
178+ {"*.e.llo.", "*.e.llo", TRUE},
179+ {"************.e.llo.", "*.e.llo", TRUE},
180+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
181+ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
182+ "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
183+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
184+ "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
185+ ".e.llo.", "*.e.llo", TRUE},
186+ {"\xfe\xfe.e.llo.", "*.e.llo", TRUE},
187+ {"h.e.llo.", "*.e.llo.", TRUE},
188+ {"h.e.llo", "*.e.llo.", TRUE},
189+ {".h.e.llo", "*.e.llo.", FALSE},
190+ {"h.e.llo", "*.*.llo.", FALSE},
191+ {"h.e.llo", "h.*.llo", FALSE},
192+ {"h.e.llo", "h.e.*", FALSE},
193+ {"hello", "*.ello", FALSE},
194+ {"hello", "**llo", FALSE},
195+ {"bar.foo.example.com", "*.example.com", FALSE},
196+ {"foo.example.com", "*.example.com", TRUE},
197+ {"baz.example.net", "b*z.example.net", FALSE},
198+ {"foobaz.example.net", "*baz.example.net", FALSE},
199+ {"xn--l8j.example.local", "x*.example.local", FALSE},
200+ {"xn--l8j.example.net", "*.example.net", TRUE},
201+ {"xn--l8j.example.net", "*j.example.net", FALSE},
202+ {"xn--l8j.example.net", "xn--l8j.example.net", TRUE},
203+ {"xn--l8j.example.net", "xn--l8j.*.net", FALSE},
204+ {"xl8j.example.net", "*.example.net", TRUE},
205+ {"fe80::3285:a9ff:fe46:b619", "*::3285:a9ff:fe46:b619", FALSE},
206+ {"fe80::3285:a9ff:fe46:b619", "fe80::3285:a9ff:fe46:b619", TRUE},
207+ {NULL, NULL, FALSE}
208+};
209
210-/* only these backends define the tested functions */
211-#if defined(USE_OPENSSL) || defined(USE_GSKIT)
212+UNITTEST_START
213+{
214+ int i;
215+ for(i = 0; tests[i].host; i++) {
216+ if(tests[i].match != Curl_cert_hostcheck(tests[i].pattern,
217+ tests[i].host)) {
218+ fprintf(stderr,
219+ "HOST: %s\n"
220+ "PTRN: %s\n"
221+ "did %sMATCH\n",
222+ tests[i].host,
223+ tests[i].pattern,
224+ tests[i].match ? "NOT ": "");
225+ unitfail++;
226+ }
227+ }
228+}
229
230- /* here you start doing things and checking that the results are good */
231+UNITTEST_STOP
232+#else
233
234-fail_unless(Curl_cert_hostcheck("www.example.com", "www.example.com"),
235- "good 1");
236-fail_unless(Curl_cert_hostcheck("*.example.com", "www.example.com"),
237- "good 2");
238-fail_unless(Curl_cert_hostcheck("xxx*.example.com", "xxxwww.example.com"),
239- "good 3");
240-fail_unless(Curl_cert_hostcheck("f*.example.com", "foo.example.com"),
241- "good 4");
242-fail_unless(Curl_cert_hostcheck("192.168.0.0", "192.168.0.0"),
243- "good 5");
244-
245-fail_if(Curl_cert_hostcheck("xxx.example.com", "www.example.com"), "bad 1");
246-fail_if(Curl_cert_hostcheck("*", "www.example.com"), "bad 2");
247-fail_if(Curl_cert_hostcheck("*.*.com", "www.example.com"), "bad 3");
248-fail_if(Curl_cert_hostcheck("*.example.com", "baa.foo.example.com"), "bad 4");
249-fail_if(Curl_cert_hostcheck("f*.example.com", "baa.example.com"), "bad 5");
250-fail_if(Curl_cert_hostcheck("*.com", "example.com"), "bad 6");
251-fail_if(Curl_cert_hostcheck("*fail.com", "example.com"), "bad 7");
252-fail_if(Curl_cert_hostcheck("*.example.", "www.example."), "bad 8");
253-fail_if(Curl_cert_hostcheck("*.example.", "www.example"), "bad 9");
254-fail_if(Curl_cert_hostcheck("", "www"), "bad 10");
255-fail_if(Curl_cert_hostcheck("*", "www"), "bad 11");
256-fail_if(Curl_cert_hostcheck("*.168.0.0", "192.168.0.0"), "bad 12");
257-fail_if(Curl_cert_hostcheck("www.example.com", "192.168.0.0"), "bad 13");
258-
259-#ifdef ENABLE_IPV6
260-fail_if(Curl_cert_hostcheck("*::3285:a9ff:fe46:b619",
261- "fe80::3285:a9ff:fe46:b619"), "bad 14");
262-fail_unless(Curl_cert_hostcheck("fe80::3285:a9ff:fe46:b619",
263- "fe80::3285:a9ff:fe46:b619"), "good 6");
264-#endif
265+UNITTEST_START
266
267+UNITTEST_STOP
268 #endif
269
270- /* you end the test code like this: */
271-
272-UNITTEST_STOP