diff options
| -rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8231.patch | 1092 | ||||
| -rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8284.patch | 209 | ||||
| -rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8285.patch | 260 | ||||
| -rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8286.patch | 133 | ||||
| -rw-r--r-- | meta/recipes-support/curl/curl_7.69.1.bb | 4 |
5 files changed, 1698 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 @@ | |||
| 1 | From c3359693e17fccdf2a04f0b908bc8f51cdc38133 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Stenberg <daniel@haxx.se> | ||
| 3 | Date: Mon, 27 Apr 2020 00:33:21 +0200 | ||
| 4 | Subject: [PATCH 1/3] conncache: various concept cleanups | ||
| 5 | |||
| 6 | More connection cache accesses are protected by locks. | ||
| 7 | |||
| 8 | CONNCACHE_* is a beter prefix for the connection cache lock macros. | ||
| 9 | |||
| 10 | Curl_attach_connnection: now called as soon as there's a connection | ||
| 11 | struct available and before the connection is added to the connection | ||
| 12 | cache. | ||
| 13 | |||
| 14 | Curl_disconnect: now assumes that the connection is already removed from | ||
| 15 | the connection cache. | ||
| 16 | |||
| 17 | Ref: #4915 | ||
| 18 | Closes #5009 | ||
| 19 | |||
| 20 | Upstream-commit: c06902713998d68202c5a764de910ba8d0e8f54d | ||
| 21 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
| 22 | |||
| 23 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0004-curl-7.69.1-CVE-2020-8231.patch ] | ||
| 24 | CVE: CVE-2020-8286 | ||
| 25 | Signed-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 | |||
| 39 | diff --git a/lib/conncache.c b/lib/conncache.c | ||
| 40 | index 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 | |||
| 274 | diff --git a/lib/conncache.h b/lib/conncache.h | ||
| 275 | index 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 | |||
| 312 | diff --git a/lib/hostip.c b/lib/hostip.c | ||
| 313 | index 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 | } | ||
| 334 | diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h | ||
| 335 | index 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 */ | ||
| 357 | diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h | ||
| 358 | index 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 */ | ||
| 380 | diff --git a/lib/multi.c b/lib/multi.c | ||
| 381 | index 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); | ||
| 536 | diff --git a/lib/multiif.h b/lib/multiif.h | ||
| 537 | index 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); | ||
| 548 | diff --git a/lib/url.c b/lib/url.c | ||
| 549 | index 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 | } | ||
| 745 | diff --git a/tests/data/test1554 b/tests/data/test1554 | ||
| 746 | index 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 | ||
| 784 | diff --git a/tests/unit/unit1620.c b/tests/unit/unit1620.c | ||
| 785 | index 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 | -- | ||
| 809 | 2.25.4 | ||
| 810 | |||
| 811 | |||
| 812 | From 6830828c9eecd9ab14404f2f49f19b56dec62130 Mon Sep 17 00:00:00 2001 | ||
| 813 | From: Marc Aldorasi <marc@groundctl.com> | ||
| 814 | Date: Thu, 30 Jul 2020 14:16:17 -0400 | ||
| 815 | Subject: [PATCH 2/3] multi_remove_handle: close unused connect-only | ||
| 816 | connections | ||
| 817 | |||
| 818 | Previously any connect-only connections in a multi handle would be kept | ||
| 819 | alive until the multi handle was closed. Since these connections cannot | ||
| 820 | be re-used, they can be marked for closure when the associated easy | ||
| 821 | handle is removed from the multi handle. | ||
| 822 | |||
| 823 | Closes #5749 | ||
| 824 | |||
| 825 | Upstream-commit: d5bb459ccf1fc5980ae4b95c05b4ecf6454a7599 | ||
| 826 | Signed-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 | |||
| 832 | diff --git a/lib/multi.c b/lib/multi.c | ||
| 833 | index 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 | ||
| 897 | diff --git a/tests/data/test1554 b/tests/data/test1554 | ||
| 898 | index 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 | -- | ||
| 929 | 2.25.4 | ||
| 930 | |||
| 931 | |||
| 932 | From 01148ee40dd913a169435b0f9ea90e6393821e70 Mon Sep 17 00:00:00 2001 | ||
| 933 | From: Daniel Stenberg <daniel@haxx.se> | ||
| 934 | Date: Sun, 16 Aug 2020 11:34:35 +0200 | ||
| 935 | Subject: [PATCH 3/3] Curl_easy: remember last connection by id, not by pointer | ||
| 936 | |||
| 937 | CVE-2020-8231 | ||
| 938 | |||
| 939 | Bug: https://curl.haxx.se/docs/CVE-2020-8231.html | ||
| 940 | |||
| 941 | Reported-by: Marc Aldorasi | ||
| 942 | Closes #5824 | ||
| 943 | |||
| 944 | Upstream-commit: 3c9e021f86872baae412a427e807fbfa2f3e8a22 | ||
| 945 | Signed-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 | |||
| 954 | diff --git a/lib/connect.c b/lib/connect.c | ||
| 955 | index 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; | ||
| 1006 | diff --git a/lib/easy.c b/lib/easy.c | ||
| 1007 | index 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; | ||
| 1020 | diff --git a/lib/multi.c b/lib/multi.c | ||
| 1021 | index 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); | ||
| 1064 | diff --git a/lib/url.c b/lib/url.c | ||
| 1065 | index 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 */ | ||
| 1077 | diff --git a/lib/urldata.h b/lib/urldata.h | ||
| 1078 | index 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 | -- | ||
| 1091 | 2.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 @@ | |||
| 1 | From ec9cc725d598ac77de7b6df8afeec292b3c8ad46 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Stenberg <daniel@haxx.se> | ||
| 3 | Date: Tue, 24 Nov 2020 14:56:57 +0100 | ||
| 4 | Subject: [PATCH] ftp: CURLOPT_FTP_SKIP_PASV_IP by default | ||
| 5 | |||
| 6 | The command line tool also independently sets --ftp-skip-pasv-ip by | ||
| 7 | default. | ||
| 8 | |||
| 9 | Ten test cases updated to adapt the modified --libcurl output. | ||
| 10 | |||
| 11 | Bug: https://curl.se/docs/CVE-2020-8284.html | ||
| 12 | CVE-2020-8284 | ||
| 13 | |||
| 14 | Reported-by: Varnavas Papaioannou | ||
| 15 | |||
| 16 | Upstream-Status: Backport [https://github.com/curl/curl/commit/ec9cc725d598ac] | ||
| 17 | CVE: CVE-2020-8284 | ||
| 18 | Signed-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 | |||
| 36 | diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d | ||
| 37 | index 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. | ||
| 47 | diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | ||
| 48 | index 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 | ||
| 76 | diff --git a/lib/url.c b/lib/url.c | ||
| 77 | index 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 | |||
| 88 | diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c | ||
| 89 | index 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) | ||
| 100 | diff --git a/tests/data/test1400 b/tests/data/test1400 | ||
| 101 | index 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 | ||
| 112 | diff --git a/tests/data/test1401 b/tests/data/test1401 | ||
| 113 | index 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 | | ||
| 124 | diff --git a/tests/data/test1402 b/tests/data/test1402 | ||
| 125 | index 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 | ||
| 136 | diff --git a/tests/data/test1403 b/tests/data/test1403 | ||
| 137 | index 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 | ||
| 148 | diff --git a/tests/data/test1404 b/tests/data/test1404 | ||
| 149 | index 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 | ||
| 160 | diff --git a/tests/data/test1405 b/tests/data/test1405 | ||
| 161 | index 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 | ||
| 172 | diff --git a/tests/data/test1406 b/tests/data/test1406 | ||
| 173 | index 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); | ||
| 184 | diff --git a/tests/data/test1407 b/tests/data/test1407 | ||
| 185 | index 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 | ||
| 196 | diff --git a/tests/data/test1420 b/tests/data/test1420 | ||
| 197 | index 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 @@ | |||
| 1 | From 6fda045b19a9066701b5e09cfa657a13a3accbf3 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Stenberg <daniel@haxx.se> | ||
| 3 | Date: Sat, 28 Nov 2020 00:27:21 +0100 | ||
| 4 | Subject: [PATCH] ftp: make wc_statemach loop instead of recurse | ||
| 5 | |||
| 6 | CVE-2020-8285 | ||
| 7 | |||
| 8 | Fixes #6255 | ||
| 9 | Bug: https://curl.se/docs/CVE-2020-8285.html | ||
| 10 | Reported-by: xnynx on github | ||
| 11 | |||
| 12 | Upstream-commit: 69a358f2186e04cf44698b5100332cbf1ee7f01d | ||
| 13 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
| 14 | |||
| 15 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0006-curl-7.69.1-CVE-2020-8285.patch] | ||
| 16 | CVE: CVE-2020-8285 | ||
| 17 | Signed-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 | |||
| 22 | diff --git a/lib/ftp.c b/lib/ftp.c | ||
| 23 | index 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 | -- | ||
| 259 | 2.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 @@ | |||
| 1 | From 43d1163b3730f715704240f7f6d31af289246873 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Stenberg <daniel@haxx.se> | ||
| 3 | Date: Wed, 2 Dec 2020 23:01:11 +0100 | ||
| 4 | Subject: [PATCH] openssl: make the OCSP verification verify the certificate id | ||
| 5 | |||
| 6 | CVE-2020-8286 | ||
| 7 | |||
| 8 | Reported by anonymous | ||
| 9 | |||
| 10 | Bug: https://curl.se/docs/CVE-2020-8286.html | ||
| 11 | |||
| 12 | Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199 | ||
| 13 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
| 14 | |||
| 15 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0007-curl-7.71.1-CVE-2020-8286.patch ] | ||
| 16 | CVE: CVE-2020-8286 | ||
| 17 | Signed-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 | |||
| 22 | diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c | ||
| 23 | index 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 | -- | ||
| 132 | 2.26.2 | ||
| 133 | |||
diff --git a/meta/recipes-support/curl/curl_7.69.1.bb b/meta/recipes-support/curl/curl_7.69.1.bb index 239852db09..c3d629108a 100644 --- a/meta/recipes-support/curl/curl_7.69.1.bb +++ b/meta/recipes-support/curl/curl_7.69.1.bb | |||
| @@ -9,6 +9,10 @@ SRC_URI = "https://curl.haxx.se/download/curl-${PV}.tar.bz2 \ | |||
| 9 | file://0001-replace-krb5-config-with-pkg-config.patch \ | 9 | file://0001-replace-krb5-config-with-pkg-config.patch \ |
| 10 | file://CVE-2020-8169.patch \ | 10 | file://CVE-2020-8169.patch \ |
| 11 | file://CVE-2020-8177.patch \ | 11 | file://CVE-2020-8177.patch \ |
| 12 | file://CVE-2020-8231.patch \ | ||
| 13 | file://CVE-2020-8284.patch \ | ||
| 14 | file://CVE-2020-8285.patch \ | ||
| 15 | file://CVE-2020-8286.patch \ | ||
| 12 | " | 16 | " |
| 13 | 17 | ||
| 14 | SRC_URI[md5sum] = "ec5fc263f898a3dfef08e805f1ecca42" | 18 | SRC_URI[md5sum] = "ec5fc263f898a3dfef08e805f1ecca42" |
