diff --git a/DEPENDENCIES b/DEPENDENCIES index 7fe6135a..fc95800a 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -5,4 +5,4 @@ bearssl https://www.bearssl.org/git/BearSSL 8ef7680081c61b486622f2d983c0d3d21e83 zlib https://github.com/madler/zlib 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf uwebsockets https://github.com/uNetworking/uWebSockets v20.64.0 googletest https://github.com/google/googletest 987e225614755fec7253aa95bf959c09e0d380d7 -curl https://github.com/curl/curl curl-8_9_0 +curl https://github.com/curl/curl curl-8_9_1 diff --git a/vendor/curl/include/curl/curl.h b/vendor/curl/include/curl/curl.h index 677bcd42..6da44ce9 100644 --- a/vendor/curl/include/curl/curl.h +++ b/vendor/curl/include/curl/curl.h @@ -2133,7 +2133,7 @@ typedef enum { /* the EC curves requested by the TLS client (RFC 8422, 5.1); * OpenSSL support via 'set_groups'/'set_curves': - * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html + * https://docs.openssl.org/master/man3/SSL_CTX_set1_curves/ */ CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), diff --git a/vendor/curl/include/curl/curlver.h b/vendor/curl/include/curl/curlver.h index afab32fc..79d920bf 100644 --- a/vendor/curl/include/curl/curlver.h +++ b/vendor/curl/include/curl/curlver.h @@ -32,13 +32,13 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "8.9.0-DEV" +#define LIBCURL_VERSION "8.9.1-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 8 #define LIBCURL_VERSION_MINOR 9 -#define LIBCURL_VERSION_PATCH 0 +#define LIBCURL_VERSION_PATCH 1 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will @@ -59,7 +59,7 @@ CURL_VERSION_BITS() macro since curl's own configure script greps for it and needs it to contain the full number. */ -#define LIBCURL_VERSION_NUM 0x080900 +#define LIBCURL_VERSION_NUM 0x080901 /* * This is the date and time when the full source package was created. The diff --git a/vendor/curl/lib/conncache.c b/vendor/curl/lib/conncache.c index a1c44cf0..92fd60c4 100644 --- a/vendor/curl/lib/conncache.c +++ b/vendor/curl/lib/conncache.c @@ -584,15 +584,15 @@ static void connc_close_all(struct conncache *connc) return; /* Move all connections to the shutdown list */ + sigpipe_init(&pipe_st); conn = connc_find_first_connection(connc); while(conn) { connc_remove_conn(connc, conn); - sigpipe_ignore(data, &pipe_st); + sigpipe_apply(data, &pipe_st); /* This will remove the connection from the cache */ connclose(conn, "kill all"); Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE); connc_discard_conn(connc, connc->closure_handle, conn, FALSE); - sigpipe_restore(&pipe_st); conn = connc_find_first_connection(connc); } @@ -613,7 +613,7 @@ static void connc_close_all(struct conncache *connc) /* discard all connections in the shutdown list */ connc_shutdown_discard_all(connc); - sigpipe_ignore(data, &pipe_st); + sigpipe_apply(data, &pipe_st); Curl_hostcache_clean(data, data->dns.hostcache); Curl_close(&data); sigpipe_restore(&pipe_st); @@ -628,7 +628,6 @@ static void connc_shutdown_discard_oldest(struct conncache *connc) { struct Curl_llist_element *e; struct connectdata *conn; - SIGPIPE_VARIABLE(pipe_st); DEBUGASSERT(!connc->shutdowns.iter_locked); if(connc->shutdowns.iter_locked) @@ -636,9 +635,11 @@ static void connc_shutdown_discard_oldest(struct conncache *connc) e = connc->shutdowns.conn_list.head; if(e) { + SIGPIPE_VARIABLE(pipe_st); conn = e->ptr; Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL); - sigpipe_ignore(connc->closure_handle, &pipe_st); + sigpipe_init(&pipe_st); + sigpipe_apply(connc->closure_handle, &pipe_st); connc_disconnect(NULL, conn, connc, FALSE); sigpipe_restore(&pipe_st); } @@ -900,6 +901,9 @@ static void connc_perform(struct conncache *connc) struct Curl_llist_element *e = connc->shutdowns.conn_list.head; struct Curl_llist_element *enext; struct connectdata *conn; + struct curltime *nowp = NULL; + struct curltime now; + timediff_t next_from_now_ms = 0, ms; bool done; if(!e) @@ -922,9 +926,22 @@ static void connc_perform(struct conncache *connc) Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL); connc_disconnect(NULL, conn, connc, FALSE); } + else { + /* Not done, when does this connection time out? */ + if(!nowp) { + now = Curl_now(); + nowp = &now; + } + ms = Curl_conn_shutdown_timeleft(conn, nowp); + if(ms && ms < next_from_now_ms) + next_from_now_ms = ms; + } e = enext; } connc->shutdowns.iter_locked = FALSE; + + if(next_from_now_ms) + Curl_expire(data, next_from_now_ms, EXPIRE_RUN_NOW); } void Curl_conncache_multi_perform(struct Curl_multi *multi) diff --git a/vendor/curl/lib/connect.c b/vendor/curl/lib/connect.c index 60416292..9b68f15d 100644 --- a/vendor/curl/lib/connect.c +++ b/vendor/curl/lib/connect.c @@ -161,6 +161,7 @@ timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex, struct curltime *nowp) { struct curltime now; + timediff_t left_ms; if(!conn->shutdown.start[sockindex].tv_sec || !conn->shutdown.timeout_ms) return 0; /* not started or no limits */ @@ -169,8 +170,30 @@ timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex, now = Curl_now(); nowp = &now; } - return conn->shutdown.timeout_ms - - Curl_timediff(*nowp, conn->shutdown.start[sockindex]); + left_ms = conn->shutdown.timeout_ms - + Curl_timediff(*nowp, conn->shutdown.start[sockindex]); + return left_ms? left_ms : -1; +} + +timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn, + struct curltime *nowp) +{ + timediff_t left_ms = 0, ms; + struct curltime now; + int i; + + for(i = 0; conn->shutdown.timeout_ms && (i < 2); ++i) { + if(!conn->shutdown.start[i].tv_sec) + continue; + if(!nowp) { + now = Curl_now(); + nowp = &now; + } + ms = Curl_shutdown_timeleft(conn, i, nowp); + if(ms && (!left_ms || ms < left_ms)) + left_ms = ms; + } + return left_ms; } void Curl_shutdown_clear(struct Curl_easy *data, int sockindex) diff --git a/vendor/curl/lib/connect.h b/vendor/curl/lib/connect.h index ffceeb87..e9a4f9c5 100644 --- a/vendor/curl/lib/connect.h +++ b/vendor/curl/lib/connect.h @@ -46,10 +46,15 @@ void Curl_shutdown_start(struct Curl_easy *data, int sockindex, struct curltime *nowp); /* return how much time there is left to shutdown the connection at - * sockindex. */ + * sockindex. Returns 0 if there is no limit or shutdown has not started. */ timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex, struct curltime *nowp); +/* return how much time there is left to shutdown the connection. + * Returns 0 if there is no limit or shutdown has not started. */ +timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn, + struct curltime *nowp); + void Curl_shutdown_clear(struct Curl_easy *data, int sockindex); /* TRUE iff shutdown has been started */ diff --git a/vendor/curl/lib/curl_setup.h b/vendor/curl/lib/curl_setup.h index 1e5371ef..c8dba5e2 100644 --- a/vendor/curl/lib/curl_setup.h +++ b/vendor/curl/lib/curl_setup.h @@ -71,7 +71,9 @@ the necessary dynamic detection features, so the SDK falls back to a codepath that sets both the old and new macro to 1. */ #if defined(TARGET_OS_MAC) && TARGET_OS_MAC && \ - defined(TARGET_OS_OSX) && !TARGET_OS_OSX + defined(TARGET_OS_OSX) && !TARGET_OS_OSX && \ + (!defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE) && \ + (!defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR) #undef TARGET_OS_OSX #define TARGET_OS_OSX TARGET_OS_MAC #endif diff --git a/vendor/curl/lib/easy.c b/vendor/curl/lib/easy.c index 75bf091b..2ba9af0b 100644 --- a/vendor/curl/lib/easy.c +++ b/vendor/curl/lib/easy.c @@ -764,7 +764,8 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) /* assign this after curl_multi_add_handle() */ data->multi_easy = multi; - sigpipe_ignore(data, &pipe_st); + sigpipe_init(&pipe_st); + sigpipe_apply(data, &pipe_st); /* run the transfer */ result = events ? easy_events(multi) : easy_transfer(multi); diff --git a/vendor/curl/lib/escape.c b/vendor/curl/lib/escape.c index 4eb53ad2..1633c2da 100644 --- a/vendor/curl/lib/escape.c +++ b/vendor/curl/lib/escape.c @@ -60,7 +60,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string, struct dynbuf d; (void)data; - if(inlength < 0) + if(!string || (inlength < 0)) return NULL; Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH * 3); @@ -181,7 +181,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string, { char *str = NULL; (void)data; - if(length >= 0) { + if(string && (length >= 0)) { size_t inputlen = (size_t)length; size_t outputlen; CURLcode res = Curl_urldecode(string, inputlen, &str, &outputlen, diff --git a/vendor/curl/lib/multi.c b/vendor/curl/lib/multi.c index 014401cf..896f7304 100644 --- a/vendor/curl/lib/multi.c +++ b/vendor/curl/lib/multi.c @@ -2714,6 +2714,7 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) CURLMcode returncode = CURLM_OK; struct Curl_tree *t; struct curltime now = Curl_now(); + SIGPIPE_VARIABLE(pipe_st); if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -2721,12 +2722,10 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; + sigpipe_init(&pipe_st); data = multi->easyp; if(data) { CURLMcode result; - bool nosig = data->set.no_signal; - SIGPIPE_VARIABLE(pipe_st); - sigpipe_ignore(data, &pipe_st); /* Do the loop and only alter the signal ignore state if the next handle has a different NO_SIGNAL state than the previous */ do { @@ -2734,22 +2733,23 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) pointer now */ struct Curl_easy *datanext = data->next; - if(data->set.no_signal != nosig) { - sigpipe_restore(&pipe_st); - sigpipe_ignore(data, &pipe_st); - nosig = data->set.no_signal; + if(data != multi->conn_cache.closure_handle) { + /* connection cache handle is processed below */ + sigpipe_apply(data, &pipe_st); + result = multi_runsingle(multi, &now, data); + if(result) + returncode = result; } - result = multi_runsingle(multi, &now, data); - if(result) - returncode = result; data = datanext; /* operate on next handle */ } while(data); - sigpipe_restore(&pipe_st); } + sigpipe_apply(multi->conn_cache.closure_handle, &pipe_st); Curl_conncache_multi_perform(multi); + sigpipe_restore(&pipe_st); + /* * Simply remove all expired timers from the splay since handles are dealt * with unconditionally by this function and curl_multi_timeout() requires @@ -2778,7 +2778,8 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) } } while(t); - *running_handles = (int)multi->num_alive; + if(running_handles) + *running_handles = (int)multi->num_alive; if(CURLM_OK >= returncode) returncode = Curl_update_timer(multi); @@ -3188,8 +3189,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi, struct Curl_easy *data = NULL; struct Curl_tree *t; struct curltime now = Curl_now(); - bool first = FALSE; - bool nosig = FALSE; + bool run_conn_cache = FALSE; SIGPIPE_VARIABLE(pipe_st); if(checkall) { @@ -3234,11 +3234,15 @@ static CURLMcode multi_socket(struct Curl_multi *multi, DEBUGASSERT(data); DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER); - if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK)) - /* set socket event bitmask if they are not locked */ - data->state.select_bits |= (unsigned char)ev_bitmask; + if(data == multi->conn_cache.closure_handle) + run_conn_cache = TRUE; + else { + if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK)) + /* set socket event bitmask if they are not locked */ + data->state.select_bits |= (unsigned char)ev_bitmask; - Curl_expire(data, 0, EXPIRE_RUN_NOW); + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } } /* Now we fall-through and do the timer-based stuff, since we do not want @@ -3265,19 +3269,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi, * to process in the splay and 'data' will be re-assigned for every expired * handle we deal with. */ + sigpipe_init(&pipe_st); do { + if(data == multi->conn_cache.closure_handle) + run_conn_cache = TRUE; /* the first loop lap 'data' can be NULL */ - if(data) { - if(!first) { - first = TRUE; - nosig = data->set.no_signal; /* initial state */ - sigpipe_ignore(data, &pipe_st); - } - else if(data->set.no_signal != nosig) { - sigpipe_restore(&pipe_st); - sigpipe_ignore(data, &pipe_st); - nosig = data->set.no_signal; /* remember new state */ - } + else if(data) { + sigpipe_apply(data, &pipe_st); result = multi_runsingle(multi, &now, data); if(CURLM_OK >= result) { @@ -3299,10 +3297,16 @@ static CURLMcode multi_socket(struct Curl_multi *multi, } } while(t); - if(first) - sigpipe_restore(&pipe_st); - *running_handles = (int)multi->num_alive; + if(run_conn_cache) { + sigpipe_apply(multi->conn_cache.closure_handle, &pipe_st); + Curl_conncache_multi_perform(multi); + } + + sigpipe_restore(&pipe_st); + + if(running_handles) + *running_handles = (int)multi->num_alive; return result; } diff --git a/vendor/curl/lib/setup-os400.h b/vendor/curl/lib/setup-os400.h index 9dd546e9..ef7baca6 100644 --- a/vendor/curl/lib/setup-os400.h +++ b/vendor/curl/lib/setup-os400.h @@ -38,6 +38,15 @@ typedef unsigned long u_int32_t; #define isatty(fd) 0 +/* Workaround bug in IBM QADRT runtime library: + * function puts() does not output the implicit trailing newline. + */ + +#include /* Be sure it is loaded. */ +#undef puts +#define puts(s) (fputs((s), stdout) == EOF? EOF: putchar('\n')) + + /* System API wrapper prototypes & definitions to support ASCII parameters. */ #include diff --git a/vendor/curl/lib/sigpipe.h b/vendor/curl/lib/sigpipe.h index 9b29403c..b91a2f51 100644 --- a/vendor/curl/lib/sigpipe.h +++ b/vendor/curl/lib/sigpipe.h @@ -36,6 +36,11 @@ struct sigpipe_ignore { #define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x +static void sigpipe_init(struct sigpipe_ignore *ig) +{ + memset(ig, 0, sizeof(*ig)); +} + /* * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl * internals, and then sigpipe_restore() will restore the situation when we @@ -70,9 +75,20 @@ static void sigpipe_restore(struct sigpipe_ignore *ig) sigaction(SIGPIPE, &ig->old_pipe_act, NULL); } +static void sigpipe_apply(struct Curl_easy *data, + struct sigpipe_ignore *ig) +{ + if(data->set.no_signal != ig->no_signal) { + sigpipe_restore(ig); + sigpipe_ignore(data, ig); + } +} + #else /* for systems without sigaction */ #define sigpipe_ignore(x,y) Curl_nop_stmt +#define sigpipe_apply(x,y) Curl_nop_stmt +#define sigpipe_init(x) Curl_nop_stmt #define sigpipe_restore(x) Curl_nop_stmt #define SIGPIPE_VARIABLE(x) #endif diff --git a/vendor/curl/lib/transfer.c b/vendor/curl/lib/transfer.c index 8d21305a..6c95a471 100644 --- a/vendor/curl/lib/transfer.c +++ b/vendor/curl/lib/transfer.c @@ -281,13 +281,13 @@ static CURLcode readwrite_data(struct Curl_easy *data, buf = xfer_buf; bytestoread = xfer_blen; - if(bytestoread && data->set.max_recv_speed) { + if(bytestoread && data->set.max_recv_speed > 0) { /* In case of speed limit on receiving: if this loop already got * data, break out. If not, limit the amount of bytes to receive. * The overall, timed, speed limiting is done in multi.c */ if(total_received) break; - if((size_t)data->set.max_recv_speed < bytestoread) + if(data->set.max_recv_speed < (curl_off_t)bytestoread) bytestoread = (size_t)data->set.max_recv_speed; } diff --git a/vendor/curl/lib/vtls/mbedtls.c b/vendor/curl/lib/vtls/mbedtls.c index 4f989f2e..2b6042df 100644 --- a/vendor/curl/lib/vtls/mbedtls.c +++ b/vendor/curl/lib/vtls/mbedtls.c @@ -249,8 +249,8 @@ static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = 1024, /* RSA min key len */ }; -/* See https://tls.mbed.org/discussions/generic/ - howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der +/* See https://web.archive.org/web/20200921194007/tls.mbed.org/discussions/ + generic/howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der */ #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) diff --git a/vendor/curl/lib/vtls/openssl.c b/vendor/curl/lib/vtls/openssl.c index 2b60f7fb..8a65491b 100644 --- a/vendor/curl/lib/vtls/openssl.c +++ b/vendor/curl/lib/vtls/openssl.c @@ -231,7 +231,7 @@ /* * Whether SSL_CTX_set1_curves_list is available. * OpenSSL: supported since 1.0.2, see - * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html + * https://docs.openssl.org/master/man3/SSL_CTX_set1_curves/ * BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30) * LibreSSL: since 2.5.3 (April 12, 2017) */ @@ -3244,7 +3244,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, problems with server-sent legacy intermediates. Newer versions of OpenSSL do alternate chain checking by default but we do not know how to determine that in a reliable manner. - https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest + https://web.archive.org/web/20190422050538/ + rt.openssl.org/Ticket/Display.html?id=3621 */ #if defined(X509_V_FLAG_TRUSTED_FIRST) X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); @@ -3567,12 +3568,12 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, CVE-2010-4180 when using previous OpenSSL versions we no longer enable this option regardless of OpenSSL version and SSL_OP_ALL definition. - OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability - (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to - SSL_OP_ALL that _disables_ that work-around despite the fact that - SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to - keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit - must not be set. + OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability: + https://web.archive.org/web/20240114184648/openssl.org/~bodo/tls-cbc.txt. + In 0.9.6e they added a bit to SSL_OP_ALL that _disables_ that work-around + despite the fact that SSL_OP_ALL is documented to do "rather harmless" + workarounds. In order to keep the secure work-around, the + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit must not be set. */ ctx_options = SSL_OP_ALL; @@ -4363,7 +4364,7 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, if(!buff1) break; /* failed */ - /* https://www.openssl.org/docs/crypto/d2i_X509.html */ + /* https://docs.openssl.org/master/man3/d2i_X509/ */ len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp); /* @@ -4975,7 +4976,7 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf, default: /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return value/errno" */ - /* https://www.openssl.org/docs/crypto/ERR_get_error.html */ + /* https://docs.openssl.org/master/man3/ERR_get_error/ */ if(octx->io_result == CURLE_AGAIN) { *curlcode = CURLE_AGAIN; nread = -1; diff --git a/vendor/curl/lib/vtls/vtls.c b/vendor/curl/lib/vtls/vtls.c index 96e7197d..e601f4b1 100644 --- a/vendor/curl/lib/vtls/vtls.c +++ b/vendor/curl/lib/vtls/vtls.c @@ -413,23 +413,6 @@ int Curl_ssl_init(void) return Curl_ssl->init(); } -#if defined(CURL_WITH_MULTI_SSL) -static const struct Curl_ssl Curl_ssl_multi; -#endif - -/* Global cleanup */ -void Curl_ssl_cleanup(void) -{ - if(init_ssl) { - /* only cleanup if we did a previous init */ - Curl_ssl->cleanup(); -#if defined(CURL_WITH_MULTI_SSL) - Curl_ssl = &Curl_ssl_multi; -#endif - init_ssl = FALSE; - } -} - static bool ssl_prefs_check(struct Curl_easy *data) { /* check for CURLOPT_SSLVERSION invalid parameter value */ @@ -1404,6 +1387,19 @@ static const struct Curl_ssl *available_backends[] = { NULL }; +/* Global cleanup */ +void Curl_ssl_cleanup(void) +{ + if(init_ssl) { + /* only cleanup if we did a previous init */ + Curl_ssl->cleanup(); +#if defined(CURL_WITH_MULTI_SSL) + Curl_ssl = &Curl_ssl_multi; +#endif + init_ssl = FALSE; + } +} + static size_t multissl_version(char *buffer, size_t size) { static const struct Curl_ssl *selected; diff --git a/vendor/curl/lib/vtls/wolfssl.c b/vendor/curl/lib/vtls/wolfssl.c index 0ff36d99..2b467c93 100644 --- a/vendor/curl/lib/vtls/wolfssl.c +++ b/vendor/curl/lib/vtls/wolfssl.c @@ -212,7 +212,7 @@ static int do_file_type(const char *type) return -1; } -#ifdef HAVE_LIBOQS +#ifdef WOLFSSL_HAVE_KYBER struct group_name_map { const word16 group; const char *name; @@ -434,10 +434,10 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, } infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); - wssl->x509_store_setup = TRUE; } #endif (void)store; + wssl->x509_store_setup = TRUE; return CURLE_OK; } @@ -571,7 +571,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, bool cache_criteria_met; /* Consider the X509 store cacheable if it comes exclusively from a CAfile, - or no source is provided and we are falling back to OpenSSL's built-in + or no source is provided and we are falling back to wolfSSL's built-in default. */ cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) && conn_config->verifypeer && @@ -580,19 +580,30 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, !ssl_config->primary.CRLfile && !ssl_config->native_ca_store; - cached_store = get_cached_x509_store(cf, data); - if(cached_store && cache_criteria_met - && wolfSSL_X509_STORE_up_ref(cached_store)) { + cached_store = cache_criteria_met ? get_cached_x509_store(cf, data) : NULL; + if(cached_store && wolfSSL_X509_STORE_up_ref(cached_store)) { wolfSSL_CTX_set_cert_store(wssl->ctx, cached_store); } - else { - X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx); + else if(cache_criteria_met) { + /* wolfSSL's initial store in CTX is not shareable by default. + * Make a new one, suitable for adding to the cache. See #14278 */ + X509_STORE *store = wolfSSL_X509_STORE_new(); + if(!store) { + failf(data, "SSL: could not create a X509 store"); + return CURLE_OUT_OF_MEMORY; + } + wolfSSL_CTX_set_cert_store(wssl->ctx, store); result = populate_x509_store(cf, data, store, wssl); - if(result == CURLE_OK && cache_criteria_met) { + if(!result) { set_cached_x509_store(cf, data, store); } } + else { + /* We never share the CTX's store, use it. */ + X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx); + result = populate_x509_store(cf, data, store, wssl); + } return result; } @@ -611,8 +622,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); WOLFSSL_METHOD* req_method = NULL; -#ifdef HAVE_LIBOQS - word16 oqsAlg = 0; +#ifdef WOLFSSL_HAVE_KYBER + word16 pqkem = 0; size_t idx = 0; #endif #ifdef HAVE_SNI @@ -739,15 +750,15 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) curves = conn_config->curves; if(curves) { -#ifdef HAVE_LIBOQS +#ifdef WOLFSSL_HAVE_KYBER for(idx = 0; gnm[idx].name != NULL; idx++) { if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) { - oqsAlg = gnm[idx].group; + pqkem = gnm[idx].group; break; } } - if(oqsAlg == 0) + if(pqkem == 0) #endif { if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) { @@ -821,8 +832,14 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { - CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx, - data->set.ssl.fsslctxp); + CURLcode result; + if(!backend->x509_store_setup) { + result = Curl_wssl_setup_x509_store(cf, data, backend); + if(result) + return result; + } + result = (*data->set.ssl.fsslctx)(data, backend->ctx, + data->set.ssl.fsslctxp); if(result) { failf(data, "error signaled by ssl ctx callback"); return result; @@ -847,10 +864,10 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; } -#ifdef HAVE_LIBOQS - if(oqsAlg) { - if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) { - failf(data, "unable to use oqs KEM"); +#ifdef WOLFSSL_HAVE_KYBER + if(pqkem) { + if(wolfSSL_UseKeyShare(backend->handle, pqkem) != WOLFSSL_SUCCESS) { + failf(data, "unable to use PQ KEM"); } } #endif @@ -1059,15 +1076,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* After having send off the ClientHello, we prepare the x509 * store to verify the coming certificate from the server */ CURLcode result; - struct wolfssl_ctx wssl; - wssl.ctx = backend->ctx; - wssl.handle = backend->handle; - wssl.io_result = CURLE_OK; - wssl.x509_store_setup = FALSE; - result = Curl_wssl_setup_x509_store(cf, data, &wssl); + result = Curl_wssl_setup_x509_store(cf, data, backend); if(result) return result; - backend->x509_store_setup = wssl.x509_store_setup; } connssl->io_need = CURL_SSL_IO_NEED_NONE; diff --git a/vendor/curl/lib/vtls/x509asn1.c b/vendor/curl/lib/vtls/x509asn1.c index 1bc4243d..7f04af3b 100644 --- a/vendor/curl/lib/vtls/x509asn1.c +++ b/vendor/curl/lib/vtls/x509asn1.c @@ -494,7 +494,7 @@ static CURLcode GTime2str(struct dynbuf *store, /* Convert an ASN.1 Generalized time to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ - for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++) + for(fracp = beg; fracp < end && ISDIGIT(*fracp); fracp++) ; /* Get seconds digits. */ @@ -513,32 +513,44 @@ static CURLcode GTime2str(struct dynbuf *store, return CURLE_BAD_FUNCTION_ARGUMENT; } - /* Scan for timezone, measure fractional seconds. */ + /* timezone follows optional fractional seconds. */ tzp = fracp; - fracl = 0; + fracl = 0; /* no fractional seconds detected so far */ if(fracp < end && (*fracp == '.' || *fracp == ',')) { - fracp++; - do + /* Have fractional seconds, e.g. "[.,]\d+". How many? */ + fracp++; /* should be a digit char or BAD ARGUMENT */ + tzp = fracp; + while(tzp < end && ISDIGIT(*tzp)) tzp++; - while(tzp < end && *tzp >= '0' && *tzp <= '9'); - /* Strip leading zeroes in fractional seconds. */ - for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) - ; + if(tzp == fracp) /* never looped, no digit after [.,] */ + return CURLE_BAD_FUNCTION_ARGUMENT; + fracl = tzp - fracp; /* number of fractional sec digits */ + DEBUGASSERT(fracl > 0); + /* Strip trailing zeroes in fractional seconds. + * May reduce fracl to 0 if only '0's are present. */ + while(fracl && fracp[fracl - 1] == '0') + fracl--; } /* Process timezone. */ - if(tzp >= end) - ; /* Nothing to do. */ + if(tzp >= end) { + tzp = ""; + tzl = 0; + } else if(*tzp == 'Z') { - tzp = " GMT"; - end = tzp + 4; + sep = " "; + tzp = "GMT"; + tzl = 3; + } + else if((*tzp == '+') || (*tzp == '-')) { + sep = " UTC"; + tzl = end - tzp; } else { sep = " "; - tzp++; + tzl = end - tzp; } - tzl = end - tzp; return Curl_dyn_addf(store, "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", beg, beg + 4, beg + 6, @@ -547,6 +559,15 @@ static CURLcode GTime2str(struct dynbuf *store, sep, (int)tzl, tzp); } +#ifdef UNITTESTS +/* used by unit1656.c */ +CURLcode Curl_x509_GTime2str(struct dynbuf *store, + const char *beg, const char *end) +{ + return GTime2str(store, beg, end); +} +#endif + /* * Convert an ASN.1 UTC time to a printable string. * diff --git a/vendor/curl/lib/vtls/x509asn1.h b/vendor/curl/lib/vtls/x509asn1.h index 58444604..5b48596c 100644 --- a/vendor/curl/lib/vtls/x509asn1.h +++ b/vendor/curl/lib/vtls/x509asn1.h @@ -77,5 +77,16 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, const char *beg, const char *end); CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data, const char *beg, const char *end); + +#ifdef UNITTESTS +#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ + defined(USE_MBEDTLS) + +/* used by unit1656.c */ +CURLcode Curl_x509_GTime2str(struct dynbuf *store, + const char *beg, const char *end); +#endif +#endif + #endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */ #endif /* HEADER_CURL_X509ASN1_H */