summaryrefslogtreecommitdiffstats
path: root/meta/recipes-support/curl/curl
diff options
context:
space:
mode:
authorLee Chee Yang <chee.yang.lee@intel.com>2021-01-13 17:29:35 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-01-21 23:08:16 +0000
commitd5a1834e4fb666dd2348b7dca59ab3052d25468d (patch)
tree1e75ba5a4d4c21fec0773bf7f1fa3a09dca0911d /meta/recipes-support/curl/curl
parent6b78a1734318fce8ee13c28c1454d3d76f52bae8 (diff)
downloadpoky-d5a1834e4fb666dd2348b7dca59ab3052d25468d.tar.gz
curl: fix CVE-2020-8231/8284/8285/8286
backport CVE-2020-8284 fixes from upstream, but drop binary file tests/data/test1465. upstream fixes for CVE-2020-8231, CVE-2020-8285 and CVE-2020-8286 does not applies cleanly to 7.69.1, fedora have working patch hence import patch from Fedora. https://koji.fedoraproject.org/koji/rpminfo?rpmID=24270817 (From OE-Core rev: 16ec5dea53d24cc1449d173912c1056c873fa98d) Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com> Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-support/curl/curl')
-rw-r--r--meta/recipes-support/curl/curl/CVE-2020-8231.patch1092
-rw-r--r--meta/recipes-support/curl/curl/CVE-2020-8284.patch209
-rw-r--r--meta/recipes-support/curl/curl/CVE-2020-8285.patch260
-rw-r--r--meta/recipes-support/curl/curl/CVE-2020-8286.patch133
4 files changed, 1694 insertions, 0 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8231.patch b/meta/recipes-support/curl/curl/CVE-2020-8231.patch
new file mode 100644
index 0000000000..51f40047f1
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2020-8231.patch
@@ -0,0 +1,1092 @@
1From c3359693e17fccdf2a04f0b908bc8f51cdc38133 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Mon, 27 Apr 2020 00:33:21 +0200
4Subject: [PATCH 1/3] conncache: various concept cleanups
5
6More connection cache accesses are protected by locks.
7
8CONNCACHE_* is a beter prefix for the connection cache lock macros.
9
10Curl_attach_connnection: now called as soon as there's a connection
11struct available and before the connection is added to the connection
12cache.
13
14Curl_disconnect: now assumes that the connection is already removed from
15the connection cache.
16
17Ref: #4915
18Closes #5009
19
20Upstream-commit: c06902713998d68202c5a764de910ba8d0e8f54d
21Signed-off-by: Kamil Dudka <kdudka@redhat.com>
22
23Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0004-curl-7.69.1-CVE-2020-8231.patch ]
24CVE: CVE-2020-8286
25Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
26---
27 lib/conncache.c | 87 ++++++++++++++++++++-----------------------
28 lib/conncache.h | 9 ++---
29 lib/hostip.c | 12 +++---
30 lib/http_negotiate.h | 6 ++-
31 lib/http_ntlm.h | 6 ++-
32 lib/multi.c | 56 ++++++++++++++--------------
33 lib/multiif.h | 1 +
34 lib/url.c | 69 ++++++++++++++++++----------------
35 tests/data/test1554 | 14 +++++++
36 tests/unit/unit1620.c | 6 +--
37 10 files changed, 139 insertions(+), 127 deletions(-)
38
39diff --git a/lib/conncache.c b/lib/conncache.c
40index cbd3bb1..95fcea6 100644
41--- a/lib/conncache.c
42+++ b/lib/conncache.c
43@@ -49,53 +49,51 @@ static void conn_llist_dtor(void *user, void *element)
44 conn->bundle = NULL;
45 }
46
47-static CURLcode bundle_create(struct Curl_easy *data,
48- struct connectbundle **cb_ptr)
49+static CURLcode bundle_create(struct connectbundle **bundlep)
50 {
51- (void)data;
52- DEBUGASSERT(*cb_ptr == NULL);
53- *cb_ptr = malloc(sizeof(struct connectbundle));
54- if(!*cb_ptr)
55+ DEBUGASSERT(*bundlep == NULL);
56+ *bundlep = malloc(sizeof(struct connectbundle));
57+ if(!*bundlep)
58 return CURLE_OUT_OF_MEMORY;
59
60- (*cb_ptr)->num_connections = 0;
61- (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
62+ (*bundlep)->num_connections = 0;
63+ (*bundlep)->multiuse = BUNDLE_UNKNOWN;
64
65- Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor);
66+ Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor);
67 return CURLE_OK;
68 }
69
70-static void bundle_destroy(struct connectbundle *cb_ptr)
71+static void bundle_destroy(struct connectbundle *bundle)
72 {
73- if(!cb_ptr)
74+ if(!bundle)
75 return;
76
77- Curl_llist_destroy(&cb_ptr->conn_list, NULL);
78+ Curl_llist_destroy(&bundle->conn_list, NULL);
79
80- free(cb_ptr);
81+ free(bundle);
82 }
83
84 /* Add a connection to a bundle */
85-static void bundle_add_conn(struct connectbundle *cb_ptr,
86+static void bundle_add_conn(struct connectbundle *bundle,
87 struct connectdata *conn)
88 {
89- Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
90+ Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn,
91 &conn->bundle_node);
92- conn->bundle = cb_ptr;
93- cb_ptr->num_connections++;
94+ conn->bundle = bundle;
95+ bundle->num_connections++;
96 }
97
98 /* Remove a connection from a bundle */
99-static int bundle_remove_conn(struct connectbundle *cb_ptr,
100+static int bundle_remove_conn(struct connectbundle *bundle,
101 struct connectdata *conn)
102 {
103 struct curl_llist_element *curr;
104
105- curr = cb_ptr->conn_list.head;
106+ curr = bundle->conn_list.head;
107 while(curr) {
108 if(curr->ptr == conn) {
109- Curl_llist_remove(&cb_ptr->conn_list, curr, NULL);
110- cb_ptr->num_connections--;
111+ Curl_llist_remove(&bundle->conn_list, curr, NULL);
112+ bundle->num_connections--;
113 conn->bundle = NULL;
114 return 1; /* we removed a handle */
115 }
116@@ -162,20 +160,15 @@ static void hashkey(struct connectdata *conn, char *buf,
117 msnprintf(buf, len, "%ld%s", port, hostname);
118 }
119
120-void Curl_conncache_unlock(struct Curl_easy *data)
121-{
122- CONN_UNLOCK(data);
123-}
124-
125 /* Returns number of connections currently held in the connection cache.
126 Locks/unlocks the cache itself!
127 */
128 size_t Curl_conncache_size(struct Curl_easy *data)
129 {
130 size_t num;
131- CONN_LOCK(data);
132+ CONNCACHE_LOCK(data);
133 num = data->state.conn_cache->num_conn;
134- CONN_UNLOCK(data);
135+ CONNCACHE_UNLOCK(data);
136 return num;
137 }
138
139@@ -188,7 +181,7 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
140 const char **hostp)
141 {
142 struct connectbundle *bundle = NULL;
143- CONN_LOCK(conn->data);
144+ CONNCACHE_LOCK(conn->data);
145 if(connc) {
146 char key[HASHKEY_SIZE];
147 hashkey(conn, key, sizeof(key), hostp);
148@@ -235,8 +228,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
149 struct connectdata *conn)
150 {
151 CURLcode result = CURLE_OK;
152- struct connectbundle *bundle;
153- struct connectbundle *new_bundle = NULL;
154+ struct connectbundle *bundle = NULL;
155 struct Curl_easy *data = conn->data;
156
157 /* *find_bundle() locks the connection cache */
158@@ -245,20 +237,19 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
159 int rc;
160 char key[HASHKEY_SIZE];
161
162- result = bundle_create(data, &new_bundle);
163+ result = bundle_create(&bundle);
164 if(result) {
165 goto unlock;
166 }
167
168 hashkey(conn, key, sizeof(key), NULL);
169- rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
170+ rc = conncache_add_bundle(data->state.conn_cache, key, bundle);
171
172 if(!rc) {
173- bundle_destroy(new_bundle);
174+ bundle_destroy(bundle);
175 result = CURLE_OUT_OF_MEMORY;
176 goto unlock;
177 }
178- bundle = new_bundle;
179 }
180
181 bundle_add_conn(bundle, conn);
182@@ -270,15 +261,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
183 conn->connection_id, connc->num_conn));
184
185 unlock:
186- CONN_UNLOCK(data);
187+ CONNCACHE_UNLOCK(data);
188
189 return result;
190 }
191
192 /*
193- * Removes the connectdata object from the connection cache *and* clears the
194- * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument
195- * depending on if the parent function already holds the lock or not.
196+ * Removes the connectdata object from the connection cache, but does *not*
197+ * clear the conn->data association. The transfer still owns this connection.
198+ *
199+ * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
200+ * already holds the lock or not.
201 */
202 void Curl_conncache_remove_conn(struct Curl_easy *data,
203 struct connectdata *conn, bool lock)
204@@ -290,7 +283,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
205 due to a failed connection attempt, before being added to a bundle */
206 if(bundle) {
207 if(lock) {
208- CONN_LOCK(data);
209+ CONNCACHE_LOCK(data);
210 }
211 bundle_remove_conn(bundle, conn);
212 if(bundle->num_connections == 0)
213@@ -301,9 +294,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
214 DEBUGF(infof(data, "The cache now contains %zu members\n",
215 connc->num_conn));
216 }
217- conn->data = NULL; /* clear the association */
218 if(lock) {
219- CONN_UNLOCK(data);
220+ CONNCACHE_UNLOCK(data);
221 }
222 }
223 }
224@@ -332,7 +324,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
225 if(!connc)
226 return FALSE;
227
228- CONN_LOCK(data);
229+ CONNCACHE_LOCK(data);
230 Curl_hash_start_iterate(&connc->hash, &iter);
231
232 he = Curl_hash_next_element(&iter);
233@@ -350,12 +342,12 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
234 curr = curr->next;
235
236 if(1 == func(conn, param)) {
237- CONN_UNLOCK(data);
238+ CONNCACHE_UNLOCK(data);
239 return TRUE;
240 }
241 }
242 }
243- CONN_UNLOCK(data);
244+ CONNCACHE_UNLOCK(data);
245 return FALSE;
246 }
247
248@@ -494,7 +486,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
249
250 now = Curl_now();
251
252- CONN_LOCK(data);
253+ CONNCACHE_LOCK(data);
254 Curl_hash_start_iterate(&connc->hash, &iter);
255
256 he = Curl_hash_next_element(&iter);
257@@ -531,7 +523,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
258 connc->num_conn));
259 conn_candidate->data = data; /* associate! */
260 }
261- CONN_UNLOCK(data);
262+ CONNCACHE_UNLOCK(data);
263
264 return conn_candidate;
265 }
266@@ -548,6 +540,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
267 sigpipe_ignore(conn->data, &pipe_st);
268 /* This will remove the connection from the cache */
269 connclose(conn, "kill all");
270+ Curl_conncache_remove_conn(conn->data, conn, TRUE);
271 (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
272 sigpipe_restore(&pipe_st);
273
274diff --git a/lib/conncache.h b/lib/conncache.h
275index e3e4c9c..3dda21c 100644
276--- a/lib/conncache.h
277+++ b/lib/conncache.h
278@@ -45,21 +45,21 @@ struct conncache {
279 #ifdef CURLDEBUG
280 /* the debug versions of these macros make extra certain that the lock is
281 never doubly locked or unlocked */
282-#define CONN_LOCK(x) if((x)->share) { \
283+#define CONNCACHE_LOCK(x) if((x)->share) { \
284 Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
285 DEBUGASSERT(!(x)->state.conncache_lock); \
286 (x)->state.conncache_lock = TRUE; \
287 }
288
289-#define CONN_UNLOCK(x) if((x)->share) { \
290+#define CONNCACHE_UNLOCK(x) if((x)->share) { \
291 DEBUGASSERT((x)->state.conncache_lock); \
292 (x)->state.conncache_lock = FALSE; \
293 Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
294 }
295 #else
296-#define CONN_LOCK(x) if((x)->share) \
297+#define CONNCACHE_LOCK(x) if((x)->share) \
298 Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
299-#define CONN_UNLOCK(x) if((x)->share) \
300+#define CONNCACHE_UNLOCK(x) if((x)->share) \
301 Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
302 #endif
303
304@@ -77,7 +77,6 @@ void Curl_conncache_destroy(struct conncache *connc);
305 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
306 struct conncache *connc,
307 const char **hostp);
308-void Curl_conncache_unlock(struct Curl_easy *data);
309 /* returns number of connections currently held in the connection cache */
310 size_t Curl_conncache_size(struct Curl_easy *data);
311
312diff --git a/lib/hostip.c b/lib/hostip.c
313index c0feb79..f5bb634 100644
314--- a/lib/hostip.c
315+++ b/lib/hostip.c
316@@ -1085,10 +1085,12 @@ CURLcode Curl_once_resolved(struct connectdata *conn,
317
318 result = Curl_setup_conn(conn, protocol_done);
319
320- if(result)
321- /* We're not allowed to return failure with memory left allocated
322- in the connectdata struct, free those here */
323- Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
324-
325+ if(result) {
326+ struct Curl_easy *data = conn->data;
327+ DEBUGASSERT(data);
328+ Curl_detach_connnection(data);
329+ Curl_conncache_remove_conn(data, conn, TRUE);
330+ Curl_disconnect(data, conn, TRUE);
331+ }
332 return result;
333 }
334diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h
335index 4f0ac16..a737f6f 100644
336--- a/lib/http_negotiate.h
337+++ b/lib/http_negotiate.h
338@@ -7,7 +7,7 @@
339 * | (__| |_| | _ <| |___
340 * \___|\___/|_| \_\_____|
341 *
342- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
343+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
344 *
345 * This software is licensed as described in the file COPYING, which
346 * you should have received as part of this distribution. The terms
347@@ -33,6 +33,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
348
349 void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
350
351-#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
352+#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */
353+#define Curl_http_auth_cleanup_negotiate(x)
354+#endif
355
356 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
357diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h
358index 003714d..3ebdf97 100644
359--- a/lib/http_ntlm.h
360+++ b/lib/http_ntlm.h
361@@ -7,7 +7,7 @@
362 * | (__| |_| | _ <| |___
363 * \___|\___/|_| \_\_____|
364 *
365- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
366+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
367 *
368 * This software is licensed as described in the file COPYING, which
369 * you should have received as part of this distribution. The terms
370@@ -35,6 +35,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
371
372 void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
373
374-#endif /* !CURL_DISABLE_HTTP && USE_NTLM */
375+#else /* !CURL_DISABLE_HTTP && USE_NTLM */
376+#define Curl_http_auth_cleanup_ntlm(x)
377+#endif
378
379 #endif /* HEADER_CURL_HTTP_NTLM_H */
380diff --git a/lib/multi.c b/lib/multi.c
381index e10e752..273653d 100644
382--- a/lib/multi.c
383+++ b/lib/multi.c
384@@ -79,7 +79,6 @@ static CURLMcode add_next_timeout(struct curltime now,
385 static CURLMcode multi_timeout(struct Curl_multi *multi,
386 long *timeout_ms);
387 static void process_pending_handles(struct Curl_multi *multi);
388-static void detach_connnection(struct Curl_easy *data);
389
390 #ifdef DEBUGBUILD
391 static const char * const statename[]={
392@@ -112,7 +111,7 @@ static void Curl_init_completed(struct Curl_easy *data)
393
394 /* Important: reset the conn pointer so that we don't point to memory
395 that could be freed anytime */
396- detach_connnection(data);
397+ Curl_detach_connnection(data);
398 Curl_expire_clear(data); /* stop all timers */
399 }
400
401@@ -506,6 +505,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
402 easy handle is added */
403 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
404
405+ CONNCACHE_LOCK(data);
406 /* The closure handle only ever has default timeouts set. To improve the
407 state somewhat we clone the timeouts from each added handle so that the
408 closure handle always has the same timeouts as the most recently added
409@@ -515,6 +515,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
410 data->set.server_response_timeout;
411 data->state.conn_cache->closure_handle->set.no_signal =
412 data->set.no_signal;
413+ CONNCACHE_UNLOCK(data);
414
415 Curl_update_timer(multi);
416 return CURLM_OK;
417@@ -589,14 +590,14 @@ static CURLcode multi_done(struct Curl_easy *data,
418
419 process_pending_handles(data->multi); /* connection / multiplex */
420
421- CONN_LOCK(data);
422- detach_connnection(data);
423+ CONNCACHE_LOCK(data);
424+ Curl_detach_connnection(data);
425 if(CONN_INUSE(conn)) {
426 /* Stop if still used. */
427 /* conn->data must not remain pointing to this transfer since it is going
428 away! Find another to own it! */
429 conn->data = conn->easyq.head->ptr;
430- CONN_UNLOCK(data);
431+ CONNCACHE_UNLOCK(data);
432 DEBUGF(infof(data, "Connection still in use %zu, "
433 "no more multi_done now!\n",
434 conn->easyq.size));
435@@ -647,7 +648,8 @@ static CURLcode multi_done(struct Curl_easy *data,
436 || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
437 CURLcode res2;
438 connclose(conn, "disconnecting");
439- CONN_UNLOCK(data);
440+ Curl_conncache_remove_conn(data, conn, FALSE);
441+ CONNCACHE_UNLOCK(data);
442 res2 = Curl_disconnect(data, conn, premature);
443
444 /* If we had an error already, make sure we return that one. But
445@@ -666,7 +668,7 @@ static CURLcode multi_done(struct Curl_easy *data,
446 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
447 conn->host.dispname);
448 /* the connection is no longer in use by this transfer */
449- CONN_UNLOCK(data);
450+ CONNCACHE_UNLOCK(data);
451 if(Curl_conncache_return_conn(data, conn)) {
452 /* remember the most recently used connection */
453 data->state.lastconnect = conn;
454@@ -774,8 +776,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
455 vanish with this handle */
456
457 /* Remove the association between the connection and the handle */
458- if(data->conn)
459- detach_connnection(data);
460+ Curl_detach_connnection(data);
461
462 #ifdef USE_LIBPSL
463 /* Remove the PSL association. */
464@@ -824,9 +825,13 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi)
465 return (multi && (multi->multiplexing));
466 }
467
468-/* This is the only function that should clear data->conn. This will
469- occasionally be called with the pointer already cleared. */
470-static void detach_connnection(struct Curl_easy *data)
471+/*
472+ * Curl_detach_connnection() removes the given transfer from the connection.
473+ *
474+ * This is the only function that should clear data->conn. This will
475+ * occasionally be called with the data->conn pointer already cleared.
476+ */
477+void Curl_detach_connnection(struct Curl_easy *data)
478 {
479 struct connectdata *conn = data->conn;
480 if(conn)
481@@ -834,7 +839,11 @@ static void detach_connnection(struct Curl_easy *data)
482 data->conn = NULL;
483 }
484
485-/* This is the only function that should assign data->conn */
486+/*
487+ * Curl_attach_connnection() attaches this transfer to this connection.
488+ *
489+ * This is the only function that should assign data->conn
490+ */
491 void Curl_attach_connnection(struct Curl_easy *data,
492 struct connectdata *conn)
493 {
494@@ -1536,19 +1545,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
495 bool stream_error = FALSE;
496 rc = CURLM_OK;
497
498- DEBUGASSERT((data->mstate <= CURLM_STATE_CONNECT) ||
499- (data->mstate >= CURLM_STATE_DONE) ||
500- data->conn);
501- if(!data->conn &&
502- data->mstate > CURLM_STATE_CONNECT &&
503- data->mstate < CURLM_STATE_DONE) {
504- /* In all these states, the code will blindly access 'data->conn'
505- so this is precaution that it isn't NULL. And it silences static
506- analyzers. */
507- failf(data, "In state %d with no conn, bail out!\n", data->mstate);
508- return CURLM_INTERNAL_ERROR;
509- }
510-
511 if(multi_ischanged(multi, TRUE)) {
512 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
513 process_pending_handles(multi); /* multiplexed */
514@@ -2231,8 +2227,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
515 * access free'd data, if the connection is free'd and the handle
516 * removed before we perform the processing in CURLM_STATE_COMPLETED
517 */
518- if(data->conn)
519- detach_connnection(data);
520+ Curl_detach_connnection(data);
521 }
522
523 #ifndef CURL_DISABLE_FTP
524@@ -2284,7 +2279,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
525 /* This is where we make sure that the conn pointer is reset.
526 We don't have to do this in every case block above where a
527 failure is detected */
528- detach_connnection(data);
529+ Curl_detach_connnection(data);
530+
531+ /* remove connection from cache */
532+ Curl_conncache_remove_conn(data, conn, TRUE);
533
534 /* disconnect properly */
535 Curl_disconnect(data, conn, dead_connection);
536diff --git a/lib/multiif.h b/lib/multiif.h
537index bde755e..c07587b 100644
538--- a/lib/multiif.h
539+++ b/lib/multiif.h
540@@ -33,6 +33,7 @@ void Curl_expire_done(struct Curl_easy *data, expire_id id);
541 void Curl_update_timer(struct Curl_multi *multi);
542 void Curl_attach_connnection(struct Curl_easy *data,
543 struct connectdata *conn);
544+void Curl_detach_connnection(struct Curl_easy *data);
545 bool Curl_multiplex_wanted(const struct Curl_multi *multi);
546 void Curl_set_in_callback(struct Curl_easy *data, bool value);
547 bool Curl_is_in_callback(struct Curl_easy *easy);
548diff --git a/lib/url.c b/lib/url.c
549index a826f8a..4ed0623 100644
550--- a/lib/url.c
551+++ b/lib/url.c
552@@ -679,9 +679,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
553
554 static void conn_shutdown(struct connectdata *conn)
555 {
556- if(!conn)
557- return;
558-
559+ DEBUGASSERT(conn);
560 infof(conn->data, "Closing connection %ld\n", conn->connection_id);
561 DEBUGASSERT(conn->data);
562
563@@ -702,16 +700,11 @@ static void conn_shutdown(struct connectdata *conn)
564 Curl_closesocket(conn, conn->tempsock[0]);
565 if(CURL_SOCKET_BAD != conn->tempsock[1])
566 Curl_closesocket(conn, conn->tempsock[1]);
567-
568- /* unlink ourselves. this should be called last since other shutdown
569- procedures need a valid conn->data and this may clear it. */
570- Curl_conncache_remove_conn(conn->data, conn, TRUE);
571 }
572
573 static void conn_free(struct connectdata *conn)
574 {
575- if(!conn)
576- return;
577+ DEBUGASSERT(conn);
578
579 Curl_free_idnconverted_hostname(&conn->host);
580 Curl_free_idnconverted_hostname(&conn->conn_to_host);
581@@ -778,13 +771,17 @@ static void conn_free(struct connectdata *conn)
582 CURLcode Curl_disconnect(struct Curl_easy *data,
583 struct connectdata *conn, bool dead_connection)
584 {
585- if(!conn)
586- return CURLE_OK; /* this is closed and fine already */
587+ /* there must be a connection to close */
588+ DEBUGASSERT(conn);
589
590- if(!data) {
591- DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
592- return CURLE_OK;
593- }
594+ /* it must be removed from the connection cache */
595+ DEBUGASSERT(!conn->bundle);
596+
597+ /* there must be an associated transfer */
598+ DEBUGASSERT(data);
599+
600+ /* the transfer must be detached from the connection */
601+ DEBUGASSERT(!data->conn);
602
603 /*
604 * If this connection isn't marked to force-close, leave it open if there
605@@ -800,16 +797,11 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
606 conn->dns_entry = NULL;
607 }
608
609- Curl_hostcache_prune(data); /* kill old DNS cache entries */
610-
611-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
612 /* Cleanup NTLM connection-related data */
613 Curl_http_auth_cleanup_ntlm(conn);
614-#endif
615-#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
616+
617 /* Cleanup NEGOTIATE connection-related data */
618 Curl_http_auth_cleanup_negotiate(conn);
619-#endif
620
621 /* the protocol specific disconnect handler and conn_shutdown need a transfer
622 for the connection! */
623@@ -1006,8 +998,12 @@ static int call_extract_if_dead(struct connectdata *conn, void *param)
624 static void prune_dead_connections(struct Curl_easy *data)
625 {
626 struct curltime now = Curl_now();
627- timediff_t elapsed =
628+ timediff_t elapsed;
629+
630+ CONNCACHE_LOCK(data);
631+ elapsed =
632 Curl_timediff(now, data->state.conn_cache->last_cleanup);
633+ CONNCACHE_UNLOCK(data);
634
635 if(elapsed >= 1000L) {
636 struct prunedead prune;
637@@ -1015,10 +1011,17 @@ static void prune_dead_connections(struct Curl_easy *data)
638 prune.extracted = NULL;
639 while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
640 call_extract_if_dead)) {
641+ /* unlocked */
642+
643+ /* remove connection from cache */
644+ Curl_conncache_remove_conn(data, prune.extracted, TRUE);
645+
646 /* disconnect it */
647 (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
648 }
649+ CONNCACHE_LOCK(data);
650 data->state.conn_cache->last_cleanup = now;
651+ CONNCACHE_UNLOCK(data);
652 }
653 }
654
655@@ -1078,7 +1081,7 @@ ConnectionExists(struct Curl_easy *data,
656 if(data->set.pipewait) {
657 infof(data, "Server doesn't support multiplex yet, wait\n");
658 *waitpipe = TRUE;
659- Curl_conncache_unlock(data);
660+ CONNCACHE_UNLOCK(data);
661 return FALSE; /* no re-use */
662 }
663
664@@ -1402,11 +1405,12 @@ ConnectionExists(struct Curl_easy *data,
665 if(chosen) {
666 /* mark it as used before releasing the lock */
667 chosen->data = data; /* own it! */
668- Curl_conncache_unlock(data);
669+ Curl_attach_connnection(data, chosen);
670+ CONNCACHE_UNLOCK(data);
671 *usethis = chosen;
672 return TRUE; /* yes, we found one to use! */
673 }
674- Curl_conncache_unlock(data);
675+ CONNCACHE_UNLOCK(data);
676
677 if(foundPendingCandidate && data->set.pipewait) {
678 infof(data,
679@@ -3519,6 +3523,7 @@ static CURLcode create_conn(struct Curl_easy *data,
680 if(!result) {
681 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
682
683+ Curl_attach_connnection(data, conn);
684 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
685 if(result)
686 goto out;
687@@ -3533,7 +3538,6 @@ static CURLcode create_conn(struct Curl_easy *data,
688 (void)conn->handler->done(conn, result, FALSE);
689 goto out;
690 }
691- Curl_attach_connnection(data, conn);
692 Curl_setup_transfer(data, -1, -1, FALSE, -1);
693 }
694
695@@ -3683,7 +3687,7 @@ static CURLcode create_conn(struct Curl_easy *data,
696
697 /* The bundle is full. Extract the oldest connection. */
698 conn_candidate = Curl_conncache_extract_bundle(data, bundle);
699- Curl_conncache_unlock(data);
700+ CONNCACHE_UNLOCK(data);
701
702 if(conn_candidate)
703 (void)Curl_disconnect(data, conn_candidate,
704@@ -3695,7 +3699,7 @@ static CURLcode create_conn(struct Curl_easy *data,
705 }
706 }
707 else
708- Curl_conncache_unlock(data);
709+ CONNCACHE_UNLOCK(data);
710
711 }
712
713@@ -3729,6 +3733,8 @@ static CURLcode create_conn(struct Curl_easy *data,
714 * This is a brand new connection, so let's store it in the connection
715 * cache of ours!
716 */
717+ Curl_attach_connnection(data, conn);
718+
719 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
720 if(result)
721 goto out;
722@@ -3883,7 +3889,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
723 result = create_conn(data, &conn, asyncp);
724
725 if(!result) {
726- if(CONN_INUSE(conn))
727+ if(CONN_INUSE(conn) > 1)
728 /* multiplexed */
729 *protocol_done = TRUE;
730 else if(!*asyncp) {
731@@ -3900,11 +3906,10 @@ CURLcode Curl_connect(struct Curl_easy *data,
732 else if(result && conn) {
733 /* We're not allowed to return failure with memory left allocated in the
734 connectdata struct, free those here */
735+ Curl_detach_connnection(data);
736+ Curl_conncache_remove_conn(data, conn, TRUE);
737 Curl_disconnect(data, conn, TRUE);
738 }
739- else if(!result && !data->conn)
740- /* FILE: transfers already have the connection attached */
741- Curl_attach_connnection(data, conn);
742
743 return result;
744 }
745diff --git a/tests/data/test1554 b/tests/data/test1554
746index 06f1897..d3926d9 100644
747--- a/tests/data/test1554
748+++ b/tests/data/test1554
749@@ -29,6 +29,12 @@ run 1: foobar and so on fun!
750 <- Mutex unlock
751 -> Mutex lock
752 <- Mutex unlock
753+-> Mutex lock
754+<- Mutex unlock
755+-> Mutex lock
756+<- Mutex unlock
757+-> Mutex lock
758+<- Mutex unlock
759 run 1: foobar and so on fun!
760 -> Mutex lock
761 <- Mutex unlock
762@@ -40,6 +46,10 @@ run 1: foobar and so on fun!
763 <- Mutex unlock
764 -> Mutex lock
765 <- Mutex unlock
766+-> Mutex lock
767+<- Mutex unlock
768+-> Mutex lock
769+<- Mutex unlock
770 run 1: foobar and so on fun!
771 -> Mutex lock
772 <- Mutex unlock
773@@ -51,6 +61,10 @@ run 1: foobar and so on fun!
774 <- Mutex unlock
775 -> Mutex lock
776 <- Mutex unlock
777+-> Mutex lock
778+<- Mutex unlock
779+-> Mutex lock
780+<- Mutex unlock
781 run 1: foobar and so on fun!
782 -> Mutex lock
783 <- Mutex unlock
784diff --git a/tests/unit/unit1620.c b/tests/unit/unit1620.c
785index 6e572c6..b23e5b9 100644
786--- a/tests/unit/unit1620.c
787+++ b/tests/unit/unit1620.c
788@@ -5,7 +5,7 @@
789 * | (__| |_| | _ <| |___
790 * \___|\___/|_| \_\_____|
791 *
792- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
793+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
794 *
795 * This software is licensed as described in the file COPYING, which
796 * you should have received as part of this distribution. The terms
797@@ -73,10 +73,6 @@ UNITTEST_START
798 fail_unless(rc == CURLE_OK,
799 "Curl_parse_login_details() failed");
800
801- rc = Curl_disconnect(empty, empty->conn, FALSE);
802- fail_unless(rc == CURLE_OK,
803- "Curl_disconnect() with dead_connection set FALSE failed");
804-
805 Curl_freeset(empty);
806 for(i = (enum dupstring)0; i < STRING_LAST; i++) {
807 fail_unless(empty->set.str[i] == NULL,
808--
8092.25.4
810
811
812From 6830828c9eecd9ab14404f2f49f19b56dec62130 Mon Sep 17 00:00:00 2001
813From: Marc Aldorasi <marc@groundctl.com>
814Date: Thu, 30 Jul 2020 14:16:17 -0400
815Subject: [PATCH 2/3] multi_remove_handle: close unused connect-only
816 connections
817
818Previously any connect-only connections in a multi handle would be kept
819alive until the multi handle was closed. Since these connections cannot
820be re-used, they can be marked for closure when the associated easy
821handle is removed from the multi handle.
822
823Closes #5749
824
825Upstream-commit: d5bb459ccf1fc5980ae4b95c05b4ecf6454a7599
826Signed-off-by: Kamil Dudka <kdudka@redhat.com>
827---
828 lib/multi.c | 34 ++++++++++++++++++++++++++++++----
829 tests/data/test1554 | 6 ++++++
830 2 files changed, 36 insertions(+), 4 deletions(-)
831
832diff --git a/lib/multi.c b/lib/multi.c
833index 249e360..f1371bd 100644
834--- a/lib/multi.c
835+++ b/lib/multi.c
836@@ -682,6 +682,26 @@ static CURLcode multi_done(struct Curl_easy *data,
837 return result;
838 }
839
840+static int close_connect_only(struct connectdata *conn, void *param)
841+{
842+ struct Curl_easy *data = param;
843+
844+ if(data->state.lastconnect != conn)
845+ return 0;
846+
847+ if(conn->data != data)
848+ return 1;
849+ conn->data = NULL;
850+
851+ if(!conn->bits.connect_only)
852+ return 1;
853+
854+ connclose(conn, "Removing connect-only easy handle");
855+ conn->bits.connect_only = FALSE;
856+
857+ return 1;
858+}
859+
860 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
861 struct Curl_easy *data)
862 {
863@@ -765,10 +785,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
864 multi_done() as that may actually call Curl_expire that uses this */
865 Curl_llist_destroy(&data->state.timeoutlist, NULL);
866
867- /* as this was using a shared connection cache we clear the pointer to that
868- since we're not part of that multi handle anymore */
869- data->state.conn_cache = NULL;
870-
871 /* change state without using multistate(), only to make singlesocket() do
872 what we want */
873 data->mstate = CURLM_STATE_COMPLETED;
874@@ -778,12 +794,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
875 /* Remove the association between the connection and the handle */
876 Curl_detach_connnection(data);
877
878+ if(data->state.lastconnect) {
879+ /* Mark any connect-only connection for closure */
880+ Curl_conncache_foreach(data, data->state.conn_cache,
881+ data, &close_connect_only);
882+ }
883+
884 #ifdef USE_LIBPSL
885 /* Remove the PSL association. */
886 if(data->psl == &multi->psl)
887 data->psl = NULL;
888 #endif
889
890+ /* as this was using a shared connection cache we clear the pointer to that
891+ since we're not part of that multi handle anymore */
892+ data->state.conn_cache = NULL;
893+
894 data->multi = NULL; /* clear the association to this multi handle */
895
896 /* make sure there's no pending message in the queue sent from this easy
897diff --git a/tests/data/test1554 b/tests/data/test1554
898index d3926d9..fffa6ad 100644
899--- a/tests/data/test1554
900+++ b/tests/data/test1554
901@@ -50,6 +50,8 @@ run 1: foobar and so on fun!
902 <- Mutex unlock
903 -> Mutex lock
904 <- Mutex unlock
905+-> Mutex lock
906+<- Mutex unlock
907 run 1: foobar and so on fun!
908 -> Mutex lock
909 <- Mutex unlock
910@@ -65,6 +67,8 @@ run 1: foobar and so on fun!
911 <- Mutex unlock
912 -> Mutex lock
913 <- Mutex unlock
914+-> Mutex lock
915+<- Mutex unlock
916 run 1: foobar and so on fun!
917 -> Mutex lock
918 <- Mutex unlock
919@@ -74,6 +78,8 @@ run 1: foobar and so on fun!
920 <- Mutex unlock
921 -> Mutex lock
922 <- Mutex unlock
923+-> Mutex lock
924+<- Mutex unlock
925 </datacheck>
926 </reply>
927
928--
9292.25.4
930
931
932From 01148ee40dd913a169435b0f9ea90e6393821e70 Mon Sep 17 00:00:00 2001
933From: Daniel Stenberg <daniel@haxx.se>
934Date: Sun, 16 Aug 2020 11:34:35 +0200
935Subject: [PATCH 3/3] Curl_easy: remember last connection by id, not by pointer
936
937CVE-2020-8231
938
939Bug: https://curl.haxx.se/docs/CVE-2020-8231.html
940
941Reported-by: Marc Aldorasi
942Closes #5824
943
944Upstream-commit: 3c9e021f86872baae412a427e807fbfa2f3e8a22
945Signed-off-by: Kamil Dudka <kdudka@redhat.com>
946---
947 lib/connect.c | 19 ++++++++++---------
948 lib/easy.c | 3 +--
949 lib/multi.c | 9 +++++----
950 lib/url.c | 2 +-
951 lib/urldata.h | 2 +-
952 5 files changed, 18 insertions(+), 17 deletions(-)
953
954diff --git a/lib/connect.c b/lib/connect.c
955index 29293f0..e1c5662 100644
956--- a/lib/connect.c
957+++ b/lib/connect.c
958@@ -1356,15 +1356,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
959 }
960
961 struct connfind {
962- struct connectdata *tofind;
963- bool found;
964+ long id_tofind;
965+ struct connectdata *found;
966 };
967
968 static int conn_is_conn(struct connectdata *conn, void *param)
969 {
970 struct connfind *f = (struct connfind *)param;
971- if(conn == f->tofind) {
972- f->found = TRUE;
973+ if(conn->connection_id == f->id_tofind) {
974+ f->found = conn;
975 return 1;
976 }
977 return 0;
978@@ -1386,21 +1386,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
979 * - that is associated with a multi handle, and whose connection
980 * was detached with CURLOPT_CONNECT_ONLY
981 */
982- if(data->state.lastconnect && (data->multi_easy || data->multi)) {
983- struct connectdata *c = data->state.lastconnect;
984+ if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
985+ struct connectdata *c;
986 struct connfind find;
987- find.tofind = data->state.lastconnect;
988- find.found = FALSE;
989+ find.id_tofind = data->state.lastconnect_id;
990+ find.found = NULL;
991
992 Curl_conncache_foreach(data, data->multi_easy?
993 &data->multi_easy->conn_cache:
994 &data->multi->conn_cache, &find, conn_is_conn);
995
996 if(!find.found) {
997- data->state.lastconnect = NULL;
998+ data->state.lastconnect_id = -1;
999 return CURL_SOCKET_BAD;
1000 }
1001
1002+ c = find.found;
1003 if(connp) {
1004 /* only store this if the caller cares for it */
1005 *connp = c;
1006diff --git a/lib/easy.c b/lib/easy.c
1007index 292cca7..a69eb9e 100644
1008--- a/lib/easy.c
1009+++ b/lib/easy.c
1010@@ -831,8 +831,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
1011
1012 /* the connection cache is setup on demand */
1013 outcurl->state.conn_cache = NULL;
1014-
1015- outcurl->state.lastconnect = NULL;
1016+ outcurl->state.lastconnect_id = -1;
1017
1018 outcurl->progress.flags = data->progress.flags;
1019 outcurl->progress.callback = data->progress.callback;
1020diff --git a/lib/multi.c b/lib/multi.c
1021index f1371bd..778c537 100644
1022--- a/lib/multi.c
1023+++ b/lib/multi.c
1024@@ -453,6 +453,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
1025 data->state.conn_cache = &data->share->conn_cache;
1026 else
1027 data->state.conn_cache = &multi->conn_cache;
1028+ data->state.lastconnect_id = -1;
1029
1030 #ifdef USE_LIBPSL
1031 /* Do the same for PSL. */
1032@@ -671,11 +672,11 @@ static CURLcode multi_done(struct Curl_easy *data,
1033 CONNCACHE_UNLOCK(data);
1034 if(Curl_conncache_return_conn(data, conn)) {
1035 /* remember the most recently used connection */
1036- data->state.lastconnect = conn;
1037+ data->state.lastconnect_id = conn->connection_id;
1038 infof(data, "%s\n", buffer);
1039 }
1040 else
1041- data->state.lastconnect = NULL;
1042+ data->state.lastconnect_id = -1;
1043 }
1044
1045 Curl_free_request_state(data);
1046@@ -686,7 +687,7 @@ static int close_connect_only(struct connectdata *conn, void *param)
1047 {
1048 struct Curl_easy *data = param;
1049
1050- if(data->state.lastconnect != conn)
1051+ if(data->state.lastconnect_id != conn->connection_id)
1052 return 0;
1053
1054 if(conn->data != data)
1055@@ -794,7 +795,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
1056 /* Remove the association between the connection and the handle */
1057 Curl_detach_connnection(data);
1058
1059- if(data->state.lastconnect) {
1060+ if(data->state.lastconnect_id != -1) {
1061 /* Mark any connect-only connection for closure */
1062 Curl_conncache_foreach(data, data->state.conn_cache,
1063 data, &close_connect_only);
1064diff --git a/lib/url.c b/lib/url.c
1065index a1a6b69..2919a3d 100644
1066--- a/lib/url.c
1067+++ b/lib/url.c
1068@@ -617,7 +617,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
1069 Curl_initinfo(data);
1070
1071 /* most recent connection is not yet defined */
1072- data->state.lastconnect = NULL;
1073+ data->state.lastconnect_id = -1;
1074
1075 data->progress.flags |= PGRS_HIDE;
1076 data->state.current_speed = -1; /* init to negative == impossible */
1077diff --git a/lib/urldata.h b/lib/urldata.h
1078index f80a02d..6d8eb69 100644
1079--- a/lib/urldata.h
1080+++ b/lib/urldata.h
1081@@ -1332,7 +1332,7 @@ struct UrlState {
1082 /* buffers to store authentication data in, as parsed from input options */
1083 struct curltime keeps_speed; /* for the progress meter really */
1084
1085- struct connectdata *lastconnect; /* The last connection, NULL if undefined */
1086+ long lastconnect_id; /* The last connection, -1 if undefined */
1087
1088 char *headerbuff; /* allocated buffer to store headers in */
1089 size_t headersize; /* size of the allocation */
1090--
10912.25.4
1092
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8284.patch b/meta/recipes-support/curl/curl/CVE-2020-8284.patch
new file mode 100644
index 0000000000..ed6e8049a6
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2020-8284.patch
@@ -0,0 +1,209 @@
1From ec9cc725d598ac77de7b6df8afeec292b3c8ad46 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Tue, 24 Nov 2020 14:56:57 +0100
4Subject: [PATCH] ftp: CURLOPT_FTP_SKIP_PASV_IP by default
5
6The command line tool also independently sets --ftp-skip-pasv-ip by
7default.
8
9Ten test cases updated to adapt the modified --libcurl output.
10
11Bug: https://curl.se/docs/CVE-2020-8284.html
12CVE-2020-8284
13
14Reported-by: Varnavas Papaioannou
15
16Upstream-Status: Backport [https://github.com/curl/curl/commit/ec9cc725d598ac]
17CVE: CVE-2020-8284
18Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
19
20---
21 docs/cmdline-opts/ftp-skip-pasv-ip.d | 2 ++
22 docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | 8 +++++---
23 lib/url.c | 1 +
24 src/tool_cfgable.c | 1 +
25 tests/data/test1400 | 1 +
26 tests/data/test1401 | 1 +
27 tests/data/test1402 | 1 +
28 tests/data/test1403 | 1 +
29 tests/data/test1404 | 1 +
30 tests/data/test1405 | 1 +
31 tests/data/test1406 | 1 +
32 tests/data/test1407 | 1 +
33 tests/data/test1420 | 1 +
34 14 files changed, 18 insertions(+), 3 deletions(-)
35
36diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d
37index d6fd4589b1e..bcf4e7e62f2 100644
38--- a/docs/cmdline-opts/ftp-skip-pasv-ip.d
39+++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d
40@@ -10,4 +10,6 @@ to curl's PASV command when curl connects the data connection. Instead curl
41 will re-use the same IP address it already uses for the control
42 connection.
43
44+Since curl 7.74.0 this option is enabled by default.
45+
46 This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
47diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
48index d6217d0d8ca..fa87ddce769 100644
49--- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
50+++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
51@@ -5,7 +5,7 @@
52 .\" * | (__| |_| | _ <| |___
53 .\" * \___|\___/|_| \_\_____|
54 .\" *
55-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
56+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
57 .\" *
58 .\" * This software is licensed as described in the file COPYING, which
59 .\" * you should have received as part of this distribution. The terms
60@@ -35,11 +35,13 @@ address it already uses for the control connection. But it will use the port
61 number from the 227-response.
62
63 This option thus allows libcurl to work around broken server installations
64-that due to NATs, firewalls or incompetence report the wrong IP address back.
65+that due to NATs, firewalls or incompetence report the wrong IP address
66+back. Setting the option also reduces the risk for various sorts of client
67+abuse by malicious servers.
68
69 This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
70 .SH DEFAULT
71-0
72+1 since 7.74.0, was 0 before then.
73 .SH PROTOCOLS
74 FTP
75 .SH EXAMPLE
76diff --git a/lib/url.c b/lib/url.c
77index f8b2a0030de..2b0ba87ba87 100644
78--- a/lib/url.c
79+++ b/lib/url.c
80@@ -497,6 +497,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
81 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
82 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
83 set->ftp_filemethod = FTPFILE_MULTICWD;
84+ set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
85 #endif
86 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
87
88diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
89index c52d8e1c6bb..4c06d3557b7 100644
90--- a/src/tool_cfgable.c
91+++ b/src/tool_cfgable.c
92@@ -44,6 +44,7 @@ void config_init(struct OperationConfig *config)
93 config->tcp_nodelay = TRUE; /* enabled by default */
94 config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
95 config->http09_allowed = FALSE;
96+ config->ftp_skip_ip = TRUE;
97 }
98
99 static void free_config_fields(struct OperationConfig *config)
100diff --git a/tests/data/test1400 b/tests/data/test1400
101index 812ad0b88d9..b7060eca58e 100644
102--- a/tests/data/test1400
103+++ b/tests/data/test1400
104@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
105 curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
106 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
107 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
108+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
109 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
110
111 /* Here is a list of options the curl code used that cannot get generated
112diff --git a/tests/data/test1401 b/tests/data/test1401
113index f93b3d637de..a2629683aff 100644
114--- a/tests/data/test1401
115+++ b/tests/data/test1401
116@@ -87,6 +87,7 @@ int main(int argc, char *argv[])
117 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
118 curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
119 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
120+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
121 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
122 curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
123 (long)CURLPROTO_FTP |
124diff --git a/tests/data/test1402 b/tests/data/test1402
125index 7593c516da1..1bd55cb4e3b 100644
126--- a/tests/data/test1402
127+++ b/tests/data/test1402
128@@ -78,6 +78,7 @@ int main(int argc, char *argv[])
129 curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
130 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
131 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
132+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
133 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
134
135 /* Here is a list of options the curl code used that cannot get generated
136diff --git a/tests/data/test1403 b/tests/data/test1403
137index ecb4dd3dcab..a7c9fcca322 100644
138--- a/tests/data/test1403
139+++ b/tests/data/test1403
140@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
141 curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
142 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
143 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
144+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
145 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
146
147 /* Here is a list of options the curl code used that cannot get generated
148diff --git a/tests/data/test1404 b/tests/data/test1404
149index 97622b63948..1d8e8cf7779 100644
150--- a/tests/data/test1404
151+++ b/tests/data/test1404
152@@ -147,6 +147,7 @@ int main(int argc, char *argv[])
153 curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
154 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
155 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
156+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
157 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
158
159 /* Here is a list of options the curl code used that cannot get generated
160diff --git a/tests/data/test1405 b/tests/data/test1405
161index 2bac79eda74..b4087704f7b 100644
162--- a/tests/data/test1405
163+++ b/tests/data/test1405
164@@ -89,6 +89,7 @@ int main(int argc, char *argv[])
165 curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2);
166 curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3);
167 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
168+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
169 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
170
171 /* Here is a list of options the curl code used that cannot get generated
172diff --git a/tests/data/test1406 b/tests/data/test1406
173index 51a166adff2..38f68d11ee1 100644
174--- a/tests/data/test1406
175+++ b/tests/data/test1406
176@@ -79,6 +79,7 @@ int main(int argc, char *argv[])
177 curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406");
178 curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
179 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
180+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
181 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
182 curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com");
183 curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1);
184diff --git a/tests/data/test1407 b/tests/data/test1407
185index f6879008fb2..a7e13ba7585 100644
186--- a/tests/data/test1407
187+++ b/tests/data/test1407
188@@ -62,6 +62,7 @@ int main(int argc, char *argv[])
189 curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L);
190 curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
191 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
192+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
193 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
194
195 /* Here is a list of options the curl code used that cannot get generated
196diff --git a/tests/data/test1420 b/tests/data/test1420
197index 057ecc4773a..4b8d7bbf418 100644
198--- a/tests/data/test1420
199+++ b/tests/data/test1420
200@@ -67,6 +67,7 @@ int main(int argc, char *argv[])
201 curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;MAILINDEX=1");
202 curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
203 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
204+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
205 curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
206
207 /* Here is a list of options the curl code used that cannot get generated
208
209
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8285.patch b/meta/recipes-support/curl/curl/CVE-2020-8285.patch
new file mode 100644
index 0000000000..a66729b180
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2020-8285.patch
@@ -0,0 +1,260 @@
1From 6fda045b19a9066701b5e09cfa657a13a3accbf3 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Sat, 28 Nov 2020 00:27:21 +0100
4Subject: [PATCH] ftp: make wc_statemach loop instead of recurse
5
6CVE-2020-8285
7
8Fixes #6255
9Bug: https://curl.se/docs/CVE-2020-8285.html
10Reported-by: xnynx on github
11
12Upstream-commit: 69a358f2186e04cf44698b5100332cbf1ee7f01d
13Signed-off-by: Kamil Dudka <kdudka@redhat.com>
14
15Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0006-curl-7.69.1-CVE-2020-8285.patch]
16CVE: CVE-2020-8285
17Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
18---
19 lib/ftp.c | 202 +++++++++++++++++++++++++++---------------------------
20 1 file changed, 102 insertions(+), 100 deletions(-)
21
22diff --git a/lib/ftp.c b/lib/ftp.c
23index 57b22ad..3382772 100644
24--- a/lib/ftp.c
25+++ b/lib/ftp.c
26@@ -3763,129 +3763,131 @@ static CURLcode init_wc_data(struct connectdata *conn)
27 return result;
28 }
29
30-/* This is called recursively */
31 static CURLcode wc_statemach(struct connectdata *conn)
32 {
33 struct WildcardData * const wildcard = &(conn->data->wildcard);
34 CURLcode result = CURLE_OK;
35
36- switch(wildcard->state) {
37- case CURLWC_INIT:
38- result = init_wc_data(conn);
39- if(wildcard->state == CURLWC_CLEAN)
40- /* only listing! */
41- break;
42- wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
43- break;
44+ for(;;) {
45+ switch(wildcard->state) {
46+ case CURLWC_INIT:
47+ result = init_wc_data(conn);
48+ if(wildcard->state == CURLWC_CLEAN)
49+ /* only listing! */
50+ return result;
51+ wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
52+ return result;
53
54- case CURLWC_MATCHING: {
55- /* In this state is LIST response successfully parsed, so lets restore
56- previous WRITEFUNCTION callback and WRITEDATA pointer */
57- struct ftp_wc *ftpwc = wildcard->protdata;
58- conn->data->set.fwrite_func = ftpwc->backup.write_function;
59- conn->data->set.out = ftpwc->backup.file_descriptor;
60- ftpwc->backup.write_function = ZERO_NULL;
61- ftpwc->backup.file_descriptor = NULL;
62- wildcard->state = CURLWC_DOWNLOADING;
63-
64- if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
65- /* error found in LIST parsing */
66- wildcard->state = CURLWC_CLEAN;
67- return wc_statemach(conn);
68- }
69- if(wildcard->filelist.size == 0) {
70- /* no corresponding file */
71- wildcard->state = CURLWC_CLEAN;
72- return CURLE_REMOTE_FILE_NOT_FOUND;
73+ case CURLWC_MATCHING: {
74+ /* In this state is LIST response successfully parsed, so lets restore
75+ previous WRITEFUNCTION callback and WRITEDATA pointer */
76+ struct ftp_wc *ftpwc = wildcard->protdata;
77+ conn->data->set.fwrite_func = ftpwc->backup.write_function;
78+ conn->data->set.out = ftpwc->backup.file_descriptor;
79+ ftpwc->backup.write_function = ZERO_NULL;
80+ ftpwc->backup.file_descriptor = NULL;
81+ wildcard->state = CURLWC_DOWNLOADING;
82+
83+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
84+ /* error found in LIST parsing */
85+ wildcard->state = CURLWC_CLEAN;
86+ continue;
87+ }
88+ if(wildcard->filelist.size == 0) {
89+ /* no corresponding file */
90+ wildcard->state = CURLWC_CLEAN;
91+ return CURLE_REMOTE_FILE_NOT_FOUND;
92+ }
93+ continue;
94 }
95- return wc_statemach(conn);
96- }
97
98- case CURLWC_DOWNLOADING: {
99- /* filelist has at least one file, lets get first one */
100- struct ftp_conn *ftpc = &conn->proto.ftpc;
101- struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
102- struct FTP *ftp = conn->data->req.protop;
103+ case CURLWC_DOWNLOADING: {
104+ /* filelist has at least one file, lets get first one */
105+ struct ftp_conn *ftpc = &conn->proto.ftpc;
106+ struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
107+ struct FTP *ftp = conn->data->req.protop;
108
109- char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
110- if(!tmp_path)
111- return CURLE_OUT_OF_MEMORY;
112+ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
113+ if(!tmp_path)
114+ return CURLE_OUT_OF_MEMORY;
115
116- /* switch default ftp->path and tmp_path */
117- free(ftp->pathalloc);
118- ftp->pathalloc = ftp->path = tmp_path;
119-
120- infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
121- if(conn->data->set.chunk_bgn) {
122- long userresponse;
123- Curl_set_in_callback(conn->data, true);
124- userresponse = conn->data->set.chunk_bgn(
125- finfo, wildcard->customptr, (int)wildcard->filelist.size);
126- Curl_set_in_callback(conn->data, false);
127- switch(userresponse) {
128- case CURL_CHUNK_BGN_FUNC_SKIP:
129- infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
130- finfo->filename);
131- wildcard->state = CURLWC_SKIP;
132- return wc_statemach(conn);
133- case CURL_CHUNK_BGN_FUNC_FAIL:
134- return CURLE_CHUNK_FAILED;
135+ /* switch default ftp->path and tmp_path */
136+ free(ftp->pathalloc);
137+ ftp->pathalloc = ftp->path = tmp_path;
138+
139+ infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
140+ if(conn->data->set.chunk_bgn) {
141+ long userresponse;
142+ Curl_set_in_callback(conn->data, true);
143+ userresponse = conn->data->set.chunk_bgn(
144+ finfo, wildcard->customptr, (int)wildcard->filelist.size);
145+ Curl_set_in_callback(conn->data, false);
146+ switch(userresponse) {
147+ case CURL_CHUNK_BGN_FUNC_SKIP:
148+ infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
149+ finfo->filename);
150+ wildcard->state = CURLWC_SKIP;
151+ continue;
152+ case CURL_CHUNK_BGN_FUNC_FAIL:
153+ return CURLE_CHUNK_FAILED;
154+ }
155 }
156- }
157
158- if(finfo->filetype != CURLFILETYPE_FILE) {
159- wildcard->state = CURLWC_SKIP;
160- return wc_statemach(conn);
161- }
162+ if(finfo->filetype != CURLFILETYPE_FILE) {
163+ wildcard->state = CURLWC_SKIP;
164+ continue;
165+ }
166
167- if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
168- ftpc->known_filesize = finfo->size;
169+ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
170+ ftpc->known_filesize = finfo->size;
171
172- result = ftp_parse_url_path(conn);
173- if(result)
174- return result;
175+ result = ftp_parse_url_path(conn);
176+ if(result)
177+ return result;
178
179- /* we don't need the Curl_fileinfo of first file anymore */
180- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
181+ /* we don't need the Curl_fileinfo of first file anymore */
182+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
183
184- if(wildcard->filelist.size == 0) { /* remains only one file to down. */
185- wildcard->state = CURLWC_CLEAN;
186- /* after that will be ftp_do called once again and no transfer
187- will be done because of CURLWC_CLEAN state */
188- return CURLE_OK;
189+ if(wildcard->filelist.size == 0) { /* remains only one file to down. */
190+ wildcard->state = CURLWC_CLEAN;
191+ /* after that will be ftp_do called once again and no transfer
192+ will be done because of CURLWC_CLEAN state */
193+ return CURLE_OK;
194+ }
195+ return result;
196 }
197- } break;
198
199- case CURLWC_SKIP: {
200- if(conn->data->set.chunk_end) {
201- Curl_set_in_callback(conn->data, true);
202- conn->data->set.chunk_end(conn->data->wildcard.customptr);
203- Curl_set_in_callback(conn->data, false);
204+ case CURLWC_SKIP: {
205+ if(conn->data->set.chunk_end) {
206+ Curl_set_in_callback(conn->data, true);
207+ conn->data->set.chunk_end(conn->data->wildcard.customptr);
208+ Curl_set_in_callback(conn->data, false);
209+ }
210+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
211+ wildcard->state = (wildcard->filelist.size == 0) ?
212+ CURLWC_CLEAN : CURLWC_DOWNLOADING;
213+ continue;
214 }
215- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
216- wildcard->state = (wildcard->filelist.size == 0) ?
217- CURLWC_CLEAN : CURLWC_DOWNLOADING;
218- return wc_statemach(conn);
219- }
220
221- case CURLWC_CLEAN: {
222- struct ftp_wc *ftpwc = wildcard->protdata;
223- result = CURLE_OK;
224- if(ftpwc)
225- result = Curl_ftp_parselist_geterror(ftpwc->parser);
226+ case CURLWC_CLEAN: {
227+ struct ftp_wc *ftpwc = wildcard->protdata;
228+ result = CURLE_OK;
229+ if(ftpwc)
230+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
231
232- wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
233- } break;
234+ wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
235+ return result;
236+ }
237
238- case CURLWC_DONE:
239- case CURLWC_ERROR:
240- case CURLWC_CLEAR:
241- if(wildcard->dtor)
242- wildcard->dtor(wildcard->protdata);
243- break;
244+ case CURLWC_DONE:
245+ case CURLWC_ERROR:
246+ case CURLWC_CLEAR:
247+ if(wildcard->dtor)
248+ wildcard->dtor(wildcard->protdata);
249+ return result;
250+ }
251 }
252-
253- return result;
254+ /* UNREACHABLE */
255 }
256
257 /***********************************************************************
258--
2592.26.2
260
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8286.patch b/meta/recipes-support/curl/curl/CVE-2020-8286.patch
new file mode 100644
index 0000000000..093562fe01
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2020-8286.patch
@@ -0,0 +1,133 @@
1From 43d1163b3730f715704240f7f6d31af289246873 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Wed, 2 Dec 2020 23:01:11 +0100
4Subject: [PATCH] openssl: make the OCSP verification verify the certificate id
5
6CVE-2020-8286
7
8Reported by anonymous
9
10Bug: https://curl.se/docs/CVE-2020-8286.html
11
12Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199
13Signed-off-by: Kamil Dudka <kdudka@redhat.com>
14
15Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0007-curl-7.71.1-CVE-2020-8286.patch ]
16CVE: CVE-2020-8286
17Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
18---
19 lib/vtls/openssl.c | 83 ++++++++++++++++++++++++++++++----------------
20 1 file changed, 54 insertions(+), 29 deletions(-)
21
22diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
23index 1d09cad..bcfd83b 100644
24--- a/lib/vtls/openssl.c
25+++ b/lib/vtls/openssl.c
26@@ -1717,6 +1717,11 @@ static CURLcode verifystatus(struct connectdata *conn,
27 OCSP_BASICRESP *br = NULL;
28 X509_STORE *st = NULL;
29 STACK_OF(X509) *ch = NULL;
30+ X509 *cert;
31+ OCSP_CERTID *id = NULL;
32+ int cert_status, crl_reason;
33+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
34+ int ret;
35
36 long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status);
37
38@@ -1785,43 +1790,63 @@ static CURLcode verifystatus(struct connectdata *conn,
39 goto end;
40 }
41
42- for(i = 0; i < OCSP_resp_count(br); i++) {
43- int cert_status, crl_reason;
44- OCSP_SINGLERESP *single = NULL;
45-
46- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
47+ /* Compute the certificate's ID */
48+ cert = SSL_get_peer_certificate(BACKEND->handle);
49+ if(!cert) {
50+ failf(data, "Error getting peer certficate");
51+ result = CURLE_SSL_INVALIDCERTSTATUS;
52+ goto end;
53+ }
54
55- single = OCSP_resp_get0(br, i);
56- if(!single)
57- continue;
58+ for(i = 0; i < sk_X509_num(ch); i++) {
59+ X509 *issuer = sk_X509_value(ch, i);
60+ if(X509_check_issued(issuer, cert) == X509_V_OK) {
61+ id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
62+ break;
63+ }
64+ }
65+ X509_free(cert);
66
67- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
68- &thisupd, &nextupd);
69+ if(!id) {
70+ failf(data, "Error computing OCSP ID");
71+ result = CURLE_SSL_INVALIDCERTSTATUS;
72+ goto end;
73+ }
74
75- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
76- failf(data, "OCSP response has expired");
77- result = CURLE_SSL_INVALIDCERTSTATUS;
78- goto end;
79- }
80+ /* Find the single OCSP response corresponding to the certificate ID */
81+ ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
82+ &thisupd, &nextupd);
83+ OCSP_CERTID_free(id);
84+ if(ret != 1) {
85+ failf(data, "Could not find certificate ID in OCSP response");
86+ result = CURLE_SSL_INVALIDCERTSTATUS;
87+ goto end;
88+ }
89
90- infof(data, "SSL certificate status: %s (%d)\n",
91- OCSP_cert_status_str(cert_status), cert_status);
92+ /* Validate the corresponding single OCSP response */
93+ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
94+ failf(data, "OCSP response has expired");
95+ result = CURLE_SSL_INVALIDCERTSTATUS;
96+ goto end;
97+ }
98
99- switch(cert_status) {
100- case V_OCSP_CERTSTATUS_GOOD:
101- break;
102+ infof(data, "SSL certificate status: %s (%d)\n",
103+ OCSP_cert_status_str(cert_status), cert_status);
104
105- case V_OCSP_CERTSTATUS_REVOKED:
106- result = CURLE_SSL_INVALIDCERTSTATUS;
107+ switch(cert_status) {
108+ case V_OCSP_CERTSTATUS_GOOD:
109+ break;
110
111- failf(data, "SSL certificate revocation reason: %s (%d)",
112- OCSP_crl_reason_str(crl_reason), crl_reason);
113- goto end;
114+ case V_OCSP_CERTSTATUS_REVOKED:
115+ result = CURLE_SSL_INVALIDCERTSTATUS;
116+ failf(data, "SSL certificate revocation reason: %s (%d)",
117+ OCSP_crl_reason_str(crl_reason), crl_reason);
118+ goto end;
119
120- case V_OCSP_CERTSTATUS_UNKNOWN:
121- result = CURLE_SSL_INVALIDCERTSTATUS;
122- goto end;
123- }
124+ case V_OCSP_CERTSTATUS_UNKNOWN:
125+ default:
126+ result = CURLE_SSL_INVALIDCERTSTATUS;
127+ goto end;
128 }
129
130 end:
131--
1322.26.2
133