CVE-2021-22901: TLS session caching disaster
What the report claims
A use-after-free vulnerability in libcurl's TLS session caching code can lead to remote code execution when a stale connection pointer is reused after being detached and reattached.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2021-22901 TLS session caching disaster
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The available evidence does not settle the report. A maintainer should investigate.
Why this finding?
- The code confirms the stale-pointer flaw: ex_data is set on the SSL handle during connection setup (per deterministic checks), but Curl_detach_connection and Curl_attach_connection do not clear or update those indices, so a reused SSL handle can return pointers to a previous connection.
- The report does not demonstrate that an external attacker can trigger the session callback after a detach/attach cycle with a freed/repurposed Curl_easy. The reporter notes this occurs in a rare WebKit/PlayStation use case and admits no reproduction exists.
- Exploitability for remote code execution requires the attacker to control the freed Curl_easy's share pointer, which implies an existing memory-corruption primitive; the provided code does not show a path from network input to that primitive.
- Because the security impact (remote code execution by an external attacker) is not settled by the provided code, human assessment of the specific deployment scenario is needed.
What still needs checking
- Whether the SSL handle (backend->handle) is recreated or reused across detach/attach cycles in the affected deployment.
- A concrete reproduction or evidence that an external attacker can influence the detach/attach sequence and trigger the session callback.
- Whether the Curl_easy (data) can be freed while the SSL handle remains alive in the reported use case.
How this analysis ran 5 claims · 11 citations verified
Checked against curl master on 2021-04-29 (a3268eca792f). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Review a draft reply to the reporter
Edit and verify before sending.
Thank you for the detailed analysis. The code confirms that ex_data indices set during TLS setup are not cleared by Curl_detach_connection or updated by Curl_attach_connection, so a reused SSL handle can return stale pointers. However, the report does not show how an external attacker can reach this path: we need to know whether the SSL handle persists across detach/attach, whether the Curl_easy can be freed while the handle lives, and whether the session callback fires in that state. Could you provide a minimal reproduction or describe the WebKit/PlayStation flow that triggers the callback after reattachment?
Inspect all claims and source code 5 claims · 6 code excerpts
Report claims
ossl_new_session_cb callback can be called with stale connection pointers after Curl_detach_connnection and Curl_attach_connection reassign connections without clearing ex_data indices.
Read the reasoning
The code confirms that ex_data indices are read in the session callback but are not cleared or updated by Curl_detach_connection or Curl_attach_connection. The deterministic checks confirm the quoted SSL_set_ex_data lines exist in the file (though not in the provided snippets).
ossl_connect_step1 function in lib/vtls/openssl.c sets up the sessionid callback and ex_data associations.
Read the reasoning
Deterministic checks confirm the quoted SSL_CTX_set_session_cache_mode and SSL_CTX_sess_set_new_cb lines appear in the file at the checked revision.
When a session callback is invoked, it retrieves connection and data pointers via SSL_get_ex_data using data_idx and connectdata_idx.
Read the reasoning
The callback implementation directly shows retrieval of both pointers via the ex_data indices.
Stale pointers can lead to use-after-free, enabling remote code execution via Curl_ssl_sessionid_lock calling a fake struct Curl_share's lockfunc.
Read the reasoning
The code shows the call chain exists, but the provided code does not establish whether an external attacker can cause the data pointer to become a controlled dangling pointer, nor whether the session callback is reachable in the detach/attach scenario. The report itself states this is uncertain and lacks reproduction.
The vulnerability occurs when a connection is detached and reattached, leaving ex_data entries non-NULL while the original connection is no longer valid.
Read the reasoning
The mechanism described is consistent with the code: detach/attach modify data->conn but not the SSL object's ex_data, so the SSL object retains pointers to the previous connection.
Read the original report (excerpt)
Source code
| 2452 | static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) |
| 2453 | { |
| 2454 | int res = 0; |
| 2455 | struct connectdata *conn; |
| 2456 | struct Curl_easy *data; |
| 2457 | int sockindex; |
| 2458 | curl_socket_t *sockindex_ptr; |
| 2459 | int data_idx = ossl_get_ssl_data_index(); |
| 2460 | int connectdata_idx = ossl_get_ssl_conn_index(); |
| 2461 | int sockindex_idx = ossl_get_ssl_sockindex_index(); |
| 2462 | int proxy_idx = ossl_get_proxy_index(); |
| 2463 | bool isproxy; |
| 2464 | |
| 2465 | if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0 || proxy_idx < 0) |
| 2466 | return 0; |
| 2467 | |
| 2468 | conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); |
| C1: ossl_new_session_cb retrieves conn via SSL_get_ex_data(ssl, connectdata_idx) | |
| C3: conn = SSL_get_ex_data(ssl, connectdata_idx) | |
| 2469 | if(!conn) |
| 2470 | return 0; |
| 2471 | |
| 2472 | data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx); |
| C1: ossl_new_session_cb retrieves data via SSL_get_ex_data(ssl, data_idx) | |
| C3: data = SSL_get_ex_data(ssl, data_idx) | |
| 2473 | |
| 2474 | /* The sockindex has been stored as a pointer to an array element */ |
| 2475 | sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); |
| 2476 | sockindex = (int)(sockindex_ptr - conn->sock); |
| 2477 | |
| 2478 | isproxy = SSL_get_ex_data(ssl, proxy_idx) ? TRUE : FALSE; |
| 2479 | |
| 2480 | if(SSL_SET_OPTION(primary.sessionid)) { |
| 2481 | bool incache; |
| 2482 | void *old_ssl_sessionid = NULL; |
| 2483 | |
| 2484 | Curl_ssl_sessionid_lock(data); |
| C4: Curl_ssl_sessionid_lock(data) called with data pointer from ex_data | |
| 2485 | if(isproxy) |
| 2486 | incache = FALSE; |
| 2487 | else |
| 2488 | incache = !(Curl_ssl_getsessionid(data, conn, isproxy, |
| 2489 | &old_ssl_sessionid, NULL, sockindex)); |
| 2490 | if(incache) { |
| 2491 | if(old_ssl_sessionid != ssl_sessionid) { |
| 2492 | infof(data, "old SSL session ID is stale, removing\n"); |
| 2493 | Curl_ssl_delsessionid(data, old_ssl_sessionid); |
| 2494 | incache = FALSE; |
| 2495 | } |
| 2496 | } |
| 2497 | |
| 2498 | if(!incache) { |
| 2499 | if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid, |
| 2500 | 0 /* unknown size */, sockindex)) { |
| 2501 | /* the session has been put into the session cache */ |
| 2502 | res = 1; |
| 2503 | } |
| 2504 | else |
| 2505 | failf(data, "failed to store ssl session"); |
| 2506 | } |
| 2507 | Curl_ssl_sessionid_unlock(data); |
| 2508 | } |
| 2509 | |
| 2510 | return res; |
| 2511 | } |
| 2513 | static CURLcode ossl_connect_step1(struct Curl_easy *data, |
| C2: ossl_connect_step1 function definition | |
| 2514 | struct connectdata *conn, int sockindex) |
| 2515 | { |
| 2516 | CURLcode result = CURLE_OK; |
| 2517 | char *ciphers; |
| 2518 | SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; |
| 2519 | X509_LOOKUP *lookup = NULL; |
| 2520 | curl_socket_t sockfd = conn->sock[sockindex]; |
| 2521 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
| 2522 | ctx_option_t ctx_options = 0; |
| 2523 | |
| 2524 | #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME |
| 2525 | bool sni; |
| 2526 | const char * const hostname = SSL_HOST_NAME(); |
| 2527 | |
| 2528 | #ifdef ENABLE_IPV6 |
| 2529 | struct in6_addr addr; |
| 2530 | #else |
| 2531 | struct in_addr addr; |
| 2532 | #endif |
| 2533 | #endif |
| 2534 | const long int ssl_version = SSL_CONN_CONFIG(version); |
| 2535 | #ifdef USE_OPENSSL_SRP |
| 2536 | const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); |
| 2537 | #endif |
| 2538 | char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); |
| 2539 | const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); |
| 2540 | const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); |
| 2541 | const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); |
| 2542 | const char * const ssl_capath = SSL_CONN_CONFIG(CApath); |
| 2543 | const bool verifypeer = SSL_CONN_CONFIG(verifypeer); |
| 2544 | const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); |
| 2545 | char error_buffer[256]; |
| 2546 | struct ssl_backend_data *backend = connssl->backend; |
| 2547 | bool imported_native_ca = false; |
| 2548 | |
| 2549 | DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); |
| 2550 | |
| 2551 | /* Make funny stuff to get random input */ |
| 2552 | result = ossl_seed(data); |
| 2553 | if(result) |
| 2554 | return result; |
| 2555 | |
| 2556 | SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK; |
| 2557 | |
| 2558 | /* check to see if we've been told to use an explicit SSL/TLS version */ |
| 2559 | |
| 2560 | switch(ssl_version) { |
| 2561 | case CURL_SSLVERSION_DEFAULT: |
| 2562 | case CURL_SSLVERSION_TLSv1: |
| 2563 | case CURL_SSLVERSION_TLSv1_0: |
| 2564 | case CURL_SSLVERSION_TLSv1_1: |
| 2565 | case CURL_SSLVERSION_TLSv1_2: |
| 2566 | case CURL_SSLVERSION_TLSv1_3: |
| 2567 | /* it will be handled later with the context options */ |
| 2568 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
| 2569 | req_method = TLS_client_method(); |
| 2570 | #else |
| 2571 | req_method = SSLv23_client_method(); |
| 2572 | #endif |
| 2573 | use_sni(TRUE); |
| 2574 | break; |
| 2575 | case CURL_SSLVERSION_SSLv2: |
| 2576 | failf(data, "No SSLv2 support"); |
| 2577 | return CURLE_NOT_BUILT_IN; |
| 2578 | case CURL_SSLVERSION_SSLv3: |
| 2579 | failf(data, "No SSLv3 support"); |
| 2580 | return CURLE_NOT_BUILT_IN; |
| 2581 | default: |
| 2582 | failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); |
| 2583 | return CURLE_SSL_CONNECT_ERROR; |
| 2584 | } |
| 2585 | |
| 2586 | if(backend->ctx) |
| 2587 | SSL_CTX_free(backend->ctx); |
| 2588 | backend->ctx = SSL_CTX_new(req_method); |
| 2589 | |
| 2590 | if(!backend->ctx) { |
| 2591 | failf(data, "SSL: couldn't create a context: %s", |
| 2592 | ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); |
| 2593 | return CURLE_OUT_OF_MEMORY; |
| 2594 | } |
| 2595 | |
| 2596 | #ifdef SSL_MODE_RELEASE_BUFFERS |
| 2597 | SSL_CTX_set_mode(backend->ctx, SSL_MODE_RELEASE_BUFFERS); |
| 2598 | #endif |
| 2599 | |
| 2600 | #ifdef SSL_CTRL_SET_MSG_CALLBACK |
| 2601 | if(data->set.fdebug && data->set.verbose) { |
| 2602 | /* the SSL trace callback is only used for verbose logging */ |
| 2603 | SSL_CTX_set_msg_callback(backend->ctx, ossl_trace); |
| 2604 | SSL_CTX_set_msg_callback_arg(backend->ctx, conn); |
| 2605 | set_logger(conn, data); |
| 2606 | } |
| 2607 | #endif |
| 2608 | |
| 2609 | /* OpenSSL contains code to work-around lots of bugs and flaws in various |
| 2610 | SSL-implementations. SSL_CTX_set_options() is used to enabled those |
| 2611 | work-arounds. The man page for this option states that SSL_OP_ALL enables |
| 2612 | all the work-arounds and that "It is usually safe to use SSL_OP_ALL to |
| 2613 | enable the bug workaround options if compatibility with somewhat broken |
| 2614 | implementations is desired." |
| 2615 | |
| 2616 | The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to |
| 2617 | disable "rfc4507bis session ticket support". rfc4507bis was later turned |
| 2618 | into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 |
| 2619 | |
| 2620 | The enabled extension concerns the session management. I wonder how often |
| 2621 | libcurl stops a connection and then resumes a TLS session. also, sending |
| 2622 | the session data is some overhead. .I suggest that you just use your |
| 2623 | proposed patch (which explicitly disables TICKET). |
| 2624 | |
| 2625 | If someone writes an application with libcurl and openssl who wants to |
| 2626 | enable the feature, one can do this in the SSL callback. |
| 2627 | |
| 2628 | SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper |
| 2629 | interoperability with web server Netscape Enterprise Server 2.0.1 which |
| 2630 | was released back in 1996. |
| 2631 | |
| 2632 | Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has |
| 2633 | become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate |
| 2634 | CVE-2010-4180 when using previous OpenSSL versions we no longer enable |
| 2635 | this option regardless of OpenSSL version and SSL_OP_ALL definition. |
| 2636 | |
| 2637 | OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability |
| 2638 | (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to |
| 2639 | SSL_OP_ALL that _disables_ that work-around despite the fact that |
| 2640 | SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to |
| 2641 | keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit |
| 2642 | must not be set. |
| 2643 | */ |
| 2644 | |
| 2645 | ctx_options = SSL_OP_ALL; |
| 2646 | |
| 2647 | #ifdef SSL_OP_NO_TICKET |
| 2648 | ctx_options |= SSL_OP_NO_TICKET; |
| 2649 | #endif |
| 2650 | |
| 2651 | #ifdef SSL_OP_NO_COMPRESSION |
| 2652 | ctx_options |= SSL_OP_NO_COMPRESSION; |
| 2653 | #endif |
| 2654 | |
| 2655 | #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG |
| 2656 | /* mitigate CVE-2010-4180 */ |
| 2657 | ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; |
| 2658 | #endif |
| 2659 | |
| 2660 | #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS |
| 2661 | /* unless the user explicitly ask to allow the protocol vulnerability we |
| 2662 | use the work-around */ |
| 2663 | if(!SSL_SET_OPTION(enable_beast)) |
| 2664 | ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; |
| 2665 | #endif |
| 2666 | |
| 2667 | switch(ssl_version) { |
| 2668 | case CURL_SSLVERSION_SSLv2: |
| 2669 | case CURL_SSLVERSION_SSLv3: |
| 2670 | return CURLE_NOT_BUILT_IN; |
| 2671 | |
| 2672 | /* "--tlsv<x.y>" options mean TLS >= version <x.y> */ |
| 2673 | case CURL_SSLVERSION_DEFAULT: |
| 353 | void Curl_ssl_sessionid_lock(struct Curl_easy *data) |
| C4: Curl_ssl_sessionid_lock calls Curl_share_lock if SSLSESSION_SHARED(data) | |
| 354 | { |
| 355 | if(SSLSESSION_SHARED(data)) |
| 356 | Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); |
| 357 | } |
| 878 | void Curl_detach_connnection(struct Curl_easy *data) |
| C1: Curl_detach_connection only sets data->conn = NULL, does not clear SSL ex_data | |
| C5: Curl_detach_connection leaves ex_data untouched | |
| 879 | { |
| 880 | struct connectdata *conn = data->conn; |
| 881 | if(conn) |
| 882 | Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); |
| 883 | data->conn = NULL; |
| 884 | } |
| 891 | void Curl_attach_connnection(struct Curl_easy *data, |
| C1: Curl_attach_connection only sets data->conn = conn, does not update SSL ex_data | |
| C5: Curl_attach_connection leaves ex_data untouched | |
| 892 | struct connectdata *conn) |
| 893 | { |
| 894 | DEBUGASSERT(!data->conn); |
| 895 | DEBUGASSERT(conn); |
| 896 | data->conn = conn; |
| 897 | Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, |
| 898 | &data->conn_queue); |
| 899 | } |
Show 161 lines (not cited by the judge)
| 2521 | static CURLcode ossl_connect_step1(struct Curl_easy *data, |
| 2522 | struct connectdata *conn, int sockindex) |
| 2523 | { |
| 2524 | CURLcode result = CURLE_OK; |
| 2525 | char *ciphers; |
| 2526 | SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; |
| 2527 | X509_LOOKUP *lookup = NULL; |
| 2528 | curl_socket_t sockfd = conn->sock[sockindex]; |
| 2529 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
| 2530 | ctx_option_t ctx_options = 0; |
| 2531 | |
| 2532 | #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME |
| 2533 | bool sni; |
| 2534 | const char * const hostname = SSL_HOST_NAME(); |
| 2535 | |
| 2536 | #ifdef ENABLE_IPV6 |
| 2537 | struct in6_addr addr; |
| 2538 | #else |
| 2539 | struct in_addr addr; |
| 2540 | #endif |
| 2541 | #endif |
| 2542 | const long int ssl_version = SSL_CONN_CONFIG(version); |
| 2543 | #ifdef USE_OPENSSL_SRP |
| 2544 | const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); |
| 2545 | #endif |
| 2546 | char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); |
| 2547 | const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); |
| 2548 | const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); |
| 2549 | const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); |
| 2550 | const char * const ssl_capath = SSL_CONN_CONFIG(CApath); |
| 2551 | const bool verifypeer = SSL_CONN_CONFIG(verifypeer); |
| 2552 | const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); |
| 2553 | char error_buffer[256]; |
| 2554 | struct ssl_backend_data *backend = connssl->backend; |
| 2555 | bool imported_native_ca = false; |
| 2556 | |
| 2557 | DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); |
| 2558 | |
| 2559 | /* Make funny stuff to get random input */ |
| 2560 | result = ossl_seed(data); |
| 2561 | if(result) |
| 2562 | return result; |
| 2563 | |
| 2564 | SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK; |
| 2565 | |
| 2566 | /* check to see if we've been told to use an explicit SSL/TLS version */ |
| 2567 | |
| 2568 | switch(ssl_version) { |
| 2569 | case CURL_SSLVERSION_DEFAULT: |
| 2570 | case CURL_SSLVERSION_TLSv1: |
| 2571 | case CURL_SSLVERSION_TLSv1_0: |
| 2572 | case CURL_SSLVERSION_TLSv1_1: |
| 2573 | case CURL_SSLVERSION_TLSv1_2: |
| 2574 | case CURL_SSLVERSION_TLSv1_3: |
| 2575 | /* it will be handled later with the context options */ |
| 2576 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
| 2577 | req_method = TLS_client_method(); |
| 2578 | #else |
| 2579 | req_method = SSLv23_client_method(); |
| 2580 | #endif |
| 2581 | use_sni(TRUE); |
| 2582 | break; |
| 2583 | case CURL_SSLVERSION_SSLv2: |
| 2584 | #ifdef OPENSSL_NO_SSL2 |
| 2585 | failf(data, OSSL_PACKAGE " was built without SSLv2 support"); |
| 2586 | return CURLE_NOT_BUILT_IN; |
| 2587 | #else |
| 2588 | #ifdef USE_OPENSSL_SRP |
| 2589 | if(ssl_authtype == CURL_TLSAUTH_SRP) |
| 2590 | return CURLE_SSL_CONNECT_ERROR; |
| 2591 | #endif |
| 2592 | req_method = SSLv2_client_method(); |
| 2593 | use_sni(FALSE); |
| 2594 | break; |
| 2595 | #endif |
| 2596 | case CURL_SSLVERSION_SSLv3: |
| 2597 | #ifdef OPENSSL_NO_SSL3_METHOD |
| 2598 | failf(data, OSSL_PACKAGE " was built without SSLv3 support"); |
| 2599 | return CURLE_NOT_BUILT_IN; |
| 2600 | #else |
| 2601 | #ifdef USE_OPENSSL_SRP |
| 2602 | if(ssl_authtype == CURL_TLSAUTH_SRP) |
| 2603 | return CURLE_SSL_CONNECT_ERROR; |
| 2604 | #endif |
| 2605 | req_method = SSLv3_client_method(); |
| 2606 | use_sni(FALSE); |
| 2607 | break; |
| 2608 | #endif |
| 2609 | default: |
| 2610 | failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); |
| 2611 | return CURLE_SSL_CONNECT_ERROR; |
| 2612 | } |
| 2613 | |
| 2614 | if(backend->ctx) |
| 2615 | SSL_CTX_free(backend->ctx); |
| 2616 | backend->ctx = SSL_CTX_new(req_method); |
| 2617 | |
| 2618 | if(!backend->ctx) { |
| 2619 | failf(data, "SSL: couldn't create a context: %s", |
| 2620 | ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); |
| 2621 | return CURLE_OUT_OF_MEMORY; |
| 2622 | } |
| 2623 | |
| 2624 | #ifdef SSL_MODE_RELEASE_BUFFERS |
| 2625 | SSL_CTX_set_mode(backend->ctx, SSL_MODE_RELEASE_BUFFERS); |
| 2626 | #endif |
| 2627 | |
| 2628 | #ifdef SSL_CTRL_SET_MSG_CALLBACK |
| 2629 | if(data->set.fdebug && data->set.verbose) { |
| 2630 | /* the SSL trace callback is only used for verbose logging */ |
| 2631 | SSL_CTX_set_msg_callback(backend->ctx, ossl_trace); |
| 2632 | SSL_CTX_set_msg_callback_arg(backend->ctx, conn); |
| 2633 | set_logger(conn, data); |
| 2634 | } |
| 2635 | #endif |
| 2636 | |
| 2637 | /* OpenSSL contains code to work-around lots of bugs and flaws in various |
| 2638 | SSL-implementations. SSL_CTX_set_options() is used to enabled those |
| 2639 | work-arounds. The man page for this option states that SSL_OP_ALL enables |
| 2640 | all the work-arounds and that "It is usually safe to use SSL_OP_ALL to |
| 2641 | enable the bug workaround options if compatibility with somewhat broken |
| 2642 | implementations is desired." |
| 2643 | |
| 2644 | The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to |
| 2645 | disable "rfc4507bis session ticket support". rfc4507bis was later turned |
| 2646 | into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 |
| 2647 | |
| 2648 | The enabled extension concerns the session management. I wonder how often |
| 2649 | libcurl stops a connection and then resumes a TLS session. also, sending |
| 2650 | the session data is some overhead. .I suggest that you just use your |
| 2651 | proposed patch (which explicitly disables TICKET). |
| 2652 | |
| 2653 | If someone writes an application with libcurl and openssl who wants to |
| 2654 | enable the feature, one can do this in the SSL callback. |
| 2655 | |
| 2656 | SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper |
| 2657 | interoperability with web server Netscape Enterprise Server 2.0.1 which |
| 2658 | was released back in 1996. |
| 2659 | |
| 2660 | Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has |
| 2661 | become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate |
| 2662 | CVE-2010-4180 when using previous OpenSSL versions we no longer enable |
| 2663 | this option regardless of OpenSSL version and SSL_OP_ALL definition. |
| 2664 | |
| 2665 | OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability |
| 2666 | (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to |
| 2667 | SSL_OP_ALL that _disables_ that work-around despite the fact that |
| 2668 | SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to |
| 2669 | keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit |
| 2670 | must not be set. |
| 2671 | */ |
| 2672 | |
| 2673 | ctx_options = SSL_OP_ALL; |
| 2674 | |
| 2675 | #ifdef SSL_OP_NO_TICKET |
| 2676 | ctx_options |= SSL_OP_NO_TICKET; |
| 2677 | #endif |
| 2678 | |
| 2679 | #ifdef SSL_OP_NO_COMPRESSION |
| 2680 | ctx_options |= SSL_OP_NO_COMPRESSION; |
| 2681 | #endif |