diff options
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch | 353 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch | 728 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch | 130 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl_8.7.1.bb | 3 |
4 files changed, 1214 insertions, 0 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch new file mode 100644 index 0000000000..52ba390cde --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch | |||
@@ -0,0 +1,353 @@ | |||
1 | From 9bee39bfed2c413b4cc4eb306a57ac92a1854907 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Sat, 12 Oct 2024 23:54:39 +0200 | ||
4 | Subject: [PATCH] url: use same credentials on redirect | ||
5 | |||
6 | Previously it could lose the username and only use the password. | ||
7 | |||
8 | Added test 998 and 999 to verify. | ||
9 | |||
10 | Reported-by: Tobias Bora | ||
11 | Fixes #15262 | ||
12 | Closes #15282 | ||
13 | |||
14 | Changes: | ||
15 | - Test files are added in Makefile.inc. | ||
16 | |||
17 | CVE: CVE-2024-11053 | ||
18 | Upstream-Status: Backport [https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907] | ||
19 | |||
20 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
21 | --- | ||
22 | lib/transfer.c | 3 ++ | ||
23 | lib/url.c | 19 +++++---- | ||
24 | lib/urldata.h | 9 +++- | ||
25 | tests/data/Makefile.inc | 2 +- | ||
26 | tests/data/test998 | 92 +++++++++++++++++++++++++++++++++++++++++ | ||
27 | tests/data/test999 | 81 ++++++++++++++++++++++++++++++++++++ | ||
28 | 6 files changed, 195 insertions(+), 11 deletions(-) | ||
29 | create mode 100644 tests/data/test998 | ||
30 | create mode 100644 tests/data/test999 | ||
31 | |||
32 | diff --git a/lib/transfer.c b/lib/transfer.c | ||
33 | index e31d1d6..ccd042b 100644 | ||
34 | --- a/lib/transfer.c | ||
35 | +++ b/lib/transfer.c | ||
36 | @@ -700,6 +700,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) | ||
37 | return CURLE_OUT_OF_MEMORY; | ||
38 | } | ||
39 | |||
40 | + if(data->set.str[STRING_USERNAME] || | ||
41 | + data->set.str[STRING_PASSWORD]) | ||
42 | + data->state.creds_from = CREDS_OPTION; | ||
43 | if(!result) | ||
44 | result = Curl_setstropt(&data->state.aptr.user, | ||
45 | data->set.str[STRING_USERNAME]); | ||
46 | diff --git a/lib/url.c b/lib/url.c | ||
47 | index 224b9f3..05431b9 100644 | ||
48 | --- a/lib/url.c | ||
49 | +++ b/lib/url.c | ||
50 | @@ -1899,10 +1899,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, | ||
51 | return result; | ||
52 | |||
53 | /* | ||
54 | - * User name and password set with their own options override the | ||
55 | - * credentials possibly set in the URL. | ||
56 | + * username and password set with their own options override the credentials | ||
57 | + * possibly set in the URL, but netrc does not. | ||
58 | */ | ||
59 | - if(!data->set.str[STRING_PASSWORD]) { | ||
60 | + if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) { | ||
61 | uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0); | ||
62 | if(!uc) { | ||
63 | char *decoded; | ||
64 | @@ -1915,12 +1915,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, | ||
65 | result = Curl_setstropt(&data->state.aptr.passwd, decoded); | ||
66 | if(result) | ||
67 | return result; | ||
68 | + data->state.creds_from = CREDS_URL; | ||
69 | } | ||
70 | else if(uc != CURLUE_NO_PASSWORD) | ||
71 | return Curl_uc_to_curlcode(uc); | ||
72 | } | ||
73 | |||
74 | - if(!data->set.str[STRING_USERNAME]) { | ||
75 | + if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) { | ||
76 | /* we don't use the URL API's URL decoder option here since it rejects | ||
77 | control codes and we want to allow them for some schemes in the user | ||
78 | and password fields */ | ||
79 | @@ -1934,13 +1935,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, | ||
80 | return result; | ||
81 | conn->user = decoded; | ||
82 | result = Curl_setstropt(&data->state.aptr.user, decoded); | ||
83 | + data->state.creds_from = CREDS_URL; | ||
84 | } | ||
85 | else if(uc != CURLUE_NO_USER) | ||
86 | return Curl_uc_to_curlcode(uc); | ||
87 | - else if(data->state.aptr.passwd) { | ||
88 | - /* no user was set but a password, set a blank user */ | ||
89 | - result = Curl_setstropt(&data->state.aptr.user, ""); | ||
90 | - } | ||
91 | if(result) | ||
92 | return result; | ||
93 | } | ||
94 | @@ -2730,7 +2728,8 @@ static CURLcode override_login(struct Curl_easy *data, | ||
95 | int ret; | ||
96 | bool url_provided = FALSE; | ||
97 | |||
98 | - if(data->state.aptr.user) { | ||
99 | + if(data->state.aptr.user && | ||
100 | + (data->state.creds_from != CREDS_NETRC)) { | ||
101 | /* there was a user name in the URL. Use the URL decoded version */ | ||
102 | userp = &data->state.aptr.user; | ||
103 | url_provided = TRUE; | ||
104 | @@ -2778,6 +2777,7 @@ static CURLcode override_login(struct Curl_easy *data, | ||
105 | result = Curl_setstropt(&data->state.aptr.user, *userp); | ||
106 | if(result) | ||
107 | return result; | ||
108 | + data->state.creds_from = CREDS_NETRC; | ||
109 | } | ||
110 | } | ||
111 | if(data->state.aptr.user) { | ||
112 | @@ -2795,6 +2795,7 @@ static CURLcode override_login(struct Curl_easy *data, | ||
113 | CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp); | ||
114 | if(result) | ||
115 | return result; | ||
116 | + data->state.creds_from = CREDS_NETRC; | ||
117 | } | ||
118 | if(data->state.aptr.passwd) { | ||
119 | uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, | ||
120 | diff --git a/lib/urldata.h b/lib/urldata.h | ||
121 | index ce28f25..b68d023 100644 | ||
122 | --- a/lib/urldata.h | ||
123 | +++ b/lib/urldata.h | ||
124 | @@ -1207,6 +1207,11 @@ struct urlpieces { | ||
125 | char *query; | ||
126 | }; | ||
127 | |||
128 | +#define CREDS_NONE 0 | ||
129 | +#define CREDS_URL 1 /* from URL */ | ||
130 | +#define CREDS_OPTION 2 /* set with a CURLOPT_ */ | ||
131 | +#define CREDS_NETRC 3 /* found in netrc */ | ||
132 | + | ||
133 | struct UrlState { | ||
134 | /* Points to the connection cache */ | ||
135 | struct conncache *conn_cache; | ||
136 | @@ -1344,7 +1349,6 @@ struct UrlState { | ||
137 | char *proxyuser; | ||
138 | char *proxypasswd; | ||
139 | } aptr; | ||
140 | - | ||
141 | unsigned char httpwant; /* when non-zero, a specific HTTP version requested | ||
142 | to be used in the library's request(s) */ | ||
143 | unsigned char httpversion; /* the lowest HTTP version*10 reported by any | ||
144 | @@ -1354,6 +1358,9 @@ struct UrlState { | ||
145 | unsigned char select_bits; /* != 0 -> bitmask of socket events for this | ||
146 | transfer overriding anything the socket may | ||
147 | report */ | ||
148 | + unsigned int creds_from:2; /* where is the server credentials originating | ||
149 | + from, see the CREDS_* defines above */ | ||
150 | + | ||
151 | #ifdef CURLDEBUG | ||
152 | BIT(conncache_lock); | ||
153 | #endif | ||
154 | diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc | ||
155 | index d89e565..03cb6a0 100644 | ||
156 | --- a/tests/data/Makefile.inc | ||
157 | +++ b/tests/data/Makefile.inc | ||
158 | @@ -126,7 +126,7 @@ test952 test953 test954 test955 test956 test957 test958 test959 test960 \ | ||
159 | test961 test962 test963 test964 test965 test966 test967 test968 test969 \ | ||
160 | test970 test971 test972 test973 test974 test975 test976 test977 test978 \ | ||
161 | test979 test980 test981 test982 test983 test984 test985 test986 test987 \ | ||
162 | -test988 test989 test990 test991 test992 \ | ||
163 | +test988 test989 test990 test991 test992 test998 test999 \ | ||
164 | \ | ||
165 | test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \ | ||
166 | test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \ | ||
167 | diff --git a/tests/data/test998 b/tests/data/test998 | ||
168 | new file mode 100644 | ||
169 | index 0000000..596b18e | ||
170 | --- /dev/null | ||
171 | +++ b/tests/data/test998 | ||
172 | @@ -0,0 +1,92 @@ | ||
173 | +<testcase> | ||
174 | + <info> | ||
175 | + <keywords> | ||
176 | + HTTP | ||
177 | + --location-trusted | ||
178 | + </keywords> | ||
179 | + </info> | ||
180 | + | ||
181 | + # | ||
182 | + # Server-side | ||
183 | + <reply> | ||
184 | + <data> | ||
185 | + HTTP/1.1 301 redirect | ||
186 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
187 | + Server: test-server/fake | ||
188 | + Content-Length: 0 | ||
189 | + Connection: close | ||
190 | + Content-Type: text/html | ||
191 | + Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 | ||
192 | + | ||
193 | + </data> | ||
194 | + <data2> | ||
195 | + HTTP/1.1 200 OK | ||
196 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
197 | + Content-Length: 6 | ||
198 | + Content-Type: text/html | ||
199 | + Funny-head: yesyes | ||
200 | + | ||
201 | + -foo- | ||
202 | + </data2> | ||
203 | + | ||
204 | + <datacheck> | ||
205 | + HTTP/1.1 301 redirect | ||
206 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
207 | + Server: test-server/fake | ||
208 | + Content-Length: 0 | ||
209 | + Connection: close | ||
210 | + Content-Type: text/html | ||
211 | + Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 | ||
212 | + | ||
213 | + HTTP/1.1 200 OK | ||
214 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
215 | + Content-Length: 6 | ||
216 | + Content-Type: text/html | ||
217 | + Funny-head: yesyes | ||
218 | + | ||
219 | + -foo- | ||
220 | + </datacheck> | ||
221 | + | ||
222 | + </reply> | ||
223 | + | ||
224 | + # | ||
225 | + # Client-side | ||
226 | + <client> | ||
227 | + <features> | ||
228 | + proxy | ||
229 | + </features> | ||
230 | + <server> | ||
231 | + http | ||
232 | + </server> | ||
233 | + <name> | ||
234 | + HTTP with auth in URL redirected to another host | ||
235 | + </name> | ||
236 | + <command> | ||
237 | + -x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER --location-trusted | ||
238 | + </command> | ||
239 | + </client> | ||
240 | + | ||
241 | + # | ||
242 | + # Verify data after the test has been "shot" | ||
243 | + <verify> | ||
244 | + <strip> | ||
245 | + QUIT | ||
246 | + </strip> | ||
247 | + <protocol> | ||
248 | + GET http://somwhere.example/998 HTTP/1.1 | ||
249 | + Host: somwhere.example | ||
250 | + Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg== | ||
251 | + User-Agent: curl/%VERSION | ||
252 | + Accept: */* | ||
253 | + Proxy-Connection: Keep-Alive | ||
254 | + | ||
255 | + GET http://somewhere.else.example/a/path/9980002 HTTP/1.1 | ||
256 | + Host: somewhere.else.example | ||
257 | + Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg== | ||
258 | + User-Agent: curl/%VERSION | ||
259 | + Accept: */* | ||
260 | + Proxy-Connection: Keep-Alive | ||
261 | + | ||
262 | + </protocol> | ||
263 | + </verify> | ||
264 | + </testcase> | ||
265 | diff --git a/tests/data/test999 b/tests/data/test999 | ||
266 | new file mode 100644 | ||
267 | index 0000000..184821d | ||
268 | --- /dev/null | ||
269 | +++ b/tests/data/test999 | ||
270 | @@ -0,0 +1,81 @@ | ||
271 | +<testcase> | ||
272 | + <info> | ||
273 | + <keywords> | ||
274 | + HTTP | ||
275 | + --location-trusted | ||
276 | + </keywords> | ||
277 | + </info> | ||
278 | + | ||
279 | + # | ||
280 | + # Server-side | ||
281 | + <reply> | ||
282 | + <data nocheck="yes"> | ||
283 | + HTTP/1.1 200 OK | ||
284 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
285 | + Content-Length: 6 | ||
286 | + Content-Type: text/html | ||
287 | + Funny-head: yesyes | ||
288 | + | ||
289 | + -foo- | ||
290 | + </data> | ||
291 | + | ||
292 | + <datacheck> | ||
293 | + HTTP/1.1 301 redirect | ||
294 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
295 | + Server: test-server/fake | ||
296 | + Content-Length: 0 | ||
297 | + Connection: close | ||
298 | + Content-Type: text/html | ||
299 | + Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 | ||
300 | + | ||
301 | + HTTP/1.1 200 OK | ||
302 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
303 | + Content-Length: 6 | ||
304 | + Content-Type: text/html | ||
305 | + Funny-head: yesyes | ||
306 | + | ||
307 | + -foo- | ||
308 | + </datacheck> | ||
309 | + | ||
310 | + </reply> | ||
311 | + | ||
312 | + # | ||
313 | + # Client-side | ||
314 | + <client> | ||
315 | + <features> | ||
316 | + proxy | ||
317 | + </features> | ||
318 | + <server> | ||
319 | + http | ||
320 | + </server> | ||
321 | + <name> | ||
322 | + HTTP with auth in first URL but not second | ||
323 | + </name> | ||
324 | + <command> | ||
325 | + -x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER http://somewhere.else.example/%TESTNUMBER | ||
326 | + </command> | ||
327 | + </client> | ||
328 | + | ||
329 | + # | ||
330 | + # Verify data after the test has been "shot" | ||
331 | + <verify> | ||
332 | + <strip> | ||
333 | + QUIT | ||
334 | + </strip> | ||
335 | + <protocol> | ||
336 | + GET http://somwhere.example/%TESTNUMBER HTTP/1.1 | ||
337 | + Host: somwhere.example | ||
338 | + Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg== | ||
339 | + User-Agent: curl/%VERSION | ||
340 | + Accept: */* | ||
341 | + Proxy-Connection: Keep-Alive | ||
342 | + | ||
343 | + GET http://somewhere.else.example/%TESTNUMBER HTTP/1.1 | ||
344 | + Host: somewhere.else.example | ||
345 | + User-Agent: curl/%VERSION | ||
346 | + Accept: */* | ||
347 | + Proxy-Connection: Keep-Alive | ||
348 | + | ||
349 | + </protocol> | ||
350 | + </verify> | ||
351 | + </testcase> | ||
352 | -- | ||
353 | 2.40.0 | ||
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch new file mode 100644 index 0000000000..7f45f79cf2 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch | |||
@@ -0,0 +1,728 @@ | |||
1 | From e9b9bbac22c26cf67316fa8e6c6b9e831af31949 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Fri, 15 Nov 2024 11:06:36 +0100 | ||
4 | Subject: [PATCH] netrc: address several netrc parser flaws | ||
5 | |||
6 | - make sure that a match that returns a username also returns a | ||
7 | password, that should be blank if no password is found | ||
8 | |||
9 | - fix handling of multiple logins for same host where the password/login | ||
10 | order might be reversed. | ||
11 | |||
12 | - reject credentials provided in the .netrc if they contain ASCII control | ||
13 | codes - if the used protocol does not support such (like HTTP and WS do) | ||
14 | |||
15 | Reported-by: Harry Sintonen | ||
16 | |||
17 | Add test 478, 479 and 480 to verify. Updated unit 1304. | ||
18 | |||
19 | Closes #15586 | ||
20 | |||
21 | Changes: | ||
22 | - Refresh patch context. | ||
23 | - Adjust `%LOGDIR/` to 'log/' due to its absence in code. | ||
24 | - Backported only required enum found_state defination from: | ||
25 | https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca | ||
26 | - Replaces the previous usage of the state_login, state_password, and | ||
27 | state_our_login variables with the found_state enum, which includes the | ||
28 | values NONE, LOGIN, and PASSWORD. As a result, all conditionals and memory | ||
29 | management logic associated with these variables were updated. | ||
30 | |||
31 | CVE: CVE-2024-11053 | ||
32 | Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af3194] | ||
33 | |||
34 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
35 | --- | ||
36 | lib/netrc.c | 122 ++++++++++++++++++++++------------------ | ||
37 | lib/url.c | 59 ++++++++++++------- | ||
38 | tests/data/Makefile.inc | 2 +- | ||
39 | tests/data/test478 | 73 ++++++++++++++++++++++++ | ||
40 | tests/data/test479 | 107 +++++++++++++++++++++++++++++++++++ | ||
41 | tests/data/test480 | 38 +++++++++++++ | ||
42 | tests/unit/unit1304.c | 75 +++++++----------------- | ||
43 | 7 files changed, 347 insertions(+), 129 deletions(-) | ||
44 | create mode 100644 tests/data/test478 | ||
45 | create mode 100644 tests/data/test479 | ||
46 | create mode 100644 tests/data/test480 | ||
47 | |||
48 | diff --git a/lib/netrc.c b/lib/netrc.c | ||
49 | index cd2a284..64efdc0 100644 | ||
50 | --- a/lib/netrc.c | ||
51 | +++ b/lib/netrc.c | ||
52 | @@ -49,6 +49,15 @@ enum host_lookup_state { | ||
53 | MACDEF | ||
54 | }; | ||
55 | |||
56 | +enum found_state { | ||
57 | + NONE, | ||
58 | + LOGIN, | ||
59 | + PASSWORD | ||
60 | +}; | ||
61 | + | ||
62 | +#define FOUND_LOGIN 1 | ||
63 | +#define FOUND_PASSWORD 2 | ||
64 | + | ||
65 | #define NETRC_FILE_MISSING 1 | ||
66 | #define NETRC_FAILED -1 | ||
67 | #define NETRC_SUCCESS 0 | ||
68 | @@ -59,23 +68,20 @@ enum host_lookup_state { | ||
69 | * Returns zero on success. | ||
70 | */ | ||
71 | static int parsenetrc(const char *host, | ||
72 | - char **loginp, | ||
73 | + char **loginp, /* might point to a username */ | ||
74 | char **passwordp, | ||
75 | char *netrcfile) | ||
76 | { | ||
77 | FILE *file; | ||
78 | int retcode = NETRC_FILE_MISSING; | ||
79 | char *login = *loginp; | ||
80 | - char *password = *passwordp; | ||
81 | - bool specific_login = (login && *login != 0); | ||
82 | - bool login_alloc = FALSE; | ||
83 | - bool password_alloc = FALSE; | ||
84 | + char *password = NULL; | ||
85 | + bool specific_login = login; /* points to something */ | ||
86 | enum host_lookup_state state = NOTHING; | ||
87 | - | ||
88 | - char state_login = 0; /* Found a login keyword */ | ||
89 | - char state_password = 0; /* Found a password keyword */ | ||
90 | - int state_our_login = TRUE; /* With specific_login, found *our* login | ||
91 | - name (or login-less line) */ | ||
92 | + enum found_state keyword = NONE; | ||
93 | + unsigned char found = 0; /* login + password found bits, as they can come in | ||
94 | + any order */ | ||
95 | + bool our_login = FALSE; /* found our login name */ | ||
96 | |||
97 | DEBUGASSERT(netrcfile); | ||
98 | |||
99 | @@ -97,7 +103,7 @@ static int parsenetrc(const char *host, | ||
100 | continue; | ||
101 | } | ||
102 | tok = netrcbuffer; | ||
103 | - while(tok) { | ||
104 | + while(tok && !done) { | ||
105 | while(ISBLANK(*tok)) | ||
106 | tok++; | ||
107 | /* tok is first non-space letter */ | ||
108 | @@ -156,11 +162,6 @@ static int parsenetrc(const char *host, | ||
109 | } | ||
110 | } | ||
111 | |||
112 | - if((login && *login) && (password && *password)) { | ||
113 | - done = TRUE; | ||
114 | - break; | ||
115 | - } | ||
116 | - | ||
117 | switch(state) { | ||
118 | case NOTHING: | ||
119 | if(strcasecompare("macdef", tok)) { | ||
120 | @@ -175,6 +176,12 @@ static int parsenetrc(const char *host, | ||
121 | after this we need to search for 'login' and | ||
122 | 'password'. */ | ||
123 | state = HOSTFOUND; | ||
124 | + keyword = NONE; | ||
125 | + found = 0; | ||
126 | + our_login = FALSE; | ||
127 | + Curl_safefree(password); | ||
128 | + if(!specific_login) | ||
129 | + Curl_safefree(login); | ||
130 | } | ||
131 | else if(strcasecompare("default", tok)) { | ||
132 | state = HOSTVALID; | ||
133 | @@ -198,48 +205,55 @@ static int parsenetrc(const char *host, | ||
134 | break; | ||
135 | case HOSTVALID: | ||
136 | /* we are now parsing sub-keywords concerning "our" host */ | ||
137 | - if(state_login) { | ||
138 | + if(keyword == LOGIN) { | ||
139 | if(specific_login) { | ||
140 | - state_our_login = !Curl_timestrcmp(login, tok); | ||
141 | + our_login = !Curl_timestrcmp(login, tok); | ||
142 | } | ||
143 | - else if(!login || Curl_timestrcmp(login, tok)) { | ||
144 | - if(login_alloc) { | ||
145 | - free(login); | ||
146 | - login_alloc = FALSE; | ||
147 | - } | ||
148 | + else { | ||
149 | + our_login = TRUE; | ||
150 | + free(login); | ||
151 | login = strdup(tok); | ||
152 | if(!login) { | ||
153 | retcode = NETRC_FAILED; /* allocation failed */ | ||
154 | goto out; | ||
155 | } | ||
156 | - login_alloc = TRUE; | ||
157 | } | ||
158 | - state_login = 0; | ||
159 | + found |= FOUND_LOGIN; | ||
160 | + keyword = NONE; | ||
161 | } | ||
162 | - else if(state_password) { | ||
163 | - if((state_our_login || !specific_login) | ||
164 | - && (!password || Curl_timestrcmp(password, tok))) { | ||
165 | - if(password_alloc) { | ||
166 | - free(password); | ||
167 | - password_alloc = FALSE; | ||
168 | - } | ||
169 | - password = strdup(tok); | ||
170 | - if(!password) { | ||
171 | - retcode = NETRC_FAILED; /* allocation failed */ | ||
172 | - goto out; | ||
173 | - } | ||
174 | - password_alloc = TRUE; | ||
175 | + else if(keyword == PASSWORD) { | ||
176 | + free(password); | ||
177 | + password = strdup(tok); | ||
178 | + if(!password) { | ||
179 | + retcode = NETRC_FAILED; /* allocation failed */ | ||
180 | + goto out; | ||
181 | } | ||
182 | - state_password = 0; | ||
183 | + found |= FOUND_PASSWORD; | ||
184 | + keyword = NONE; | ||
185 | } | ||
186 | else if(strcasecompare("login", tok)) | ||
187 | - state_login = 1; | ||
188 | + keyword = LOGIN; | ||
189 | else if(strcasecompare("password", tok)) | ||
190 | - state_password = 1; | ||
191 | + keyword = PASSWORD; | ||
192 | else if(strcasecompare("machine", tok)) { | ||
193 | - /* ok, there's machine here go => */ | ||
194 | + /* a new machine here */ | ||
195 | state = HOSTFOUND; | ||
196 | - state_our_login = FALSE; | ||
197 | + keyword = NONE; | ||
198 | + found = 0; | ||
199 | + Curl_safefree(password); | ||
200 | + if(!specific_login) | ||
201 | + Curl_safefree(login); | ||
202 | + } | ||
203 | + else if(strcasecompare("default", tok)) { | ||
204 | + state = HOSTVALID; | ||
205 | + retcode = NETRC_SUCCESS; /* we did find our host */ | ||
206 | + Curl_safefree(password); | ||
207 | + if(!specific_login) | ||
208 | + Curl_safefree(login); | ||
209 | + } | ||
210 | + if((found == (FOUND_PASSWORD|FOUND_LOGIN)) && our_login) { | ||
211 | + done = TRUE; | ||
212 | + break; | ||
213 | } | ||
214 | break; | ||
215 | } /* switch (state) */ | ||
216 | @@ -249,24 +263,22 @@ static int parsenetrc(const char *host, | ||
217 | |||
218 | out: | ||
219 | Curl_dyn_free(&buf); | ||
220 | + if(!retcode && !password && our_login) { | ||
221 | + /* success without a password, set a blank one */ | ||
222 | + password = strdup(""); | ||
223 | + if(!password) | ||
224 | + retcode = 1; /* out of memory */ | ||
225 | + } | ||
226 | if(!retcode) { | ||
227 | /* success */ | ||
228 | - if(login_alloc) { | ||
229 | - if(*loginp) | ||
230 | - free(*loginp); | ||
231 | + if(!specific_login) | ||
232 | *loginp = login; | ||
233 | - } | ||
234 | - if(password_alloc) { | ||
235 | - if(*passwordp) | ||
236 | - free(*passwordp); | ||
237 | - *passwordp = password; | ||
238 | - } | ||
239 | + *passwordp = password; | ||
240 | } | ||
241 | else { | ||
242 | - if(login_alloc) | ||
243 | + if(!specific_login) | ||
244 | free(login); | ||
245 | - if(password_alloc) | ||
246 | - free(password); | ||
247 | + free(password); | ||
248 | } | ||
249 | fclose(file); | ||
250 | } | ||
251 | diff --git a/lib/url.c b/lib/url.c | ||
252 | index 05431b9..1439c9e 100644 | ||
253 | --- a/lib/url.c | ||
254 | +++ b/lib/url.c | ||
255 | @@ -2699,6 +2699,17 @@ static CURLcode parse_remote_port(struct Curl_easy *data, | ||
256 | return CURLE_OK; | ||
257 | } | ||
258 | |||
259 | +static bool str_has_ctrl(const char *input) | ||
260 | +{ | ||
261 | + const unsigned char *str = (const unsigned char *)input; | ||
262 | + while(*str) { | ||
263 | + if(*str < 0x20) | ||
264 | + return TRUE; | ||
265 | + str++; | ||
266 | + } | ||
267 | + return FALSE; | ||
268 | +} | ||
269 | + | ||
270 | /* | ||
271 | * Override the login details from the URL with that in the CURLOPT_USERPWD | ||
272 | * option or a .netrc file, if applicable. | ||
273 | @@ -2730,29 +2741,39 @@ static CURLcode override_login(struct Curl_easy *data, | ||
274 | |||
275 | if(data->state.aptr.user && | ||
276 | (data->state.creds_from != CREDS_NETRC)) { | ||
277 | - /* there was a user name in the URL. Use the URL decoded version */ | ||
278 | + /* there was a username with a length in the URL. Use the URL decoded | ||
279 | + version */ | ||
280 | userp = &data->state.aptr.user; | ||
281 | url_provided = TRUE; | ||
282 | } | ||
283 | |||
284 | - ret = Curl_parsenetrc(conn->host.name, | ||
285 | - userp, passwdp, | ||
286 | - data->set.str[STRING_NETRC_FILE]); | ||
287 | - if(ret > 0) { | ||
288 | - infof(data, "Couldn't find host %s in the %s file; using defaults", | ||
289 | - conn->host.name, | ||
290 | - (data->set.str[STRING_NETRC_FILE] ? | ||
291 | - data->set.str[STRING_NETRC_FILE] : ".netrc")); | ||
292 | - } | ||
293 | - else if(ret < 0) { | ||
294 | - failf(data, ".netrc parser error"); | ||
295 | - return CURLE_READ_ERROR; | ||
296 | - } | ||
297 | - else { | ||
298 | - /* set bits.netrc TRUE to remember that we got the name from a .netrc | ||
299 | - file, so that it is safe to use even if we followed a Location: to a | ||
300 | - different host or similar. */ | ||
301 | - conn->bits.netrc = TRUE; | ||
302 | + if(!*passwdp) { | ||
303 | + ret = Curl_parsenetrc(conn->host.name, userp, passwdp, | ||
304 | + data->set.str[STRING_NETRC_FILE]); | ||
305 | + if(ret > 0) { | ||
306 | + infof(data, "Couldn't find host %s in the %s file; using defaults", | ||
307 | + conn->host.name, | ||
308 | + (data->set.str[STRING_NETRC_FILE] ? | ||
309 | + data->set.str[STRING_NETRC_FILE] : ".netrc")); | ||
310 | + } | ||
311 | + else if(ret < 0) { | ||
312 | + failf(data, ".netrc parser error"); | ||
313 | + return CURLE_READ_ERROR; | ||
314 | + } | ||
315 | + else { | ||
316 | + if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) { | ||
317 | + /* if the protocol can't handle control codes in credentials, make | ||
318 | + sure there are none */ | ||
319 | + if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) { | ||
320 | + failf(data, "control code detected in .netrc credentials"); | ||
321 | + return CURLE_READ_ERROR; | ||
322 | + } | ||
323 | + } | ||
324 | + /* set bits.netrc TRUE to remember that we got the name from a .netrc | ||
325 | + file, so that it is safe to use even if we followed a Location: to a | ||
326 | + different host or similar. */ | ||
327 | + conn->bits.netrc = TRUE; | ||
328 | + } | ||
329 | } | ||
330 | if(url_provided) { | ||
331 | Curl_safefree(conn->user); | ||
332 | diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc | ||
333 | index 03cb6a0..e3508cb 100644 | ||
334 | --- a/tests/data/Makefile.inc | ||
335 | +++ b/tests/data/Makefile.inc | ||
336 | @@ -73,7 +73,7 @@ test426 test427 test428 test429 test430 test431 test432 test433 test434 \ | ||
337 | test435 test436 test437 test438 test439 test440 test441 test442 test443 \ | ||
338 | test444 test445 test446 test447 test448 test449 test450 test451 test452 \ | ||
339 | test453 test454 test455 test456 test457 test458 test459 test460 test461 \ | ||
340 | -test462 test463 test467 test468 \ | ||
341 | +test462 test463 test467 test468 test478 test479 test480 \ | ||
342 | \ | ||
343 | test490 test491 test492 test493 test494 test495 test496 test497 test498 \ | ||
344 | test499 test500 test501 test502 test503 test504 test505 test506 test507 \ | ||
345 | diff --git a/tests/data/test478 b/tests/data/test478 | ||
346 | new file mode 100644 | ||
347 | index 0000000..4acc72e | ||
348 | --- /dev/null | ||
349 | +++ b/tests/data/test478 | ||
350 | @@ -0,0 +1,73 @@ | ||
351 | +<testcase> | ||
352 | + <info> | ||
353 | + <keywords> | ||
354 | + netrc | ||
355 | + HTTP | ||
356 | + </keywords> | ||
357 | + </info> | ||
358 | + # | ||
359 | + # Server-side | ||
360 | + <reply> | ||
361 | + <data crlf="yes"> | ||
362 | + HTTP/1.1 200 OK | ||
363 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
364 | + Server: test-server/fake | ||
365 | + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT | ||
366 | + ETag: "21025-dc7-39462498" | ||
367 | + Accept-Ranges: bytes | ||
368 | + Content-Length: 6 | ||
369 | + Connection: close | ||
370 | + Content-Type: text/html | ||
371 | + Funny-head: yesyes | ||
372 | + | ||
373 | + -foo- | ||
374 | + </data> | ||
375 | + </reply> | ||
376 | + | ||
377 | + # | ||
378 | + # Client-side | ||
379 | + <client> | ||
380 | + <server> | ||
381 | + http | ||
382 | + </server> | ||
383 | + <features> | ||
384 | + proxy | ||
385 | + </features> | ||
386 | + <name> | ||
387 | + .netrc with multiple accounts for same host | ||
388 | + </name> | ||
389 | + <command> | ||
390 | + --netrc --netrc-file log/netrc%TESTNUMBER -x http://%HOSTIP:%HTTPPORT/ http://debbie@github.com/ | ||
391 | + </command> | ||
392 | + <file name="log/netrc%TESTNUMBER" > | ||
393 | + | ||
394 | + machine github.com | ||
395 | + password weird | ||
396 | + password firstone | ||
397 | + login daniel | ||
398 | + | ||
399 | + machine github.com | ||
400 | + | ||
401 | + machine github.com | ||
402 | + login debbie | ||
403 | + | ||
404 | + machine github.com | ||
405 | + password weird | ||
406 | + password "second\r" | ||
407 | + login debbie | ||
408 | + | ||
409 | + </file> | ||
410 | + </client> | ||
411 | + | ||
412 | + <verify> | ||
413 | + <protocol> | ||
414 | + GET http://github.com/ HTTP/1.1 | ||
415 | + Host: github.com | ||
416 | + Authorization: Basic %b64[debbie:second%0D]b64% | ||
417 | + User-Agent: curl/%VERSION | ||
418 | + Accept: */* | ||
419 | + Proxy-Connection: Keep-Alive | ||
420 | + | ||
421 | + </protocol> | ||
422 | + </verify> | ||
423 | + </testcase> | ||
424 | diff --git a/tests/data/test479 b/tests/data/test479 | ||
425 | new file mode 100644 | ||
426 | index 0000000..62a2057 | ||
427 | --- /dev/null | ||
428 | +++ b/tests/data/test479 | ||
429 | @@ -0,0 +1,107 @@ | ||
430 | +<testcase> | ||
431 | + <info> | ||
432 | + <keywords> | ||
433 | + netrc | ||
434 | + HTTP | ||
435 | + </keywords> | ||
436 | + </info> | ||
437 | + # | ||
438 | + # Server-side | ||
439 | + <reply> | ||
440 | + <data crlf="yes"> | ||
441 | + HTTP/1.1 301 Follow this you fool | ||
442 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
443 | + Server: test-server/fake | ||
444 | + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT | ||
445 | + ETag: "21025-dc7-39462498" | ||
446 | + Accept-Ranges: bytes | ||
447 | + Content-Length: 6 | ||
448 | + Connection: close | ||
449 | + Location: http://b.com/%TESTNUMBER0002 | ||
450 | + | ||
451 | + -foo- | ||
452 | + </data> | ||
453 | + | ||
454 | + <data2 crlf="yes"> | ||
455 | + HTTP/1.1 200 OK | ||
456 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
457 | + Server: test-server/fake | ||
458 | + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT | ||
459 | + ETag: "21025-dc7-39462498" | ||
460 | + Accept-Ranges: bytes | ||
461 | + Content-Length: 7 | ||
462 | + Connection: close | ||
463 | + | ||
464 | + target | ||
465 | + </data2> | ||
466 | + | ||
467 | + <datacheck crlf="yes"> | ||
468 | + HTTP/1.1 301 Follow this you fool | ||
469 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
470 | + Server: test-server/fake | ||
471 | + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT | ||
472 | + ETag: "21025-dc7-39462498" | ||
473 | + Accept-Ranges: bytes | ||
474 | + Content-Length: 6 | ||
475 | + Connection: close | ||
476 | + Location: http://b.com/%TESTNUMBER0002 | ||
477 | + | ||
478 | + HTTP/1.1 200 OK | ||
479 | + Date: Tue, 09 Nov 2010 14:49:00 GMT | ||
480 | + Server: test-server/fake | ||
481 | + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT | ||
482 | + ETag: "21025-dc7-39462498" | ||
483 | + Accept-Ranges: bytes | ||
484 | + Content-Length: 7 | ||
485 | + Connection: close | ||
486 | + | ||
487 | + target | ||
488 | + </datacheck> | ||
489 | + </reply> | ||
490 | + | ||
491 | + # | ||
492 | + # Client-side | ||
493 | + <client> | ||
494 | + <server> | ||
495 | + http | ||
496 | + </server> | ||
497 | + <features> | ||
498 | + proxy | ||
499 | + </features> | ||
500 | + <name> | ||
501 | + .netrc with redirect and default without password | ||
502 | + </name> | ||
503 | + <command> | ||
504 | + --netrc --netrc-file log/netrc%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/ | ||
505 | + </command> | ||
506 | + <file name="log/netrc%TESTNUMBER" > | ||
507 | + | ||
508 | + machine a.com | ||
509 | + login alice | ||
510 | + password alicespassword | ||
511 | + | ||
512 | + default | ||
513 | + login bob | ||
514 | + | ||
515 | + </file> | ||
516 | + </client> | ||
517 | + | ||
518 | + <verify> | ||
519 | + <protocol> | ||
520 | + GET http://a.com/ HTTP/1.1 | ||
521 | + Host: a.com | ||
522 | + Authorization: Basic %b64[alice:alicespassword]b64% | ||
523 | + User-Agent: curl/%VERSION | ||
524 | + Accept: */* | ||
525 | + Proxy-Connection: Keep-Alive | ||
526 | + | ||
527 | + GET http://b.com/%TESTNUMBER0002 HTTP/1.1 | ||
528 | + Host: b.com | ||
529 | + Authorization: Basic %b64[bob:]b64% | ||
530 | + User-Agent: curl/%VERSION | ||
531 | + Accept: */* | ||
532 | + Proxy-Connection: Keep-Alive | ||
533 | + | ||
534 | + </protocol> | ||
535 | + </verify> | ||
536 | + </testcase> | ||
537 | diff --git a/tests/data/test480 b/tests/data/test480 | ||
538 | new file mode 100644 | ||
539 | index 0000000..47db7ab | ||
540 | --- /dev/null | ||
541 | +++ b/tests/data/test480 | ||
542 | @@ -0,0 +1,38 @@ | ||
543 | +<testcase> | ||
544 | + <info> | ||
545 | + <keywords> | ||
546 | + netrc | ||
547 | + pop3 | ||
548 | + </keywords> | ||
549 | + </info> | ||
550 | + # | ||
551 | + # Server-side | ||
552 | + <reply> | ||
553 | + | ||
554 | + </reply> | ||
555 | + | ||
556 | + # | ||
557 | + # Client-side | ||
558 | + <client> | ||
559 | + <server> | ||
560 | + pop3 | ||
561 | + </server> | ||
562 | + <name> | ||
563 | + Reject .netrc with credentials using CRLF for POP3 | ||
564 | + </name> | ||
565 | + <command> | ||
566 | + --netrc --netrc-file log/netrc%TESTNUMBER pop3://%HOSTIP:%POP3PORT/%TESTNUMBER | ||
567 | + </command> | ||
568 | + <file name="log/netrc%TESTNUMBER" > | ||
569 | + machine %HOSTIP | ||
570 | + login alice | ||
571 | + password "password\r\ncommand" | ||
572 | + </file> | ||
573 | + </client> | ||
574 | + | ||
575 | + <verify> | ||
576 | + <errorcode> | ||
577 | + 26 | ||
578 | + </errorcode> | ||
579 | + </verify> | ||
580 | + </testcase> | ||
581 | diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c | ||
582 | index 0288562..b2b4366 100644 | ||
583 | --- a/tests/unit/unit1304.c | ||
584 | +++ b/tests/unit/unit1304.c | ||
585 | @@ -32,13 +32,8 @@ static char *password; | ||
586 | |||
587 | static CURLcode unit_setup(void) | ||
588 | { | ||
589 | - password = strdup(""); | ||
590 | - login = strdup(""); | ||
591 | - if(!password || !login) { | ||
592 | - Curl_safefree(password); | ||
593 | - Curl_safefree(login); | ||
594 | - return CURLE_OUT_OF_MEMORY; | ||
595 | - } | ||
596 | + password = NULL; | ||
597 | + login = NULL; | ||
598 | return CURLE_OK; | ||
599 | } | ||
600 | |||
601 | @@ -56,76 +51,48 @@ UNITTEST_START | ||
602 | */ | ||
603 | result = Curl_parsenetrc("test.example.com", &login, &password, arg); | ||
604 | fail_unless(result == 1, "Host not found should return 1"); | ||
605 | - abort_unless(password != NULL, "returned NULL!"); | ||
606 | - fail_unless(password[0] == 0, "password should not have been changed"); | ||
607 | - abort_unless(login != NULL, "returned NULL!"); | ||
608 | - fail_unless(login[0] == 0, "login should not have been changed"); | ||
609 | + abort_unless(password == NULL, "password did not return NULL!"); | ||
610 | + abort_unless(login == NULL, "user did not return NULL!"); | ||
611 | |||
612 | /* | ||
613 | * Test a non existent login in our netrc file. | ||
614 | */ | ||
615 | - free(login); | ||
616 | - login = strdup("me"); | ||
617 | - abort_unless(login != NULL, "returned NULL!"); | ||
618 | + login = (char *)"me"; | ||
619 | result = Curl_parsenetrc("example.com", &login, &password, arg); | ||
620 | fail_unless(result == 0, "Host should have been found"); | ||
621 | - abort_unless(password != NULL, "returned NULL!"); | ||
622 | - fail_unless(password[0] == 0, "password should not have been changed"); | ||
623 | - abort_unless(login != NULL, "returned NULL!"); | ||
624 | - fail_unless(strncmp(login, "me", 2) == 0, | ||
625 | - "login should not have been changed"); | ||
626 | + abort_unless(password == NULL, "password is not NULL!"); | ||
627 | |||
628 | /* | ||
629 | * Test a non existent login and host in our netrc file. | ||
630 | */ | ||
631 | - free(login); | ||
632 | - login = strdup("me"); | ||
633 | - abort_unless(login != NULL, "returned NULL!"); | ||
634 | + login = (char *)"me"; | ||
635 | result = Curl_parsenetrc("test.example.com", &login, &password, arg); | ||
636 | fail_unless(result == 1, "Host not found should return 1"); | ||
637 | - abort_unless(password != NULL, "returned NULL!"); | ||
638 | - fail_unless(password[0] == 0, "password should not have been changed"); | ||
639 | - abort_unless(login != NULL, "returned NULL!"); | ||
640 | - fail_unless(strncmp(login, "me", 2) == 0, | ||
641 | - "login should not have been changed"); | ||
642 | + abort_unless(password == NULL, "password is not NULL!"); | ||
643 | |||
644 | /* | ||
645 | * Test a non existent login (substring of an existing one) in our | ||
646 | * netrc file. | ||
647 | */ | ||
648 | - free(login); | ||
649 | - login = strdup("admi"); | ||
650 | - abort_unless(login != NULL, "returned NULL!"); | ||
651 | + login = (char *)"admi"; | ||
652 | result = Curl_parsenetrc("example.com", &login, &password, arg); | ||
653 | fail_unless(result == 0, "Host should have been found"); | ||
654 | - abort_unless(password != NULL, "returned NULL!"); | ||
655 | - fail_unless(password[0] == 0, "password should not have been changed"); | ||
656 | - abort_unless(login != NULL, "returned NULL!"); | ||
657 | - fail_unless(strncmp(login, "admi", 4) == 0, | ||
658 | - "login should not have been changed"); | ||
659 | + abort_unless(password == NULL, "password is not NULL!"); | ||
660 | |||
661 | /* | ||
662 | * Test a non existent login (superstring of an existing one) | ||
663 | * in our netrc file. | ||
664 | */ | ||
665 | - free(login); | ||
666 | - login = strdup("adminn"); | ||
667 | - abort_unless(login != NULL, "returned NULL!"); | ||
668 | + login = (char *)"adminn"; | ||
669 | result = Curl_parsenetrc("example.com", &login, &password, arg); | ||
670 | fail_unless(result == 0, "Host should have been found"); | ||
671 | - abort_unless(password != NULL, "returned NULL!"); | ||
672 | - fail_unless(password[0] == 0, "password should not have been changed"); | ||
673 | - abort_unless(login != NULL, "returned NULL!"); | ||
674 | - fail_unless(strncmp(login, "adminn", 6) == 0, | ||
675 | - "login should not have been changed"); | ||
676 | + abort_unless(password == NULL, "password is not NULL!"); | ||
677 | |||
678 | /* | ||
679 | * Test for the first existing host in our netrc file | ||
680 | * with login[0] = 0. | ||
681 | */ | ||
682 | - free(login); | ||
683 | - login = strdup(""); | ||
684 | - abort_unless(login != NULL, "returned NULL!"); | ||
685 | + login = NULL; | ||
686 | result = Curl_parsenetrc("example.com", &login, &password, arg); | ||
687 | fail_unless(result == 0, "Host should have been found"); | ||
688 | abort_unless(password != NULL, "returned NULL!"); | ||
689 | @@ -139,8 +106,9 @@ UNITTEST_START | ||
690 | * with login[0] != 0. | ||
691 | */ | ||
692 | free(password); | ||
693 | - password = strdup(""); | ||
694 | - abort_unless(password != NULL, "returned NULL!"); | ||
695 | + free(login); | ||
696 | + password = NULL; | ||
697 | + login = NULL; | ||
698 | result = Curl_parsenetrc("example.com", &login, &password, arg); | ||
699 | fail_unless(result == 0, "Host should have been found"); | ||
700 | abort_unless(password != NULL, "returned NULL!"); | ||
701 | @@ -154,11 +122,9 @@ UNITTEST_START | ||
702 | * with login[0] = 0. | ||
703 | */ | ||
704 | free(password); | ||
705 | - password = strdup(""); | ||
706 | - abort_unless(password != NULL, "returned NULL!"); | ||
707 | + password = NULL; | ||
708 | free(login); | ||
709 | - login = strdup(""); | ||
710 | - abort_unless(login != NULL, "returned NULL!"); | ||
711 | + login = NULL; | ||
712 | result = Curl_parsenetrc("curl.example.com", &login, &password, arg); | ||
713 | fail_unless(result == 0, "Host should have been found"); | ||
714 | abort_unless(password != NULL, "returned NULL!"); | ||
715 | @@ -172,8 +138,9 @@ UNITTEST_START | ||
716 | * with login[0] != 0. | ||
717 | */ | ||
718 | free(password); | ||
719 | - password = strdup(""); | ||
720 | - abort_unless(password != NULL, "returned NULL!"); | ||
721 | + free(login); | ||
722 | + password = NULL; | ||
723 | + login = NULL; | ||
724 | result = Curl_parsenetrc("curl.example.com", &login, &password, arg); | ||
725 | fail_unless(result == 0, "Host should have been found"); | ||
726 | abort_unless(password != NULL, "returned NULL!"); | ||
727 | -- | ||
728 | 2.40.0 | ||
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch new file mode 100644 index 0000000000..32fb1812d6 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch | |||
@@ -0,0 +1,130 @@ | |||
1 | From 9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Tue, 17 Dec 2024 23:56:42 +0100 | ||
4 | Subject: [PATCH] netrc: fix password-only entries | ||
5 | |||
6 | When a specific hostname matched, and only a password is set before | ||
7 | another machine is specified in the netrc file, the parser would not be | ||
8 | happy and stop there and return the password-only state. It instead | ||
9 | continued and did not return a match. | ||
10 | |||
11 | Add test 2005 to verify this case | ||
12 | |||
13 | Regression from e9b9bba, shipped in 8.11.1. | ||
14 | |||
15 | Reported-by: Ben Zanin | ||
16 | Fixes #15767 | ||
17 | Closes #15768 | ||
18 | |||
19 | CVE: CVE-2024-11053 | ||
20 | Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf] | ||
21 | |||
22 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
23 | --- | ||
24 | lib/netrc.c | 7 +++++- | ||
25 | tests/data/Makefile.inc | 2 +- | ||
26 | tests/data/test2005 | 55 +++++++++++++++++++++++++++++++++++++++++ | ||
27 | 3 files changed, 62 insertions(+), 2 deletions(-) | ||
28 | create mode 100644 tests/data/test2005 | ||
29 | |||
30 | diff --git a/lib/netrc.c b/lib/netrc.c | ||
31 | index 64efdc0..695e89a 100644 | ||
32 | --- a/lib/netrc.c | ||
33 | +++ b/lib/netrc.c | ||
34 | @@ -228,7 +228,8 @@ static int parsenetrc(const char *host, | ||
35 | retcode = NETRC_FAILED; /* allocation failed */ | ||
36 | goto out; | ||
37 | } | ||
38 | - found |= FOUND_PASSWORD; | ||
39 | + if(!specific_login || our_login) | ||
40 | + found |= FOUND_PASSWORD; | ||
41 | keyword = NONE; | ||
42 | } | ||
43 | else if(strcasecompare("login", tok)) | ||
44 | @@ -237,6 +238,10 @@ static int parsenetrc(const char *host, | ||
45 | keyword = PASSWORD; | ||
46 | else if(strcasecompare("machine", tok)) { | ||
47 | /* a new machine here */ | ||
48 | + if(found & FOUND_PASSWORD) { | ||
49 | + done = TRUE; | ||
50 | + break; | ||
51 | + } | ||
52 | state = HOSTFOUND; | ||
53 | keyword = NONE; | ||
54 | found = 0; | ||
55 | diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc | ||
56 | index e3508cb..dc2af79 100644 | ||
57 | --- a/tests/data/Makefile.inc | ||
58 | +++ b/tests/data/Makefile.inc | ||
59 | @@ -230,7 +230,7 @@ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \ | ||
60 | test1955 test1956 test1957 test1958 test1959 test1960 test1964 \ | ||
61 | test1970 test1971 test1972 test1973 test1974 test1975 \ | ||
62 | \ | ||
63 | -test2000 test2001 test2002 test2003 test2004 \ | ||
64 | +test2000 test2001 test2002 test2003 test2004 test2005 \ | ||
65 | \ | ||
66 | test2023 \ | ||
67 | test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \ | ||
68 | diff --git a/tests/data/test2005 b/tests/data/test2005 | ||
69 | new file mode 100644 | ||
70 | index 0000000..66afe84 | ||
71 | --- /dev/null | ||
72 | +++ b/tests/data/test2005 | ||
73 | @@ -0,0 +1,55 @@ | ||
74 | +<testcase> | ||
75 | + <info> | ||
76 | + <keywords> | ||
77 | + HTTP | ||
78 | + netrc | ||
79 | + </keywords> | ||
80 | + </info> | ||
81 | + # | ||
82 | + # Server-side | ||
83 | + <reply> | ||
84 | + <data> | ||
85 | + HTTP/1.1 200 OK | ||
86 | + Date: Fri, 05 Aug 2022 10:09:00 GMT | ||
87 | + Server: test-server/fake | ||
88 | + Content-Type: text/plain | ||
89 | + Content-Length: 6 | ||
90 | + Connection: close | ||
91 | + | ||
92 | + -foo- | ||
93 | + </data> | ||
94 | + </reply> | ||
95 | + | ||
96 | + # | ||
97 | + # Client-side | ||
98 | + <client> | ||
99 | + <server> | ||
100 | + http | ||
101 | + </server> | ||
102 | + <name> | ||
103 | + netrc match with password only in file, no username. machine follows | ||
104 | + </name> | ||
105 | + <command> | ||
106 | + --netrc-optional --netrc-file log/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/ | ||
107 | + </command> | ||
108 | + <file name="log/netrc%TESTNUMBER" > | ||
109 | + machine %HOSTIP | ||
110 | + password 5up3r53cr37 | ||
111 | + | ||
112 | + machine example.com | ||
113 | + </file> | ||
114 | + </client> | ||
115 | + | ||
116 | + # | ||
117 | + # Verify data after the test has been "shot" | ||
118 | + <verify> | ||
119 | + <protocol> | ||
120 | + GET / HTTP/1.1 | ||
121 | + Host: %HOSTIP:%HTTPPORT | ||
122 | + Authorization: Basic %b64[:5up3r53cr37]b64% | ||
123 | + User-Agent: curl/%VERSION | ||
124 | + Accept: */* | ||
125 | + | ||
126 | + </protocol> | ||
127 | + </verify> | ||
128 | + </testcase> | ||
129 | -- | ||
130 | 2.40.0 | ||
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb index ddd591dd96..6d6563591c 100644 --- a/meta/recipes-support/curl/curl_8.7.1.bb +++ b/meta/recipes-support/curl/curl_8.7.1.bb | |||
@@ -20,6 +20,9 @@ SRC_URI = " \ | |||
20 | file://CVE-2024-7264-2.patch \ | 20 | file://CVE-2024-7264-2.patch \ |
21 | file://CVE-2024-8096.patch \ | 21 | file://CVE-2024-8096.patch \ |
22 | file://CVE-2024-9681.patch \ | 22 | file://CVE-2024-9681.patch \ |
23 | file://CVE-2024-11053-0001.patch \ | ||
24 | file://CVE-2024-11053-0002.patch \ | ||
25 | file://CVE-2024-11053-0003.patch \ | ||
23 | " | 26 | " |
24 | SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd" | 27 | SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd" |
25 | 28 | ||