diff options
Diffstat (limited to 'libs/libcurl/src')
190 files changed, 7399 insertions, 7213 deletions
diff --git a/libs/libcurl/src/.checksrc b/libs/libcurl/src/.checksrc index aa8bcffd6f..b3910efdcf 100644 --- a/libs/libcurl/src/.checksrc +++ b/libs/libcurl/src/.checksrc @@ -1,2 +1,5 @@ -enable STRERROR
-enable STRNCPY
+banfunc strerror
+banfunc strncpy
+banfunc sscanf
+banfunc snprintf
+banfunc vsnprint
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt index 6173ceac1b..92e5ca0949 100644 --- a/libs/libcurl/src/CMakeLists.txt +++ b/libs/libcurl/src/CMakeLists.txt @@ -28,7 +28,7 @@ add_definitions("-DBUILDING_LIBCURL") configure_file("curl_config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
# Get 'CSOURCES', 'HHEADERS' variables
-transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
+curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
# DllMain is added later for DLL builds only.
@@ -55,6 +55,9 @@ if(CURL_BUILD_TESTING) )
target_compile_definitions(curlu PUBLIC "UNITTESTS" "CURL_STATICLIB")
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+ # There is plenty of parallelism when building the testdeps target.
+ # Override the curlu batch size with the maximum to optimize performance.
+ set_target_properties(curlu PROPERTIES UNITY_BUILD_BATCH_SIZE 0)
endif()
if(ENABLE_CURLDEBUG)
@@ -65,6 +68,13 @@ endif() ## Library definition
+if(NOT DEFINED IMPORT_LIB_SUFFIX)
+ set(IMPORT_LIB_SUFFIX "")
+endif()
+if(NOT DEFINED STATIC_LIB_SUFFIX)
+ set(STATIC_LIB_SUFFIX "")
+endif()
+
# Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib" (typically with MSVC)
if(WIN32 AND
@@ -105,9 +115,7 @@ if(SHARE_LIB_OBJECT) set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_OBJECT} PROPERTIES
- INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
- INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_OBJECT} INTERFACE
@@ -138,9 +146,7 @@ if(BUILD_STATIC_LIBS) set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_STATIC} PROPERTIES
- INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
- INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ set_target_properties(${LIB_STATIC} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_STATIC} INTERFACE
@@ -177,9 +183,7 @@ if(BUILD_SHARED_LIBS) set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_SHARED} PROPERTIES
- INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
- INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ set_target_properties(${LIB_SHARED} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_SHARED} INTERFACE
@@ -208,7 +212,7 @@ if(BUILD_SHARED_LIBS) if(CURL_LIBCURL_SOVERSION OR CURL_LIBCURL_VERSIONED_SYMBOLS)
# Get 'VERSIONCHANGE', 'VERSIONADD', 'VERSIONDEL', 'VERSIONINFO' variables
- transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
+ curl_transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
math(EXPR _cmakesoname "${VERSIONCHANGE} - ${VERSIONDEL}")
diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am index bb59de5af9..68b770cb68 100644 --- a/libs/libcurl/src/Makefile.am +++ b/libs/libcurl/src/Makefile.am @@ -28,11 +28,9 @@ CMAKE_DIST = CMakeLists.txt curl_config.h.cmake CHECKSRC_DIST = .checksrc vauth/.checksrc vquic/.checksrc vssh/.checksrc \
vtls/.checksrc
-EXTRA_DIST = Makefile.mk config-win32.h config-win32ce.h config-plan9.h \
- config-riscos.h config-mac.h curl_config.h.in config-dos.h libcurl.rc \
- config-amigaos.h config-win32ce.h config-os400.h setup-os400.h \
- $(CMAKE_DIST) setup-win32.h Makefile.soname optiontable.pl libcurl.def \
- $(CHECKSRC_DIST)
+EXTRA_DIST = config-mac.h config-os400.h config-plan9.h config-riscos.h \
+ config-win32.h curl_config.h.in libcurl.rc libcurl.def \
+ $(CMAKE_DIST) Makefile.soname optiontable.pl $(CHECKSRC_DIST)
lib_LTLIBRARIES = libcurl.la
@@ -145,9 +143,10 @@ CS_1 = CS_ = $(CS_0)
checksrc:
- $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
- -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] \
- $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] $(srcdir)/vssh/*.[ch])
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
+ -W$(srcdir)/libcurl_unity.c -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] \
+ $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] \
+ $(srcdir)/vssh/*.[ch])
if DEBUGBUILD
# for debug builds, we scan the sources on all regular make invokes
@@ -155,12 +154,15 @@ all-local: checksrc endif
# disable the tests that are mostly causing false positives
-TIDYFLAGS=-checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet
+TIDYFLAGS := -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling -quiet
+if CURL_WERROR
+TIDYFLAGS += --warnings-as-errors=*
+endif
-TIDY:=clang-tidy
+TIDY := clang-tidy
tidy:
- $(TIDY) $(CSOURCES) $(TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
+ $(TIDY) $(CSOURCES) $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
optiontable:
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index c9cfc9a5d5..75602d81b8 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -149,6 +149,7 @@ host_triplet = @host@ @HAVE_WINDRES_TRUE@@USE_CPPFLAG_CURL_STATICLIB_FALSE@am__append_8 = $(LIB_RCFILES)
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_9 = -DCURL_HIDDEN_SYMBOLS
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_10 = $(CFLAG_CURL_SYMBOL_HIDING)
+@CURL_WERROR_TRUE@am__append_11 = --warnings-as-errors=*
subdir = lib
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/curl-amissl.m4 \
@@ -214,7 +215,7 @@ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
libcurl_la_LIBADD =
am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
- asyn-thread.c base64.c bufq.c bufref.c c-hyper.c cf-h1-proxy.c \
+ asyn-thread.c base64.c bufq.c bufref.c cf-h1-proxy.c \
cf-h2-proxy.c cf-haproxy.c cf-https-connect.c cf-socket.c \
cfilters.c conncache.c connect.c content_encoding.c cookie.c \
curl_addrinfo.c curl_des.c curl_endian.c curl_fnmatch.c \
@@ -227,17 +228,17 @@ am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ getenv.c getinfo.c gopher.c hash.c headers.c hmac.c hostasyn.c \
hostip.c hostip4.c hostip6.c hostsyn.c hsts.c http.c http1.c \
http2.c http_aws_sigv4.c http_chunks.c http_digest.c \
- http_negotiate.c http_ntlm.c http_proxy.c idn.c if2ip.c imap.c \
- inet_ntop.c inet_pton.c krb5.c ldap.c llist.c macos.c md4.c \
- md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c netrc.c \
- nonblock.c noproxy.c openldap.c parsedate.c pingpong.c pop3.c \
- progress.c psl.c rand.c rename.c request.c rtsp.c select.c \
- sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c \
- socketpair.c socks.c socks_gssapi.c socks_sspi.c speedcheck.c \
- splay.c strcase.c strdup.c strerror.c strtok.c strtoofft.c \
- system_win32.c telnet.c tftp.c timediff.c timeval.c transfer.c \
- url.c urlapi.c version.c version_win32.c warnless.c ws.c \
- vauth/cleartext.c vauth/cram.c vauth/digest.c \
+ http_negotiate.c http_ntlm.c http_proxy.c httpsrr.c idn.c \
+ if2ip.c imap.c inet_ntop.c inet_pton.c krb5.c ldap.c llist.c \
+ macos.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c \
+ netrc.c nonblock.c noproxy.c openldap.c parsedate.c pingpong.c \
+ pop3.c progress.c psl.c rand.c rename.c request.c rtsp.c \
+ select.c sendf.c setopt.c sha256.c share.c slist.c smb.c \
+ smtp.c socketpair.c socks.c socks_gssapi.c socks_sspi.c \
+ speedcheck.c splay.c strcase.c strdup.c strerror.c strparse.c \
+ strtok.c strtoofft.c system_win32.c telnet.c tftp.c timediff.c \
+ timeval.c transfer.c url.c urlapi.c version.c version_win32.c \
+ warnless.c ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
vauth/digest_sspi.c vauth/gsasl.c vauth/krb5_gssapi.c \
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c \
vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
@@ -245,11 +246,12 @@ am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ vtls/hostcheck.c vtls/keylog.c vtls/mbedtls.c \
vtls/mbedtls_threadlock.c vtls/openssl.c vtls/rustls.c \
vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
- vtls/vtls.c vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
+ vtls/vtls.c vtls/vtls_scache.c vtls/vtls_spack.c \
+ vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
vquic/curl_ngtcp2.c vquic/curl_osslq.c vquic/curl_quiche.c \
vquic/vquic.c vquic/vquic-tls.c vssh/libssh.c vssh/libssh2.c \
vssh/curl_path.c vssh/wolfssh.c altsvc.h amigaos.h \
- arpa_telnet.h asyn.h bufq.h bufref.h c-hyper.h cf-h1-proxy.h \
+ arpa_telnet.h asyn.h bufq.h bufref.h cf-h1-proxy.h \
cf-h2-proxy.h cf-haproxy.h cf-https-connect.h cf-socket.h \
cfilters.h conncache.h connect.h content_encoding.h cookie.h \
curl_addrinfo.h curl_base64.h curl_ctype.h curl_des.h \
@@ -264,47 +266,48 @@ am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ fopen.h formdata.h ftp.h ftplistparser.h functypes.h getinfo.h \
gopher.h hash.h headers.h hostip.h hsts.h http.h http1.h \
http2.h http_aws_sigv4.h http_chunks.h http_digest.h \
- http_negotiate.h http_ntlm.h http_proxy.h idn.h if2ip.h imap.h \
- inet_ntop.h inet_pton.h llist.h macos.h memdebug.h mime.h \
- mqtt.h multihandle.h multiif.h netrc.h nonblock.h noproxy.h \
- parsedate.h pingpong.h pop3.h progress.h psl.h rand.h rename.h \
- request.h rtsp.h select.h sendf.h setopt.h setup-vms.h share.h \
+ http_negotiate.h http_ntlm.h http_proxy.h httpsrr.h idn.h \
+ if2ip.h imap.h inet_ntop.h inet_pton.h llist.h macos.h \
+ memdebug.h mime.h mqtt.h multihandle.h multiif.h netrc.h \
+ nonblock.h noproxy.h parsedate.h pingpong.h pop3.h progress.h \
+ psl.h rand.h rename.h request.h rtsp.h select.h sendf.h \
+ setopt.h setup-os400.h setup-vms.h setup-win32.h share.h \
sigpipe.h slist.h smb.h smtp.h sockaddr.h socketpair.h socks.h \
- speedcheck.h splay.h strcase.h strdup.h strerror.h strtok.h \
- strtoofft.h system_win32.h telnet.h tftp.h timediff.h \
+ speedcheck.h splay.h strcase.h strdup.h strerror.h strparse.h \
+ strtok.h strtoofft.h system_win32.h telnet.h tftp.h timediff.h \
timeval.h transfer.h url.h urlapi-int.h urldata.h \
version_win32.h warnless.h ws.h vauth/digest.h vauth/ntlm.h \
vauth/vauth.h vtls/bearssl.h vtls/cipher_suite.h vtls/gtls.h \
vtls/hostcheck.h vtls/keylog.h vtls/mbedtls.h \
vtls/mbedtls_threadlock.h vtls/openssl.h vtls/rustls.h \
vtls/schannel.h vtls/schannel_int.h vtls/sectransp.h \
- vtls/vtls.h vtls/vtls_int.h vtls/wolfssl.h vtls/x509asn1.h \
+ vtls/vtls.h vtls/vtls_int.h vtls/vtls_scache.h \
+ vtls/vtls_spack.h vtls/wolfssl.h vtls/x509asn1.h \
vquic/curl_msh3.h vquic/curl_ngtcp2.h vquic/curl_osslq.h \
vquic/curl_quiche.h vquic/vquic.h vquic/vquic_int.h \
vquic/vquic-tls.h vssh/curl_path.h vssh/ssh.h libcurl.rc
am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \
libcurl_la-asyn-ares.lo libcurl_la-asyn-thread.lo \
libcurl_la-base64.lo libcurl_la-bufq.lo libcurl_la-bufref.lo \
- libcurl_la-c-hyper.lo libcurl_la-cf-h1-proxy.lo \
- libcurl_la-cf-h2-proxy.lo libcurl_la-cf-haproxy.lo \
- libcurl_la-cf-https-connect.lo libcurl_la-cf-socket.lo \
- libcurl_la-cfilters.lo libcurl_la-conncache.lo \
- libcurl_la-connect.lo libcurl_la-content_encoding.lo \
- libcurl_la-cookie.lo libcurl_la-curl_addrinfo.lo \
- libcurl_la-curl_des.lo libcurl_la-curl_endian.lo \
- libcurl_la-curl_fnmatch.lo libcurl_la-curl_get_line.lo \
- libcurl_la-curl_gethostname.lo libcurl_la-curl_gssapi.lo \
- libcurl_la-curl_memrchr.lo libcurl_la-curl_multibyte.lo \
- libcurl_la-curl_ntlm_core.lo libcurl_la-curl_range.lo \
- libcurl_la-curl_rtmp.lo libcurl_la-curl_sasl.lo \
- libcurl_la-curl_sha512_256.lo libcurl_la-curl_sspi.lo \
- libcurl_la-curl_threads.lo libcurl_la-curl_trc.lo \
- libcurl_la-cw-out.lo libcurl_la-dict.lo libcurl_la-dllmain.lo \
- libcurl_la-doh.lo libcurl_la-dynbuf.lo libcurl_la-dynhds.lo \
- libcurl_la-easy.lo libcurl_la-easygetopt.lo \
- libcurl_la-easyoptions.lo libcurl_la-escape.lo \
- libcurl_la-file.lo libcurl_la-fileinfo.lo libcurl_la-fopen.lo \
- libcurl_la-formdata.lo libcurl_la-ftp.lo \
+ libcurl_la-cf-h1-proxy.lo libcurl_la-cf-h2-proxy.lo \
+ libcurl_la-cf-haproxy.lo libcurl_la-cf-https-connect.lo \
+ libcurl_la-cf-socket.lo libcurl_la-cfilters.lo \
+ libcurl_la-conncache.lo libcurl_la-connect.lo \
+ libcurl_la-content_encoding.lo libcurl_la-cookie.lo \
+ libcurl_la-curl_addrinfo.lo libcurl_la-curl_des.lo \
+ libcurl_la-curl_endian.lo libcurl_la-curl_fnmatch.lo \
+ libcurl_la-curl_get_line.lo libcurl_la-curl_gethostname.lo \
+ libcurl_la-curl_gssapi.lo libcurl_la-curl_memrchr.lo \
+ libcurl_la-curl_multibyte.lo libcurl_la-curl_ntlm_core.lo \
+ libcurl_la-curl_range.lo libcurl_la-curl_rtmp.lo \
+ libcurl_la-curl_sasl.lo libcurl_la-curl_sha512_256.lo \
+ libcurl_la-curl_sspi.lo libcurl_la-curl_threads.lo \
+ libcurl_la-curl_trc.lo libcurl_la-cw-out.lo libcurl_la-dict.lo \
+ libcurl_la-dllmain.lo libcurl_la-doh.lo libcurl_la-dynbuf.lo \
+ libcurl_la-dynhds.lo libcurl_la-easy.lo \
+ libcurl_la-easygetopt.lo libcurl_la-easyoptions.lo \
+ libcurl_la-escape.lo libcurl_la-file.lo libcurl_la-fileinfo.lo \
+ libcurl_la-fopen.lo libcurl_la-formdata.lo libcurl_la-ftp.lo \
libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \
libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \
libcurl_la-headers.lo libcurl_la-hmac.lo \
@@ -315,11 +318,11 @@ am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \ libcurl_la-http_aws_sigv4.lo libcurl_la-http_chunks.lo \
libcurl_la-http_digest.lo libcurl_la-http_negotiate.lo \
libcurl_la-http_ntlm.lo libcurl_la-http_proxy.lo \
- libcurl_la-idn.lo libcurl_la-if2ip.lo libcurl_la-imap.lo \
- libcurl_la-inet_ntop.lo libcurl_la-inet_pton.lo \
- libcurl_la-krb5.lo libcurl_la-ldap.lo libcurl_la-llist.lo \
- libcurl_la-macos.lo libcurl_la-md4.lo libcurl_la-md5.lo \
- libcurl_la-memdebug.lo libcurl_la-mime.lo \
+ libcurl_la-httpsrr.lo libcurl_la-idn.lo libcurl_la-if2ip.lo \
+ libcurl_la-imap.lo libcurl_la-inet_ntop.lo \
+ libcurl_la-inet_pton.lo libcurl_la-krb5.lo libcurl_la-ldap.lo \
+ libcurl_la-llist.lo libcurl_la-macos.lo libcurl_la-md4.lo \
+ libcurl_la-md5.lo libcurl_la-memdebug.lo libcurl_la-mime.lo \
libcurl_la-mprintf.lo libcurl_la-mqtt.lo libcurl_la-multi.lo \
libcurl_la-netrc.lo libcurl_la-nonblock.lo \
libcurl_la-noproxy.lo libcurl_la-openldap.lo \
@@ -333,9 +336,10 @@ am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \ libcurl_la-socks_gssapi.lo libcurl_la-socks_sspi.lo \
libcurl_la-speedcheck.lo libcurl_la-splay.lo \
libcurl_la-strcase.lo libcurl_la-strdup.lo \
- libcurl_la-strerror.lo libcurl_la-strtok.lo \
- libcurl_la-strtoofft.lo libcurl_la-system_win32.lo \
- libcurl_la-telnet.lo libcurl_la-tftp.lo libcurl_la-timediff.lo \
+ libcurl_la-strerror.lo libcurl_la-strparse.lo \
+ libcurl_la-strtok.lo libcurl_la-strtoofft.lo \
+ libcurl_la-system_win32.lo libcurl_la-telnet.lo \
+ libcurl_la-tftp.lo libcurl_la-timediff.lo \
libcurl_la-timeval.lo libcurl_la-transfer.lo libcurl_la-url.lo \
libcurl_la-urlapi.lo libcurl_la-version.lo \
libcurl_la-version_win32.lo libcurl_la-warnless.lo \
@@ -356,6 +360,7 @@ am__objects_3 = vtls/libcurl_la-bearssl.lo \ vtls/libcurl_la-openssl.lo vtls/libcurl_la-rustls.lo \
vtls/libcurl_la-schannel.lo vtls/libcurl_la-schannel_verify.lo \
vtls/libcurl_la-sectransp.lo vtls/libcurl_la-vtls.lo \
+ vtls/libcurl_la-vtls_scache.lo vtls/libcurl_la-vtls_spack.lo \
vtls/libcurl_la-wolfssl.lo vtls/libcurl_la-x509asn1.lo
am__objects_4 = vquic/libcurl_la-curl_msh3.lo \
vquic/libcurl_la-curl_ngtcp2.lo vquic/libcurl_la-curl_osslq.lo \
@@ -393,7 +398,7 @@ libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(CFLAGS) $(libcurl_la_LDFLAGS) $(LDFLAGS) -o $@
libcurlu_la_LIBADD =
am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
- asyn-thread.c base64.c bufq.c bufref.c c-hyper.c cf-h1-proxy.c \
+ asyn-thread.c base64.c bufq.c bufref.c cf-h1-proxy.c \
cf-h2-proxy.c cf-haproxy.c cf-https-connect.c cf-socket.c \
cfilters.c conncache.c connect.c content_encoding.c cookie.c \
curl_addrinfo.c curl_des.c curl_endian.c curl_fnmatch.c \
@@ -406,17 +411,17 @@ am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ getenv.c getinfo.c gopher.c hash.c headers.c hmac.c hostasyn.c \
hostip.c hostip4.c hostip6.c hostsyn.c hsts.c http.c http1.c \
http2.c http_aws_sigv4.c http_chunks.c http_digest.c \
- http_negotiate.c http_ntlm.c http_proxy.c idn.c if2ip.c imap.c \
- inet_ntop.c inet_pton.c krb5.c ldap.c llist.c macos.c md4.c \
- md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c netrc.c \
- nonblock.c noproxy.c openldap.c parsedate.c pingpong.c pop3.c \
- progress.c psl.c rand.c rename.c request.c rtsp.c select.c \
- sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c \
- socketpair.c socks.c socks_gssapi.c socks_sspi.c speedcheck.c \
- splay.c strcase.c strdup.c strerror.c strtok.c strtoofft.c \
- system_win32.c telnet.c tftp.c timediff.c timeval.c transfer.c \
- url.c urlapi.c version.c version_win32.c warnless.c ws.c \
- vauth/cleartext.c vauth/cram.c vauth/digest.c \
+ http_negotiate.c http_ntlm.c http_proxy.c httpsrr.c idn.c \
+ if2ip.c imap.c inet_ntop.c inet_pton.c krb5.c ldap.c llist.c \
+ macos.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c \
+ netrc.c nonblock.c noproxy.c openldap.c parsedate.c pingpong.c \
+ pop3.c progress.c psl.c rand.c rename.c request.c rtsp.c \
+ select.c sendf.c setopt.c sha256.c share.c slist.c smb.c \
+ smtp.c socketpair.c socks.c socks_gssapi.c socks_sspi.c \
+ speedcheck.c splay.c strcase.c strdup.c strerror.c strparse.c \
+ strtok.c strtoofft.c system_win32.c telnet.c tftp.c timediff.c \
+ timeval.c transfer.c url.c urlapi.c version.c version_win32.c \
+ warnless.c ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
vauth/digest_sspi.c vauth/gsasl.c vauth/krb5_gssapi.c \
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c \
vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
@@ -424,11 +429,12 @@ am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ vtls/hostcheck.c vtls/keylog.c vtls/mbedtls.c \
vtls/mbedtls_threadlock.c vtls/openssl.c vtls/rustls.c \
vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
- vtls/vtls.c vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
+ vtls/vtls.c vtls/vtls_scache.c vtls/vtls_spack.c \
+ vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
vquic/curl_ngtcp2.c vquic/curl_osslq.c vquic/curl_quiche.c \
vquic/vquic.c vquic/vquic-tls.c vssh/libssh.c vssh/libssh2.c \
vssh/curl_path.c vssh/wolfssh.c altsvc.h amigaos.h \
- arpa_telnet.h asyn.h bufq.h bufref.h c-hyper.h cf-h1-proxy.h \
+ arpa_telnet.h asyn.h bufq.h bufref.h cf-h1-proxy.h \
cf-h2-proxy.h cf-haproxy.h cf-https-connect.h cf-socket.h \
cfilters.h conncache.h connect.h content_encoding.h cookie.h \
curl_addrinfo.h curl_base64.h curl_ctype.h curl_des.h \
@@ -443,43 +449,45 @@ am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \ fopen.h formdata.h ftp.h ftplistparser.h functypes.h getinfo.h \
gopher.h hash.h headers.h hostip.h hsts.h http.h http1.h \
http2.h http_aws_sigv4.h http_chunks.h http_digest.h \
- http_negotiate.h http_ntlm.h http_proxy.h idn.h if2ip.h imap.h \
- inet_ntop.h inet_pton.h llist.h macos.h memdebug.h mime.h \
- mqtt.h multihandle.h multiif.h netrc.h nonblock.h noproxy.h \
- parsedate.h pingpong.h pop3.h progress.h psl.h rand.h rename.h \
- request.h rtsp.h select.h sendf.h setopt.h setup-vms.h share.h \
+ http_negotiate.h http_ntlm.h http_proxy.h httpsrr.h idn.h \
+ if2ip.h imap.h inet_ntop.h inet_pton.h llist.h macos.h \
+ memdebug.h mime.h mqtt.h multihandle.h multiif.h netrc.h \
+ nonblock.h noproxy.h parsedate.h pingpong.h pop3.h progress.h \
+ psl.h rand.h rename.h request.h rtsp.h select.h sendf.h \
+ setopt.h setup-os400.h setup-vms.h setup-win32.h share.h \
sigpipe.h slist.h smb.h smtp.h sockaddr.h socketpair.h socks.h \
- speedcheck.h splay.h strcase.h strdup.h strerror.h strtok.h \
- strtoofft.h system_win32.h telnet.h tftp.h timediff.h \
+ speedcheck.h splay.h strcase.h strdup.h strerror.h strparse.h \
+ strtok.h strtoofft.h system_win32.h telnet.h tftp.h timediff.h \
timeval.h transfer.h url.h urlapi-int.h urldata.h \
version_win32.h warnless.h ws.h vauth/digest.h vauth/ntlm.h \
vauth/vauth.h vtls/bearssl.h vtls/cipher_suite.h vtls/gtls.h \
vtls/hostcheck.h vtls/keylog.h vtls/mbedtls.h \
vtls/mbedtls_threadlock.h vtls/openssl.h vtls/rustls.h \
vtls/schannel.h vtls/schannel_int.h vtls/sectransp.h \
- vtls/vtls.h vtls/vtls_int.h vtls/wolfssl.h vtls/x509asn1.h \
+ vtls/vtls.h vtls/vtls_int.h vtls/vtls_scache.h \
+ vtls/vtls_spack.h vtls/wolfssl.h vtls/x509asn1.h \
vquic/curl_msh3.h vquic/curl_ngtcp2.h vquic/curl_osslq.h \
vquic/curl_quiche.h vquic/vquic.h vquic/vquic_int.h \
vquic/vquic-tls.h vssh/curl_path.h vssh/ssh.h
am__objects_13 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \
libcurlu_la-base64.lo libcurlu_la-bufq.lo \
- libcurlu_la-bufref.lo libcurlu_la-c-hyper.lo \
- libcurlu_la-cf-h1-proxy.lo libcurlu_la-cf-h2-proxy.lo \
- libcurlu_la-cf-haproxy.lo libcurlu_la-cf-https-connect.lo \
- libcurlu_la-cf-socket.lo libcurlu_la-cfilters.lo \
- libcurlu_la-conncache.lo libcurlu_la-connect.lo \
- libcurlu_la-content_encoding.lo libcurlu_la-cookie.lo \
- libcurlu_la-curl_addrinfo.lo libcurlu_la-curl_des.lo \
- libcurlu_la-curl_endian.lo libcurlu_la-curl_fnmatch.lo \
- libcurlu_la-curl_get_line.lo libcurlu_la-curl_gethostname.lo \
- libcurlu_la-curl_gssapi.lo libcurlu_la-curl_memrchr.lo \
- libcurlu_la-curl_multibyte.lo libcurlu_la-curl_ntlm_core.lo \
- libcurlu_la-curl_range.lo libcurlu_la-curl_rtmp.lo \
- libcurlu_la-curl_sasl.lo libcurlu_la-curl_sha512_256.lo \
- libcurlu_la-curl_sspi.lo libcurlu_la-curl_threads.lo \
- libcurlu_la-curl_trc.lo libcurlu_la-cw-out.lo \
- libcurlu_la-dict.lo libcurlu_la-dllmain.lo libcurlu_la-doh.lo \
+ libcurlu_la-bufref.lo libcurlu_la-cf-h1-proxy.lo \
+ libcurlu_la-cf-h2-proxy.lo libcurlu_la-cf-haproxy.lo \
+ libcurlu_la-cf-https-connect.lo libcurlu_la-cf-socket.lo \
+ libcurlu_la-cfilters.lo libcurlu_la-conncache.lo \
+ libcurlu_la-connect.lo libcurlu_la-content_encoding.lo \
+ libcurlu_la-cookie.lo libcurlu_la-curl_addrinfo.lo \
+ libcurlu_la-curl_des.lo libcurlu_la-curl_endian.lo \
+ libcurlu_la-curl_fnmatch.lo libcurlu_la-curl_get_line.lo \
+ libcurlu_la-curl_gethostname.lo libcurlu_la-curl_gssapi.lo \
+ libcurlu_la-curl_memrchr.lo libcurlu_la-curl_multibyte.lo \
+ libcurlu_la-curl_ntlm_core.lo libcurlu_la-curl_range.lo \
+ libcurlu_la-curl_rtmp.lo libcurlu_la-curl_sasl.lo \
+ libcurlu_la-curl_sha512_256.lo libcurlu_la-curl_sspi.lo \
+ libcurlu_la-curl_threads.lo libcurlu_la-curl_trc.lo \
+ libcurlu_la-cw-out.lo libcurlu_la-dict.lo \
+ libcurlu_la-dllmain.lo libcurlu_la-doh.lo \
libcurlu_la-dynbuf.lo libcurlu_la-dynhds.lo \
libcurlu_la-easy.lo libcurlu_la-easygetopt.lo \
libcurlu_la-easyoptions.lo libcurlu_la-escape.lo \
@@ -496,12 +504,12 @@ am__objects_13 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \ libcurlu_la-http_aws_sigv4.lo libcurlu_la-http_chunks.lo \
libcurlu_la-http_digest.lo libcurlu_la-http_negotiate.lo \
libcurlu_la-http_ntlm.lo libcurlu_la-http_proxy.lo \
- libcurlu_la-idn.lo libcurlu_la-if2ip.lo libcurlu_la-imap.lo \
- libcurlu_la-inet_ntop.lo libcurlu_la-inet_pton.lo \
- libcurlu_la-krb5.lo libcurlu_la-ldap.lo libcurlu_la-llist.lo \
- libcurlu_la-macos.lo libcurlu_la-md4.lo libcurlu_la-md5.lo \
- libcurlu_la-memdebug.lo libcurlu_la-mime.lo \
- libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \
+ libcurlu_la-httpsrr.lo libcurlu_la-idn.lo libcurlu_la-if2ip.lo \
+ libcurlu_la-imap.lo libcurlu_la-inet_ntop.lo \
+ libcurlu_la-inet_pton.lo libcurlu_la-krb5.lo \
+ libcurlu_la-ldap.lo libcurlu_la-llist.lo libcurlu_la-macos.lo \
+ libcurlu_la-md4.lo libcurlu_la-md5.lo libcurlu_la-memdebug.lo \
+ libcurlu_la-mime.lo libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \
libcurlu_la-multi.lo libcurlu_la-netrc.lo \
libcurlu_la-nonblock.lo libcurlu_la-noproxy.lo \
libcurlu_la-openldap.lo libcurlu_la-parsedate.lo \
@@ -516,13 +524,14 @@ am__objects_13 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \ libcurlu_la-socks_sspi.lo libcurlu_la-speedcheck.lo \
libcurlu_la-splay.lo libcurlu_la-strcase.lo \
libcurlu_la-strdup.lo libcurlu_la-strerror.lo \
- libcurlu_la-strtok.lo libcurlu_la-strtoofft.lo \
- libcurlu_la-system_win32.lo libcurlu_la-telnet.lo \
- libcurlu_la-tftp.lo libcurlu_la-timediff.lo \
- libcurlu_la-timeval.lo libcurlu_la-transfer.lo \
- libcurlu_la-url.lo libcurlu_la-urlapi.lo \
- libcurlu_la-version.lo libcurlu_la-version_win32.lo \
- libcurlu_la-warnless.lo libcurlu_la-ws.lo
+ libcurlu_la-strparse.lo libcurlu_la-strtok.lo \
+ libcurlu_la-strtoofft.lo libcurlu_la-system_win32.lo \
+ libcurlu_la-telnet.lo libcurlu_la-tftp.lo \
+ libcurlu_la-timediff.lo libcurlu_la-timeval.lo \
+ libcurlu_la-transfer.lo libcurlu_la-url.lo \
+ libcurlu_la-urlapi.lo libcurlu_la-version.lo \
+ libcurlu_la-version_win32.lo libcurlu_la-warnless.lo \
+ libcurlu_la-ws.lo
am__objects_14 = vauth/libcurlu_la-cleartext.lo \
vauth/libcurlu_la-cram.lo vauth/libcurlu_la-digest.lo \
vauth/libcurlu_la-digest_sspi.lo vauth/libcurlu_la-gsasl.lo \
@@ -540,6 +549,7 @@ am__objects_15 = vtls/libcurlu_la-bearssl.lo \ vtls/libcurlu_la-schannel.lo \
vtls/libcurlu_la-schannel_verify.lo \
vtls/libcurlu_la-sectransp.lo vtls/libcurlu_la-vtls.lo \
+ vtls/libcurlu_la-vtls_scache.lo vtls/libcurlu_la-vtls_spack.lo \
vtls/libcurlu_la-wolfssl.lo vtls/libcurlu_la-x509asn1.lo
am__objects_16 = vquic/libcurlu_la-curl_msh3.lo \
vquic/libcurlu_la-curl_ngtcp2.lo \
@@ -590,7 +600,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-base64.Plo \
./$(DEPDIR)/libcurl_la-bufq.Plo \
./$(DEPDIR)/libcurl_la-bufref.Plo \
- ./$(DEPDIR)/libcurl_la-c-hyper.Plo \
./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo \
./$(DEPDIR)/libcurl_la-cf-h2-proxy.Plo \
./$(DEPDIR)/libcurl_la-cf-haproxy.Plo \
@@ -655,6 +664,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-http_negotiate.Plo \
./$(DEPDIR)/libcurl_la-http_ntlm.Plo \
./$(DEPDIR)/libcurl_la-http_proxy.Plo \
+ ./$(DEPDIR)/libcurl_la-httpsrr.Plo \
./$(DEPDIR)/libcurl_la-idn.Plo \
./$(DEPDIR)/libcurl_la-if2ip.Plo \
./$(DEPDIR)/libcurl_la-imap.Plo \
@@ -699,6 +709,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-strcase.Plo \
./$(DEPDIR)/libcurl_la-strdup.Plo \
./$(DEPDIR)/libcurl_la-strerror.Plo \
+ ./$(DEPDIR)/libcurl_la-strparse.Plo \
./$(DEPDIR)/libcurl_la-strtok.Plo \
./$(DEPDIR)/libcurl_la-strtoofft.Plo \
./$(DEPDIR)/libcurl_la-system_win32.Plo \
@@ -720,7 +731,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-base64.Plo \
./$(DEPDIR)/libcurlu_la-bufq.Plo \
./$(DEPDIR)/libcurlu_la-bufref.Plo \
- ./$(DEPDIR)/libcurlu_la-c-hyper.Plo \
./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo \
./$(DEPDIR)/libcurlu_la-cf-h2-proxy.Plo \
./$(DEPDIR)/libcurlu_la-cf-haproxy.Plo \
@@ -785,6 +795,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo \
./$(DEPDIR)/libcurlu_la-http_ntlm.Plo \
./$(DEPDIR)/libcurlu_la-http_proxy.Plo \
+ ./$(DEPDIR)/libcurlu_la-httpsrr.Plo \
./$(DEPDIR)/libcurlu_la-idn.Plo \
./$(DEPDIR)/libcurlu_la-if2ip.Plo \
./$(DEPDIR)/libcurlu_la-imap.Plo \
@@ -832,6 +843,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-strcase.Plo \
./$(DEPDIR)/libcurlu_la-strdup.Plo \
./$(DEPDIR)/libcurlu_la-strerror.Plo \
+ ./$(DEPDIR)/libcurlu_la-strparse.Plo \
./$(DEPDIR)/libcurlu_la-strtok.Plo \
./$(DEPDIR)/libcurlu_la-strtoofft.Plo \
./$(DEPDIR)/libcurlu_la-system_win32.Plo \
@@ -905,6 +917,8 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo \
vtls/$(DEPDIR)/libcurl_la-sectransp.Plo \
vtls/$(DEPDIR)/libcurl_la-vtls.Plo \
+ vtls/$(DEPDIR)/libcurl_la-vtls_scache.Plo \
+ vtls/$(DEPDIR)/libcurl_la-vtls_spack.Plo \
vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo \
vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo \
vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo \
@@ -920,6 +934,8 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo \
vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo \
vtls/$(DEPDIR)/libcurlu_la-vtls.Plo \
+ vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Plo \
+ vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Plo \
vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo \
vtls/$(DEPDIR)/libcurlu_la-x509asn1.Plo
am__mv = mv -f
@@ -975,7 +991,6 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-APACHECTL = @APACHECTL@
APXS = @APXS@
AR = @AR@
AR_FLAGS = @AR_FLAGS@
@@ -1002,31 +1017,10 @@ CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ CURL_CA_EMBED = @CURL_CA_EMBED@
CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@
CURL_CPP = @CURL_CPP@
-CURL_DISABLE_DICT = @CURL_DISABLE_DICT@
-CURL_DISABLE_FILE = @CURL_DISABLE_FILE@
-CURL_DISABLE_FTP = @CURL_DISABLE_FTP@
-CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@
-CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@
-CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@
-CURL_DISABLE_IPFS = @CURL_DISABLE_IPFS@
-CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@
-CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@
-CURL_DISABLE_MQTT = @CURL_DISABLE_MQTT@
-CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@
-CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@
-CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@
-CURL_DISABLE_SMB = @CURL_DISABLE_SMB@
-CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@
-CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@
-CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@
-CURL_DISABLE_WEBSOCKETS = @CURL_DISABLE_WEBSOCKETS@
CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX = @CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX@
CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME = @CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME@
CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@
-CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@
-CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@
CYGPATH_W = @CYGPATH_W@
-DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
@@ -1045,22 +1039,14 @@ FILECMD = @FILECMD@ FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
GCOV = @GCOV@
GREP = @GREP@
-HAVE_BROTLI = @HAVE_BROTLI@
-HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@
-HAVE_LDAP_SSL = @HAVE_LDAP_SSL@
HAVE_LIBZ = @HAVE_LIBZ@
-HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@
-HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@
-HAVE_ZSTD = @HAVE_ZSTD@
HTTPD = @HTTPD@
HTTPD_NGHTTPX = @HTTPD_NGHTTPX@
-IDN_ENABLED = @IDN_ENABLED@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-IPV6_ENABLED = @IPV6_ENABLED@
LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
@@ -1099,9 +1085,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
-PKGADD_NAME = @PKGADD_NAME@
-PKGADD_PKG = @PKGADD_PKG@
-PKGADD_VENDOR = @PKGADD_VENDOR@
PKGCONFIG = @PKGCONFIG@
RANLIB = @RANLIB@
RC = @RC@
@@ -1109,46 +1092,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SSL_BACKENDS = @SSL_BACKENDS@
-SSL_ENABLED = @SSL_ENABLED@
-SSL_LIBS = @SSL_LIBS@
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
TEST_NGHTTPX = @TEST_NGHTTPX@
-USE_APPLE_IDN = @USE_APPLE_IDN@
-USE_ARES = @USE_ARES@
-USE_BEARSSL = @USE_BEARSSL@
-USE_GNUTLS = @USE_GNUTLS@
-USE_HYPER = @USE_HYPER@
-USE_LIBPSL = @USE_LIBPSL@
-USE_LIBRTMP = @USE_LIBRTMP@
-USE_LIBSSH = @USE_LIBSSH@
-USE_LIBSSH2 = @USE_LIBSSH2@
-USE_LIBUV = @USE_LIBUV@
-USE_MBEDTLS = @USE_MBEDTLS@
-USE_MSH3 = @USE_MSH3@
-USE_NGHTTP2 = @USE_NGHTTP2@
-USE_NGHTTP3 = @USE_NGHTTP3@
-USE_NGTCP2 = @USE_NGTCP2@
-USE_NGTCP2_CRYPTO_BORINGSSL = @USE_NGTCP2_CRYPTO_BORINGSSL@
-USE_NGTCP2_CRYPTO_GNUTLS = @USE_NGTCP2_CRYPTO_GNUTLS@
-USE_NGTCP2_CRYPTO_QUICTLS = @USE_NGTCP2_CRYPTO_QUICTLS@
-USE_NGTCP2_CRYPTO_WOLFSSL = @USE_NGTCP2_CRYPTO_WOLFSSL@
-USE_NGTCP2_H3 = @USE_NGTCP2_H3@
-USE_OPENLDAP = @USE_OPENLDAP@
-USE_OPENSSL_H3 = @USE_OPENSSL_H3@
-USE_OPENSSL_QUIC = @USE_OPENSSL_QUIC@
-USE_QUICHE = @USE_QUICHE@
-USE_RUSTLS = @USE_RUSTLS@
-USE_SCHANNEL = @USE_SCHANNEL@
-USE_SECTRANSP = @USE_SECTRANSP@
-USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
-USE_WIN32_CRYPTO = @USE_WIN32_CRYPTO@
-USE_WIN32_LARGE_FILES = @USE_WIN32_LARGE_FILES@
-USE_WIN32_SMALL_FILES = @USE_WIN32_SMALL_FILES@
-USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
-USE_WOLFSSH = @USE_WOLFSSH@
-USE_WOLFSSL = @USE_WOLFSSL@
VERSION = @VERSION@
VERSIONNUM = @VERSIONNUM@
VSFTPD = @VSFTPD@
@@ -1237,11 +1184,9 @@ CMAKE_DIST = CMakeLists.txt curl_config.h.cmake CHECKSRC_DIST = .checksrc vauth/.checksrc vquic/.checksrc vssh/.checksrc \
vtls/.checksrc
-EXTRA_DIST = Makefile.mk config-win32.h config-win32ce.h config-plan9.h \
- config-riscos.h config-mac.h curl_config.h.in config-dos.h libcurl.rc \
- config-amigaos.h config-win32ce.h config-os400.h setup-os400.h \
- $(CMAKE_DIST) setup-win32.h Makefile.soname optiontable.pl libcurl.def \
- $(CHECKSRC_DIST)
+EXTRA_DIST = config-mac.h config-os400.h config-plan9.h config-riscos.h \
+ config-win32.h curl_config.h.in libcurl.rc libcurl.def \
+ $(CMAKE_DIST) Makefile.soname optiontable.pl $(CHECKSRC_DIST)
lib_LTLIBRARIES = libcurl.la
@BUILD_UNITTESTS_FALSE@noinst_LTLIBRARIES =
@@ -1301,6 +1246,8 @@ LIB_VTLS_CFILES = \ vtls/schannel_verify.c \
vtls/sectransp.c \
vtls/vtls.c \
+ vtls/vtls_scache.c \
+ vtls/vtls_spack.c \
vtls/wolfssl.c \
vtls/x509asn1.c
@@ -1319,6 +1266,8 @@ LIB_VTLS_HFILES = \ vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
+ vtls/vtls_scache.h \
+ vtls/vtls_spack.h \
vtls/wolfssl.h \
vtls/x509asn1.h
@@ -1357,7 +1306,6 @@ LIB_CFILES = \ base64.c \
bufq.c \
bufref.c \
- c-hyper.c \
cf-h1-proxy.c \
cf-h2-proxy.c \
cf-haproxy.c \
@@ -1422,6 +1370,7 @@ LIB_CFILES = \ http_negotiate.c \
http_ntlm.c \
http_proxy.c \
+ httpsrr.c \
idn.c \
if2ip.c \
imap.c \
@@ -1468,6 +1417,7 @@ LIB_CFILES = \ strcase.c \
strdup.c \
strerror.c \
+ strparse.c \
strtok.c \
strtoofft.c \
system_win32.c \
@@ -1490,7 +1440,6 @@ LIB_HFILES = \ asyn.h \
bufq.h \
bufref.h \
- c-hyper.h \
cf-h1-proxy.h \
cf-h2-proxy.h \
cf-haproxy.h \
@@ -1562,6 +1511,7 @@ LIB_HFILES = \ http_negotiate.h \
http_ntlm.h \
http_proxy.h \
+ httpsrr.h \
idn.h \
if2ip.h \
imap.h \
@@ -1589,7 +1539,9 @@ LIB_HFILES = \ select.h \
sendf.h \
setopt.h \
+ setup-os400.h \
setup-vms.h \
+ setup-win32.h \
share.h \
sigpipe.h \
slist.h \
@@ -1603,6 +1555,7 @@ LIB_HFILES = \ strcase.h \
strdup.h \
strerror.h \
+ strparse.h \
strtok.h \
strtoofft.h \
system_win32.h \
@@ -1656,7 +1609,8 @@ CS_1 = CS_ = $(CS_0)
# disable the tests that are mostly causing false positives
-TIDYFLAGS = -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet
+TIDYFLAGS := -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling \
+ -quiet $(am__append_11)
TIDY := clang-tidy
all: curl_config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -1820,6 +1774,10 @@ vtls/libcurl_la-sectransp.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-vtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
+vtls/libcurl_la-vtls_scache.lo: vtls/$(am__dirstamp) \
+ vtls/$(DEPDIR)/$(am__dirstamp)
+vtls/libcurl_la-vtls_spack.lo: vtls/$(am__dirstamp) \
+ vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-wolfssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-x509asn1.lo: vtls/$(am__dirstamp) \
@@ -1911,6 +1869,10 @@ vtls/libcurlu_la-sectransp.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-vtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
+vtls/libcurlu_la-vtls_scache.lo: vtls/$(am__dirstamp) \
+ vtls/$(DEPDIR)/$(am__dirstamp)
+vtls/libcurlu_la-vtls_spack.lo: vtls/$(am__dirstamp) \
+ vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-wolfssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-x509asn1.lo: vtls/$(am__dirstamp) \
@@ -1960,7 +1922,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-bufq.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-bufref.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-c-hyper.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cf-h2-proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cf-haproxy.Plo@am__quote@ # am--include-marker
@@ -2025,6 +1986,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_proxy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-httpsrr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-idn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-if2ip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-imap.Plo@am__quote@ # am--include-marker
@@ -2072,6 +2034,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strcase.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strdup.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strerror.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strparse.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strtok.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strtoofft.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-system_win32.Plo@am__quote@ # am--include-marker
@@ -2093,7 +2056,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-bufq.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-bufref.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-c-hyper.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cf-h2-proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cf-haproxy.Plo@am__quote@ # am--include-marker
@@ -2158,6 +2120,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_proxy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-httpsrr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-idn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-if2ip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-imap.Plo@am__quote@ # am--include-marker
@@ -2205,6 +2168,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strcase.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strdup.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strerror.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strparse.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strtok.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strtoofft.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-system_win32.Plo@am__quote@ # am--include-marker
@@ -2278,6 +2242,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-sectransp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls_scache.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls_spack.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo@am__quote@ # am--include-marker
@@ -2293,6 +2259,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-x509asn1.Plo@am__quote@ # am--include-marker
@@ -2375,13 +2343,6 @@ libcurl_la-bufref.lo: bufref.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.c
-libcurl_la-c-hyper.lo: c-hyper.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurl_la-c-hyper.Tpo -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-c-hyper.Tpo $(DEPDIR)/libcurl_la-c-hyper.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='c-hyper.c' object='libcurl_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
-
libcurl_la-cf-h1-proxy.lo: cf-h1-proxy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-cf-h1-proxy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-cf-h1-proxy.Tpo -c -o libcurl_la-cf-h1-proxy.lo `test -f 'cf-h1-proxy.c' || echo '$(srcdir)/'`cf-h1-proxy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-cf-h1-proxy.Tpo $(DEPDIR)/libcurl_la-cf-h1-proxy.Plo
@@ -2830,6 +2791,13 @@ libcurl_la-http_proxy.lo: http_proxy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
+libcurl_la-httpsrr.lo: httpsrr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-httpsrr.lo -MD -MP -MF $(DEPDIR)/libcurl_la-httpsrr.Tpo -c -o libcurl_la-httpsrr.lo `test -f 'httpsrr.c' || echo '$(srcdir)/'`httpsrr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-httpsrr.Tpo $(DEPDIR)/libcurl_la-httpsrr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httpsrr.c' object='libcurl_la-httpsrr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-httpsrr.lo `test -f 'httpsrr.c' || echo '$(srcdir)/'`httpsrr.c
+
libcurl_la-idn.lo: idn.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-idn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-idn.Tpo -c -o libcurl_la-idn.lo `test -f 'idn.c' || echo '$(srcdir)/'`idn.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-idn.Tpo $(DEPDIR)/libcurl_la-idn.Plo
@@ -3152,6 +3120,13 @@ libcurl_la-strerror.lo: strerror.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c
+libcurl_la-strparse.lo: strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strparse.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strparse.Tpo -c -o libcurl_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strparse.Tpo $(DEPDIR)/libcurl_la-strparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strparse.c' object='libcurl_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
+
libcurl_la-strtok.lo: strtok.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strtok.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strtok.Tpo -c -o libcurl_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strtok.Tpo $(DEPDIR)/libcurl_la-strtok.Plo
@@ -3432,6 +3407,20 @@ vtls/libcurl_la-vtls.lo: vtls/vtls.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c
+vtls/libcurl_la-vtls_scache.lo: vtls/vtls_scache.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-vtls_scache.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-vtls_scache.Tpo -c -o vtls/libcurl_la-vtls_scache.lo `test -f 'vtls/vtls_scache.c' || echo '$(srcdir)/'`vtls/vtls_scache.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-vtls_scache.Tpo vtls/$(DEPDIR)/libcurl_la-vtls_scache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls_scache.c' object='vtls/libcurl_la-vtls_scache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-vtls_scache.lo `test -f 'vtls/vtls_scache.c' || echo '$(srcdir)/'`vtls/vtls_scache.c
+
+vtls/libcurl_la-vtls_spack.lo: vtls/vtls_spack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-vtls_spack.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-vtls_spack.Tpo -c -o vtls/libcurl_la-vtls_spack.lo `test -f 'vtls/vtls_spack.c' || echo '$(srcdir)/'`vtls/vtls_spack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-vtls_spack.Tpo vtls/$(DEPDIR)/libcurl_la-vtls_spack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls_spack.c' object='vtls/libcurl_la-vtls_spack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-vtls_spack.lo `test -f 'vtls/vtls_spack.c' || echo '$(srcdir)/'`vtls/vtls_spack.c
+
vtls/libcurl_la-wolfssl.lo: vtls/wolfssl.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-wolfssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-wolfssl.Tpo -c -o vtls/libcurl_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-wolfssl.Tpo vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo
@@ -3572,13 +3561,6 @@ libcurlu_la-bufref.lo: bufref.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.c
-libcurlu_la-c-hyper.lo: c-hyper.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-c-hyper.Tpo -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-c-hyper.Tpo $(DEPDIR)/libcurlu_la-c-hyper.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='c-hyper.c' object='libcurlu_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
-
libcurlu_la-cf-h1-proxy.lo: cf-h1-proxy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-cf-h1-proxy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-cf-h1-proxy.Tpo -c -o libcurlu_la-cf-h1-proxy.lo `test -f 'cf-h1-proxy.c' || echo '$(srcdir)/'`cf-h1-proxy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-cf-h1-proxy.Tpo $(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo
@@ -4027,6 +4009,13 @@ libcurlu_la-http_proxy.lo: http_proxy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
+libcurlu_la-httpsrr.lo: httpsrr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-httpsrr.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-httpsrr.Tpo -c -o libcurlu_la-httpsrr.lo `test -f 'httpsrr.c' || echo '$(srcdir)/'`httpsrr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-httpsrr.Tpo $(DEPDIR)/libcurlu_la-httpsrr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httpsrr.c' object='libcurlu_la-httpsrr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-httpsrr.lo `test -f 'httpsrr.c' || echo '$(srcdir)/'`httpsrr.c
+
libcurlu_la-idn.lo: idn.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-idn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-idn.Tpo -c -o libcurlu_la-idn.lo `test -f 'idn.c' || echo '$(srcdir)/'`idn.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-idn.Tpo $(DEPDIR)/libcurlu_la-idn.Plo
@@ -4349,6 +4338,13 @@ libcurlu_la-strerror.lo: strerror.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c
+libcurlu_la-strparse.lo: strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strparse.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strparse.Tpo -c -o libcurlu_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strparse.Tpo $(DEPDIR)/libcurlu_la-strparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strparse.c' object='libcurlu_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
+
libcurlu_la-strtok.lo: strtok.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strtok.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strtok.Tpo -c -o libcurlu_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strtok.Tpo $(DEPDIR)/libcurlu_la-strtok.Plo
@@ -4629,6 +4625,20 @@ vtls/libcurlu_la-vtls.lo: vtls/vtls.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c
+vtls/libcurlu_la-vtls_scache.lo: vtls/vtls_scache.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-vtls_scache.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Tpo -c -o vtls/libcurlu_la-vtls_scache.lo `test -f 'vtls/vtls_scache.c' || echo '$(srcdir)/'`vtls/vtls_scache.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Tpo vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls_scache.c' object='vtls/libcurlu_la-vtls_scache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-vtls_scache.lo `test -f 'vtls/vtls_scache.c' || echo '$(srcdir)/'`vtls/vtls_scache.c
+
+vtls/libcurlu_la-vtls_spack.lo: vtls/vtls_spack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-vtls_spack.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Tpo -c -o vtls/libcurlu_la-vtls_spack.lo `test -f 'vtls/vtls_spack.c' || echo '$(srcdir)/'`vtls/vtls_spack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Tpo vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls_spack.c' object='vtls/libcurlu_la-vtls_spack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-vtls_spack.lo `test -f 'vtls/vtls_spack.c' || echo '$(srcdir)/'`vtls/vtls_spack.c
+
vtls/libcurlu_la-wolfssl.lo: vtls/wolfssl.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-wolfssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-wolfssl.Tpo -c -o vtls/libcurlu_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-wolfssl.Tpo vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo
@@ -4874,7 +4884,6 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufref.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h2-proxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-haproxy.Plo
@@ -4939,6 +4948,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-httpsrr.Plo
-rm -f ./$(DEPDIR)/libcurl_la-idn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-imap.Plo
@@ -4986,6 +4996,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-strcase.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strtok.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strtoofft.Plo
-rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo
@@ -5007,7 +5018,6 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufref.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h2-proxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-haproxy.Plo
@@ -5072,6 +5082,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-httpsrr.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-idn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo
@@ -5119,6 +5130,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-strcase.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strtok.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strtoofft.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo
@@ -5192,6 +5204,8 @@ distclean: distclean-am -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo
+ -rm -f vtls/$(DEPDIR)/libcurl_la-vtls_scache.Plo
+ -rm -f vtls/$(DEPDIR)/libcurl_la-vtls_spack.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo
@@ -5207,6 +5221,8 @@ distclean: distclean-am -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo
+ -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Plo
+ -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-x509asn1.Plo
-rm -f Makefile
@@ -5261,7 +5277,6 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufref.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h2-proxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-haproxy.Plo
@@ -5326,6 +5341,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-httpsrr.Plo
-rm -f ./$(DEPDIR)/libcurl_la-idn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-imap.Plo
@@ -5373,6 +5389,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-strcase.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strtok.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strtoofft.Plo
-rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo
@@ -5394,7 +5411,6 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufref.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h2-proxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-haproxy.Plo
@@ -5459,6 +5475,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-httpsrr.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-idn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo
@@ -5506,6 +5523,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-strcase.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strtok.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strtoofft.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo
@@ -5579,6 +5597,8 @@ maintainer-clean: maintainer-clean-am -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo
+ -rm -f vtls/$(DEPDIR)/libcurl_la-vtls_scache.Plo
+ -rm -f vtls/$(DEPDIR)/libcurl_la-vtls_spack.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo
@@ -5594,6 +5614,8 @@ maintainer-clean: maintainer-clean-am -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo
+ -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls_scache.Plo
+ -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls_spack.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-x509asn1.Plo
-rm -f Makefile
@@ -5651,15 +5673,16 @@ uninstall-am: uninstall-libLTLIBRARIES @HAVE_WINDRES_TRUE@@USE_CPPFLAG_CURL_STATICLIB_FALSE@$(LIB_RCFILES): $(top_srcdir)/include/curl/curlver.h
checksrc:
- $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
- -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] \
- $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] $(srcdir)/vssh/*.[ch])
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
+ -W$(srcdir)/libcurl_unity.c -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] \
+ $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] \
+ $(srcdir)/vssh/*.[ch])
# for debug builds, we scan the sources on all regular make invokes
@DEBUGBUILD_TRUE@all-local: checksrc
tidy:
- $(TIDY) $(CSOURCES) $(TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
+ $(TIDY) $(CSOURCES) $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
optiontable:
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc index 592b36e5a9..229f60a94e 100644 --- a/libs/libcurl/src/Makefile.inc +++ b/libs/libcurl/src/Makefile.inc @@ -56,6 +56,8 @@ LIB_VTLS_CFILES = \ vtls/schannel_verify.c \
vtls/sectransp.c \
vtls/vtls.c \
+ vtls/vtls_scache.c \
+ vtls/vtls_spack.c \
vtls/wolfssl.c \
vtls/x509asn1.c
@@ -74,6 +76,8 @@ LIB_VTLS_HFILES = \ vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
+ vtls/vtls_scache.h \
+ vtls/vtls_spack.h \
vtls/wolfssl.h \
vtls/x509asn1.h
@@ -112,7 +116,6 @@ LIB_CFILES = \ base64.c \
bufq.c \
bufref.c \
- c-hyper.c \
cf-h1-proxy.c \
cf-h2-proxy.c \
cf-haproxy.c \
@@ -177,6 +180,7 @@ LIB_CFILES = \ http_negotiate.c \
http_ntlm.c \
http_proxy.c \
+ httpsrr.c \
idn.c \
if2ip.c \
imap.c \
@@ -223,6 +227,7 @@ LIB_CFILES = \ strcase.c \
strdup.c \
strerror.c \
+ strparse.c \
strtok.c \
strtoofft.c \
system_win32.c \
@@ -245,7 +250,6 @@ LIB_HFILES = \ asyn.h \
bufq.h \
bufref.h \
- c-hyper.h \
cf-h1-proxy.h \
cf-h2-proxy.h \
cf-haproxy.h \
@@ -317,6 +321,7 @@ LIB_HFILES = \ http_negotiate.h \
http_ntlm.h \
http_proxy.h \
+ httpsrr.h \
idn.h \
if2ip.h \
imap.h \
@@ -344,7 +349,9 @@ LIB_HFILES = \ select.h \
sendf.h \
setopt.h \
+ setup-os400.h \
setup-vms.h \
+ setup-win32.h \
share.h \
sigpipe.h \
slist.h \
@@ -358,6 +365,7 @@ LIB_HFILES = \ strcase.h \
strdup.h \
strerror.h \
+ strparse.h \
strtok.h \
strtoofft.h \
system_win32.h \
diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c index aac25f62b1..ff03020153 100644 --- a/libs/libcurl/src/altsvc.c +++ b/libs/libcurl/src/altsvc.c @@ -40,6 +40,8 @@ #include "rename.h"
#include "strdup.h"
#include "inet_pton.h"
+#include "strparse.h"
+#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -47,28 +49,12 @@ #include "memdebug.h"
#define MAX_ALTSVC_LINE 4095
-#define MAX_ALTSVC_DATELENSTR "64"
-#define MAX_ALTSVC_DATELEN 64
-#define MAX_ALTSVC_HOSTLENSTR "512"
-#define MAX_ALTSVC_HOSTLEN 512
-#define MAX_ALTSVC_ALPNLENSTR "10"
+#define MAX_ALTSVC_DATELEN 256
+#define MAX_ALTSVC_HOSTLEN 2048
#define MAX_ALTSVC_ALPNLEN 10
#define H3VERSION "h3"
-static enum alpnid alpn2alpnid(char *name)
-{
- if(strcasecompare(name, "h1"))
- return ALPN_h1;
- if(strcasecompare(name, "h2"))
- return ALPN_h2;
- if(strcasecompare(name, H3VERSION))
- return ALPN_h3;
- if(strcasecompare(name, "http/1.1"))
- return ALPN_h1;
- return ALPN_none; /* unknown, probably rubbish input */
-}
-
/* Given the ALPN ID, return the name */
const char *Curl_alpnid2str(enum alpnid id)
{
@@ -93,33 +79,33 @@ static void altsvc_free(struct altsvc *as) }
static struct altsvc *altsvc_createid(const char *srchost,
+ size_t hlen,
const char *dsthost,
size_t dlen, /* dsthost length */
enum alpnid srcalpnid,
enum alpnid dstalpnid,
- unsigned int srcport,
- unsigned int dstport)
+ size_t srcport,
+ size_t dstport)
{
struct altsvc *as = calloc(1, sizeof(struct altsvc));
- size_t hlen;
if(!as)
return NULL;
- hlen = strlen(srchost);
DEBUGASSERT(hlen);
DEBUGASSERT(dlen);
- if(!hlen || !dlen) {
+ if(!hlen || !dlen)
/* bad input */
- free(as);
- return NULL;
- }
+ goto error;
if((hlen > 2) && srchost[0] == '[') {
/* IPv6 address, strip off brackets */
srchost++;
hlen -= 2;
}
- else if(srchost[hlen - 1] == '.')
+ else if(srchost[hlen - 1] == '.') {
/* strip off trailing dot */
hlen--;
+ if(!hlen)
+ goto error;
+ }
if((dlen > 2) && dsthost[0] == '[') {
/* IPv6 address, strip off brackets */
dsthost++;
@@ -136,8 +122,8 @@ static struct altsvc *altsvc_createid(const char *srchost, as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
- as->src.port = curlx_ultous(srcport);
- as->dst.port = curlx_ultous(dstport);
+ as->src.port = (unsigned short)srcport;
+ as->dst.port = (unsigned short)dstport;
return as;
error:
@@ -145,18 +131,19 @@ error: return NULL;
}
-static struct altsvc *altsvc_create(char *srchost,
- char *dsthost,
- char *srcalpn,
- char *dstalpn,
- unsigned int srcport,
- unsigned int dstport)
+static struct altsvc *altsvc_create(struct Curl_str *srchost,
+ struct Curl_str *dsthost,
+ struct Curl_str *srcalpn,
+ struct Curl_str *dstalpn,
+ size_t srcport,
+ size_t dstport)
{
- enum alpnid dstalpnid = alpn2alpnid(dstalpn);
- enum alpnid srcalpnid = alpn2alpnid(srcalpn);
+ enum alpnid dstalpnid = Curl_alpn2alpnid(dstalpn->str, dstalpn->len);
+ enum alpnid srcalpnid = Curl_alpn2alpnid(srcalpn->str, srcalpn->len);
if(!srcalpnid || !dstalpnid)
return NULL;
- return altsvc_createid(srchost, dsthost, strlen(dsthost),
+ return altsvc_createid(srchost->str, srchost->len,
+ dsthost->str, dsthost->len,
srcalpnid, dstalpnid,
srcport, dstport);
}
@@ -167,31 +154,50 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line) /* Example line:
h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
*/
- char srchost[MAX_ALTSVC_HOSTLEN + 1];
- char dsthost[MAX_ALTSVC_HOSTLEN + 1];
- char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
- char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
- char date[MAX_ALTSVC_DATELEN + 1];
- unsigned int srcport;
- unsigned int dstport;
- unsigned int prio;
- unsigned int persist;
- int rc;
-
- rc = sscanf(line,
- "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
- "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
- "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
- srcalpn, srchost, &srcport,
- dstalpn, dsthost, &dstport,
- date, &persist, &prio);
- if(9 == rc) {
+ struct Curl_str srchost;
+ struct Curl_str dsthost;
+ struct Curl_str srcalpn;
+ struct Curl_str dstalpn;
+ struct Curl_str date;
+ size_t srcport;
+ size_t dstport;
+ size_t persist;
+ size_t prio;
+
+ if(Curl_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_word(&line, &srchost, MAX_ALTSVC_HOSTLEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_number(&line, &srcport, 65535) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_word(&line, &dstalpn, MAX_ALTSVC_ALPNLEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_word(&line, &dsthost, MAX_ALTSVC_HOSTLEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_number(&line, &dstport, 65535) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_quotedword(&line, &date, MAX_ALTSVC_DATELEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_number(&line, &persist, 1) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_number(&line, &prio, 0) ||
+ Curl_str_newline(&line))
+ ;
+ else {
struct altsvc *as;
- time_t expires = Curl_getdate_capped(date);
- as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
+ char dbuf[MAX_ALTSVC_DATELEN + 1];
+ time_t expires;
+
+ /* The date parser works on a null terminated string. The maximum length
+ is upheld by Curl_str_quotedword(). */
+ memcpy(dbuf, date.str, date.len);
+ dbuf[date.len] = 0;
+ expires = Curl_getdate_capped(dbuf);
+ as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn, srcport,
+ dstport);
if(as) {
as->expires = expires;
- as->prio = prio;
+ as->prio = 0; /* not supported to just set zero */
as->persist = persist ? 1 : 0;
Curl_llist_append(&asi->list, as, &as->node);
}
@@ -471,8 +477,6 @@ static time_t altsvc_debugtime(void *unused) #define time(x) altsvc_debugtime(x)
#endif
-#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
-
/*
* Curl_altsvc_parse() takes an incoming alt-svc response header and stores
* the data correctly in the cache.
@@ -495,6 +499,8 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
size_t entries = 0;
+ size_t alpnlen = strlen(alpnbuf);
+ size_t srchostlen = strlen(srchost);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -515,7 +521,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
- enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
+ enum alpnid dstalpnid = Curl_alpn2alpnid(alpnbuf, alpnlen);
p++;
if(*p == '\"') {
const char *dsthost = "";
@@ -633,13 +639,18 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, this is the first entry of the line. */
altsvc_flush(asi, srcalpnid, srchost, srcport);
- as = altsvc_createid(srchost, dsthost, dstlen,
+ as = altsvc_createid(srchost, srchostlen,
+ dsthost, dstlen,
srcalpnid, dstalpnid,
srcport, dstport);
if(as) {
- /* The expires time also needs to take the Age: value (if any) into
- account. [See RFC 7838 section 3.1] */
- as->expires = maxage + time(NULL);
+ time_t secs = time(NULL);
+ /* The expires time also needs to take the Age: value (if any)
+ into account. [See RFC 7838 section 3.1] */
+ if(maxage > (TIME_T_MAX - secs))
+ as->expires = TIME_T_MAX;
+ else
+ as->expires = maxage + secs;
as->persist = persist;
Curl_llist_append(&asi->list, as, &as->node);
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
diff --git a/libs/libcurl/src/altsvc.h b/libs/libcurl/src/altsvc.h index bf427bb84f..917f6d38a2 100644 --- a/libs/libcurl/src/altsvc.h +++ b/libs/libcurl/src/altsvc.h @@ -29,13 +29,6 @@ #include <curl/curl.h>
#include "llist.h"
-enum alpnid {
- ALPN_none = 0,
- ALPN_h1 = CURLALTSVC_H1,
- ALPN_h2 = CURLALTSVC_H2,
- ALPN_h3 = CURLALTSVC_H3
-};
-
struct althost {
char *host;
unsigned short port;
diff --git a/libs/libcurl/src/amigaos.c b/libs/libcurl/src/amigaos.c index 9951d07312..50aa41db39 100644 --- a/libs/libcurl/src/amigaos.c +++ b/libs/libcurl/src/amigaos.c @@ -196,12 +196,11 @@ int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds, */
struct Library *SocketBase = NULL;
-extern int errno, h_errno;
#ifdef __libnix__
void __request(const char *msg);
#else
-# define __request(msg) Printf(msg "\n\a")
+# define __request(msg) Printf((const unsigned char *)(msg "\n\a"), 0)
#endif
void Curl_amiga_cleanup(void)
@@ -215,7 +214,7 @@ void Curl_amiga_cleanup(void) CURLcode Curl_amiga_init(void)
{
if(!SocketBase)
- SocketBase = OpenLibrary("bsdsocket.library", 4);
+ SocketBase = OpenLibrary((const unsigned char *)"bsdsocket.library", 4);
if(!SocketBase) {
__request("No TCP/IP Stack running!");
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index 1ce5d78a4f..900c028dca 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -24,14 +24,14 @@ #include "curl_setup.h"
+#ifdef USE_ARES
+
/***********************************************************************
* Only for ares-enabled builds
* And only for functions that fulfill the asynch resolver backend API
* as defined in asyn.h, nothing else belongs in this file!
**********************************************************************/
-#ifdef CURLRES_ARES
-
#include <limits.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -59,15 +59,104 @@ #include "select.h"
#include "progress.h"
#include "timediff.h"
+#include "httpsrr.h"
+#include "strdup.h"
-#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(_WIN32)
-# define CARES_STATICLIB
-#endif
#include <ares.h>
#include <ares_version.h> /* really old c-ares did not include this by
itself */
+/*
+ * Curl_ares_getsock() is called when the outside world (using
+ * curl_multi_fdset()) wants to get our fd_set setup and we are talking with
+ * ares. The caller must make sure that this function is only called when we
+ * have a working ares channel.
+ *
+ * Returns: sockets-in-use-bitmap
+ */
+
+int Curl_ares_getsock(struct Curl_easy *data,
+ ares_channel channel,
+ curl_socket_t *socks)
+{
+ struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
+ struct timeval timebuf;
+ int max = ares_getsock(channel,
+ (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
+ struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);
+ timediff_t milli = curlx_tvtoms(timeout);
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
+ return max;
+}
+
+/*
+ * Curl_ares_perform()
+ *
+ * 1) Ask ares what sockets it currently plays with, then
+ * 2) wait for the timeout period to check for action on ares' sockets.
+ * 3) tell ares to act on all the sockets marked as "with action"
+ *
+ * return number of sockets it worked on, or -1 on error
+ */
+
+int Curl_ares_perform(ares_channel channel,
+ timediff_t timeout_ms)
+{
+ int nfds;
+ int bitmask;
+ ares_socket_t socks[ARES_GETSOCK_MAXNUM];
+ struct pollfd pfd[ARES_GETSOCK_MAXNUM];
+ int i;
+ int num = 0;
+
+ if(!channel)
+ return 0;
+
+ bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
+
+ for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
+ pfd[i].events = 0;
+ pfd[i].revents = 0;
+ if(ARES_GETSOCK_READABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLRDNORM|POLLIN;
+ }
+ if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLWRNORM|POLLOUT;
+ }
+ if(pfd[i].events)
+ num++;
+ else
+ break;
+ }
+
+ if(num) {
+ nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
+ if(nfds < 0)
+ return -1;
+ }
+ else
+ nfds = 0;
+
+ if(!nfds)
+ /* Call ares_process() unconditionally here, even if we simply timed out
+ above, as otherwise the ares name resolve will not timeout! */
+ ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+ else {
+ /* move through the descriptors and ask for processing on them */
+ for(i = 0; i < num; i++)
+ ares_process_fd(channel,
+ (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
+ pfd[i].fd : ARES_SOCKET_BAD,
+ (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
+ pfd[i].fd : ARES_SOCKET_BAD);
+ }
+ return nfds;
+}
+
+#ifdef CURLRES_ARES
+
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
@@ -93,22 +182,19 @@ #define HAVE_CARES_GETADDRINFO 1
#endif
+#if ARES_VERSION >= 0x011c00
+/* 1.28.0 and later have ares_query_dnsrec */
+#define HAVE_ARES_QUERY_DNSREC 1
+#ifdef USE_HTTPSRR
+#define USE_HTTPSRR_ARES 1
+#endif
+#endif
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-struct thread_data {
- int num_pending; /* number of outstanding c-ares requests */
- struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
- parts */
- int last_status;
-#ifndef HAVE_CARES_GETADDRINFO
- struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
-#endif
- char hostname[1];
-};
-
/* How long we are willing to wait for additional parallel responses after
obtaining a "definitive" one. For old c-ares without getaddrinfo.
@@ -280,89 +366,13 @@ static void destroy_async_data(struct Curl_async *async) /*
* Curl_resolver_getsock() is called when someone from the outside world
- * (using curl_multi_fdset()) wants to get our fd_set setup and we are talking
- * with ares. The caller must make sure that this function is only called when
- * we have a working ares channel.
- *
- * Returns: sockets-in-use-bitmap
+ * (using curl_multi_fdset()) wants to get our fd_set setup.
*/
-int Curl_resolver_getsock(struct Curl_easy *data,
- curl_socket_t *socks)
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
- struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
- struct timeval timebuf;
- int max = ares_getsock((ares_channel)data->state.async.resolver,
- (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
- struct timeval *timeout =
- ares_timeout((ares_channel)data->state.async.resolver, &maxtime, &timebuf);
- timediff_t milli = curlx_tvtoms(timeout);
- Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
- return max;
-}
-
-/*
- * waitperform()
- *
- * 1) Ask ares what sockets it currently plays with, then
- * 2) wait for the timeout period to check for action on ares' sockets.
- * 3) tell ares to act on all the sockets marked as "with action"
- *
- * return number of sockets it worked on, or -1 on error
- */
-
-static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
-{
- int nfds;
- int bitmask;
- ares_socket_t socks[ARES_GETSOCK_MAXNUM];
- struct pollfd pfd[ARES_GETSOCK_MAXNUM];
- int i;
- int num = 0;
-
- bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
- ARES_GETSOCK_MAXNUM);
-
- for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
- pfd[i].events = 0;
- pfd[i].revents = 0;
- if(ARES_GETSOCK_READABLE(bitmask, i)) {
- pfd[i].fd = socks[i];
- pfd[i].events |= POLLRDNORM|POLLIN;
- }
- if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
- pfd[i].fd = socks[i];
- pfd[i].events |= POLLWRNORM|POLLOUT;
- }
- if(pfd[i].events)
- num++;
- else
- break;
- }
-
- if(num) {
- nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
- if(nfds < 0)
- return -1;
- }
- else
- nfds = 0;
-
- if(!nfds)
- /* Call ares_process() unconditionally here, even if we simply timed out
- above, as otherwise the ares name resolve will not timeout! */
- ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
- ARES_SOCKET_BAD);
- else {
- /* move through the descriptors and ask for processing on them */
- for(i = 0; i < num; i++)
- ares_process_fd((ares_channel)data->state.async.resolver,
- (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
- pfd[i].fd : ARES_SOCKET_BAD,
- (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
- pfd[i].fd : ARES_SOCKET_BAD);
- }
- return nfds;
+ return Curl_ares_getsock(data, (ares_channel)data->state.async.resolver,
+ socks);
}
/*
@@ -381,7 +391,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, DEBUGASSERT(dns);
*dns = NULL;
- if(waitperform(data, 0) < 0)
+ if(Curl_ares_perform((ares_channel)data->state.async.resolver, 0) < 0)
return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
@@ -417,8 +427,19 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, if(!data->state.async.dns)
result = Curl_resolver_error(data);
- else
+ else {
*dns = data->state.async.dns;
+#ifdef USE_HTTPSRR_ARES
+ {
+ struct Curl_https_rrinfo *lhrr =
+ Curl_memdup(&res->hinfo, sizeof(struct Curl_https_rrinfo));
+ if(!lhrr)
+ result = CURLE_OUT_OF_MEMORY;
+ else
+ (*dns)->hinfo = lhrr;
+ }
+#endif
+ }
destroy_async_data(&data->state.async);
}
@@ -481,7 +502,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, else
timeout_ms = 1000;
- if(waitperform(data, timeout_ms) < 0)
+ if(Curl_ares_perform((ares_channel)data->state.async.resolver,
+ timeout_ms) < 0)
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
@@ -745,6 +767,7 @@ static void addrinfo_cb(void *arg, int status, int timeouts, }
#endif
+
/*
* Curl_resolver_getaddrinfo() - when using ares
*
@@ -827,6 +850,16 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, query_completed_cb, data);
}
#endif
+#ifdef USE_HTTPSRR_ARES
+ {
+ res->num_pending++; /* one more */
+ memset(&res->hinfo, 0, sizeof(struct Curl_https_rrinfo));
+ ares_query_dnsrec((ares_channel)data->state.async.resolver,
+ hostname, ARES_CLASS_IN,
+ ARES_REC_TYPE_HTTPS,
+ Curl_dnsrec_done_cb, data, NULL);
+ }
+#endif
*waitp = 1; /* expect asynchronous response */
}
return NULL; /* no struct yet */
@@ -838,14 +871,26 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, CURLcode result = CURLE_NOT_BUILT_IN;
int ares_result;
- /* If server is NULL or empty, this would purge all DNS servers
- * from ares library, which will cause any and all queries to fail.
- * So, just return OK if none are configured and do not actually make
- * any changes to c-ares. This lets c-ares use its defaults, which
- * it gets from the OS (for instance from /etc/resolv.conf on Linux).
+ /* If server is NULL, this purges all DNS servers from c-ares. Reset it to
+ * default.
*/
- if(!(servers && servers[0]))
- return CURLE_OK;
+ if(!servers) {
+ Curl_resolver_cleanup(data->state.async.resolver);
+ result = Curl_resolver_init(data, &data->state.async.resolver);
+ if(!result) {
+ /* this now needs to restore the other options set to c-ares */
+ if(data->set.str[STRING_DNS_INTERFACE])
+ (void)Curl_set_dns_interface(data,
+ data->set.str[STRING_DNS_INTERFACE]);
+ if(data->set.str[STRING_DNS_LOCAL_IP4])
+ (void)Curl_set_dns_local_ip4(data,
+ data->set.str[STRING_DNS_LOCAL_IP4]);
+ if(data->set.str[STRING_DNS_LOCAL_IP6])
+ (void)Curl_set_dns_local_ip6(data,
+ data->set.str[STRING_DNS_LOCAL_IP6]);
+ }
+ return result;
+ }
#ifdef HAVE_CARES_SERVERS_CSV
#ifdef HAVE_CARES_PORTS_CSV
@@ -947,3 +992,5 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, #endif
}
#endif /* CURLRES_ARES */
+
+#endif /* USE_ARES */
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index 11b317b283..1044166e1e 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -64,6 +64,15 @@ #include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
+#include "strdup.h"
+
+#ifdef USE_ARES
+#include <ares.h>
+#ifdef USE_HTTPSRR
+#define USE_HTTPSRR_ARES 1 /* the combo */
+#endif
+#endif
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -129,14 +138,14 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) return Curl_resolver_init(easy, to);
}
-static void destroy_async_data(struct Curl_async *);
+static void destroy_async_data(struct Curl_easy *);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
- destroy_async_data(&data->state.async);
+ destroy_async_data(data);
}
/* This function is used to init a threaded resolve */
@@ -145,32 +154,6 @@ static bool init_resolve_thread(struct Curl_easy *data, const struct addrinfo *hints);
-/* Data for synchronization between resolver thread and its parent */
-struct thread_sync_data {
- curl_mutex_t *mtx;
- int done;
- int port;
- char *hostname; /* hostname to resolve, Curl_async.hostname
- duplicate */
-#ifndef CURL_DISABLE_SOCKETPAIR
- struct Curl_easy *data;
- curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
-#endif
- int sock_error;
- struct Curl_addrinfo *res;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo hints;
-#endif
- struct thread_data *td; /* for thread-self cleanup */
-};
-
-struct thread_data {
- curl_thread_t thread_hnd;
- unsigned int poll_interval;
- timediff_t interval_end;
- struct thread_sync_data tsd;
-};
-
static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
return &(data->state.async.tdata->tsd);
@@ -195,10 +178,12 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd) * close one end of the socket pair (may be done in resolver thread);
* the other end (for reading) is always closed in the parent thread.
*/
+#ifndef USE_EVENTFD
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
wakeup_close(tsd->sock_pair[1]);
}
#endif
+#endif
memset(tsd, 0, sizeof(*tsd));
}
@@ -218,7 +203,7 @@ int init_thread_sync_data(struct thread_data *td, /* Treat the request as done until the thread actually starts so any early
* cleanup gets done properly.
*/
- tsd->done = 1;
+ tsd->done = TRUE;
#ifdef HAVE_GETADDRINFO
DEBUGASSERT(hints);
tsd->hints = *hints;
@@ -297,14 +282,6 @@ CURL_STDCALL getaddrinfo_thread(void *arg) struct thread_data *td = tsd->td;
char service[12];
int rc;
-#ifndef CURL_DISABLE_SOCKETPAIR
-#ifdef USE_EVENTFD
- const void *buf;
- const uint64_t val = 1;
-#else
- char buf[1];
-#endif
-#endif
msnprintf(service, sizeof(service), "%d", tsd->port);
@@ -330,9 +307,9 @@ CURL_STDCALL getaddrinfo_thread(void *arg) #ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
#ifdef USE_EVENTFD
- buf = &val;
+ const uint64_t buf[1] = { 1 };
#else
- buf[0] = 1;
+ const char buf[1] = { 1 };
#endif
/* DNS has been resolved, signal client task */
if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
@@ -341,7 +318,7 @@ CURL_STDCALL getaddrinfo_thread(void *arg) }
}
#endif
- tsd->done = 1;
+ tsd->done = TRUE;
Curl_mutex_release(tsd->mtx);
}
@@ -380,7 +357,7 @@ CURL_STDCALL gethostbyname_thread(void *arg) free(td);
}
else {
- tsd->done = 1;
+ tsd->done = TRUE;
Curl_mutex_release(tsd->mtx);
}
@@ -392,23 +369,30 @@ CURL_STDCALL gethostbyname_thread(void *arg) /*
* destroy_async_data() cleans up async resolver data and thread handle.
*/
-static void destroy_async_data(struct Curl_async *async)
+static void destroy_async_data(struct Curl_easy *data)
{
+ struct Curl_async *async;
+ DEBUGASSERT(data);
+ async = &data->state.async;
+ DEBUGASSERT(async);
if(async->tdata) {
struct thread_data *td = async->tdata;
- int done;
+ bool done;
#ifndef CURL_DISABLE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
- struct Curl_easy *data = td->tsd.data;
#endif
+#ifdef USE_HTTPSRR_ARES
+ if(data->state.async.tdata->channel)
+ ares_destroy(data->state.async.tdata->channel);
+#endif
/*
* if the thread is still blocking in the resolve syscall, detach it and
* let the thread do the cleanup...
*/
Curl_mutex_acquire(td->tsd.mtx);
done = td->tsd.done;
- td->tsd.done = 1;
+ td->tsd.done = TRUE;
Curl_mutex_release(td->tsd.mtx);
if(!done) {
@@ -437,6 +421,24 @@ static void destroy_async_data(struct Curl_async *async) async->hostname = NULL;
}
+#ifdef USE_HTTPSRR_ARES
+static CURLcode resolve_httpsrr(struct Curl_easy *data,
+ struct Curl_async *asp)
+{
+ int status = ares_init_options(&asp->tdata->channel, NULL, 0);
+ if(status != ARES_SUCCESS)
+ return CURLE_FAILED_INIT;
+
+ memset(&asp->tdata->hinfo, 0, sizeof(struct Curl_https_rrinfo));
+ ares_query_dnsrec(asp->tdata->channel,
+ asp->hostname, ARES_CLASS_IN,
+ ARES_REC_TYPE_HTTPS,
+ Curl_dnsrec_done_cb, data, NULL);
+
+ return CURLE_OK;
+}
+#endif
+
/*
* init_resolve_thread() starts a new thread that performs the actual
* resolve. This function returns before the resolve is done.
@@ -472,8 +474,8 @@ static bool init_resolve_thread(struct Curl_easy *data, if(!asp->hostname)
goto err_exit;
- /* The thread will set this to 1 when complete. */
- td->tsd.done = 0;
+ /* The thread will set this TRUE when complete. */
+ td->tsd.done = FALSE;
#ifdef HAVE_GETADDRINFO
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
@@ -483,15 +485,18 @@ static bool init_resolve_thread(struct Curl_easy *data, if(td->thread_hnd == curl_thread_t_null) {
/* The thread never started, so mark it as done here for proper cleanup. */
- td->tsd.done = 1;
+ td->tsd.done = TRUE;
err = errno;
goto err_exit;
}
-
+#ifdef USE_HTTPSRR_ARES
+ if(resolve_httpsrr(data, asp))
+ infof(data, "Failed HTTPS RR operation");
+#endif
return TRUE;
err_exit:
- destroy_async_data(asp);
+ destroy_async_data(data);
errno_exit:
errno = err;
@@ -530,7 +535,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, /* a name was not resolved, report error */
result = Curl_resolver_error(data);
- destroy_async_data(&data->state.async);
+ destroy_async_data(data);
if(!data->state.async.dns && report)
connclose(data->conn, "asynch resolve failed");
@@ -585,7 +590,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **entry)
{
struct thread_data *td = data->state.async.tdata;
- int done = 0;
+ bool done = FALSE;
DEBUGASSERT(entry);
*entry = NULL;
@@ -594,6 +599,10 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, DEBUGASSERT(td);
return CURLE_COULDNT_RESOLVE_HOST;
}
+#ifdef USE_HTTPSRR_ARES
+ if(Curl_ares_perform(data->state.async.tdata->channel, 0) < 0)
+ return CURLE_UNRECOVERABLE_POLL;
+#endif
Curl_mutex_acquire(td->tsd.mtx);
done = td->tsd.done;
@@ -604,10 +613,21 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, if(!data->state.async.dns) {
CURLcode result = Curl_resolver_error(data);
- destroy_async_data(&data->state.async);
+ destroy_async_data(data);
return result;
}
- destroy_async_data(&data->state.async);
+#ifdef USE_HTTPSRR_ARES
+ {
+ struct Curl_https_rrinfo *lhrr =
+ Curl_memdup(&td->hinfo, sizeof(struct Curl_https_rrinfo));
+ if(!lhrr) {
+ destroy_async_data(data);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->state.async.dns->hinfo = lhrr;
+ }
+#endif
+ destroy_async_data(data);
*entry = data->state.async.dns;
}
else {
@@ -643,16 +663,27 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifndef CURL_DISABLE_SOCKETPAIR
struct thread_data *td = data->state.async.tdata;
+#endif
+#if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES)
+ int socketi = 0;
#else
(void)socks;
#endif
+#ifdef USE_HTTPSRR_ARES
+ if(data->state.async.tdata && data->state.async.tdata->channel) {
+ ret_val = Curl_ares_getsock(data, data->state.async.tdata->channel, socks);
+ for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
+ if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
+ !ARES_GETSOCK_WRITABLE(ret_val, socketi))
+ break;
+ }
+#endif
#ifndef CURL_DISABLE_SOCKETPAIR
if(td) {
/* return read fd to client for polling the DNS resolution status */
- socks[0] = td->tsd.sock_pair[0];
- td->tsd.data = data;
- ret_val = GETSOCK_READSOCK(0);
+ socks[socketi] = td->tsd.sock_pair[0];
+ ret_val |= GETSOCK_READSOCK(socketi);
}
else {
#endif
diff --git a/libs/libcurl/src/asyn.h b/libs/libcurl/src/asyn.h index fd6792edb6..194cab2c93 100644 --- a/libs/libcurl/src/asyn.h +++ b/libs/libcurl/src/asyn.h @@ -26,6 +26,7 @@ #include "curl_setup.h"
#include "curl_addrinfo.h"
+#include "httpsrr.h"
struct addrinfo;
struct hostent;
@@ -33,6 +34,68 @@ struct Curl_easy; struct connectdata;
struct Curl_dns_entry;
+#ifdef CURLRES_THREADED
+#include "curl_threads.h"
+
+/* Data for synchronization between resolver thread and its parent */
+struct thread_sync_data {
+ curl_mutex_t *mtx;
+ char *hostname; /* hostname to resolve, Curl_async.hostname
+ duplicate */
+#ifndef CURL_DISABLE_SOCKETPAIR
+ curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
+#endif
+ struct Curl_addrinfo *res;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+#endif
+ struct thread_data *td; /* for thread-self cleanup */
+ int port;
+ int sock_error;
+ bool done;
+};
+
+struct thread_data {
+ curl_thread_t thread_hnd;
+ unsigned int poll_interval;
+ timediff_t interval_end;
+ struct thread_sync_data tsd;
+#if defined(USE_HTTPSRR) && defined(USE_ARES)
+ struct Curl_https_rrinfo hinfo;
+ ares_channel channel;
+#endif
+};
+
+#elif defined(CURLRES_ARES) /* CURLRES_THREADED */
+
+struct thread_data {
+ int num_pending; /* number of outstanding c-ares requests */
+ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
+ parts */
+ int last_status;
+#ifndef HAVE_CARES_GETADDRINFO
+ struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
+#endif
+#ifdef USE_HTTPSRR
+ struct Curl_https_rrinfo hinfo;
+#endif
+ char hostname[1];
+};
+
+#endif /* CURLRES_ARES */
+
+#ifdef USE_ARES
+#include <ares.h>
+
+/* for HTTPS RR purposes as well */
+int Curl_ares_getsock(struct Curl_easy *data,
+ ares_channel channel,
+ curl_socket_t *socks);
+int Curl_ares_perform(ares_channel channel,
+ timediff_t timeout_ms);
+#endif
+
+
/*
* This header defines all functions in the internal asynch resolver interface.
* All asynch resolvers need to provide these functions.
diff --git a/libs/libcurl/src/bufq.c b/libs/libcurl/src/bufq.c index 93c56aacec..a52bbad2c4 100644 --- a/libs/libcurl/src/bufq.c +++ b/libs/libcurl/src/bufq.c @@ -45,11 +45,6 @@ static size_t chunk_len(const struct buf_chunk *chunk) return chunk->w_offset - chunk->r_offset;
}
-static size_t chunk_space(const struct buf_chunk *chunk)
-{
- return chunk->dlen - chunk->w_offset;
-}
-
static void chunk_reset(struct buf_chunk *chunk)
{
chunk->next = NULL;
@@ -287,24 +282,6 @@ size_t Curl_bufq_len(const struct bufq *q) return len;
}
-size_t Curl_bufq_space(const struct bufq *q)
-{
- size_t space = 0;
- if(q->tail)
- space += chunk_space(q->tail);
- if(q->spare) {
- struct buf_chunk *chunk = q->spare;
- while(chunk) {
- space += chunk->dlen;
- chunk = chunk->next;
- }
- }
- if(q->chunk_count < q->max_chunks) {
- space += (q->max_chunks - q->chunk_count) * q->chunk_size;
- }
- return space;
-}
-
bool Curl_bufq_is_empty(const struct bufq *q)
{
return !q->head || chunk_is_empty(q->head);
diff --git a/libs/libcurl/src/bufq.h b/libs/libcurl/src/bufq.h index 71e2de8d82..f9e5818f31 100644 --- a/libs/libcurl/src/bufq.h +++ b/libs/libcurl/src/bufq.h @@ -151,14 +151,6 @@ void Curl_bufq_free(struct bufq *q); size_t Curl_bufq_len(const struct bufq *q);
/**
- * Return the total amount of free space in the queue.
- * The returned length is the number of bytes that can
- * be expected to be written successfully to the bufq,
- * providing no memory allocations fail.
- */
-size_t Curl_bufq_space(const struct bufq *q);
-
-/**
* Returns TRUE iff there is no data in the buffer queue.
*/
bool Curl_bufq_is_empty(const struct bufq *q);
diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c deleted file mode 100644 index bf70002c04..0000000000 --- a/libs/libcurl/src/c-hyper.c +++ /dev/null @@ -1,1254 +0,0 @@ -/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/* Curl's integration with Hyper. This replaces certain functions in http.c,
- * based on configuration #defines. This implementation supports HTTP/1.1 but
- * not HTTP/2.
- */
-#include "curl_setup.h"
-
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#include <hyper.h>
-#include "urldata.h"
-#include "cfilters.h"
-#include "sendf.h"
-#include "headers.h"
-#include "transfer.h"
-#include "multiif.h"
-#include "progress.h"
-#include "content_encoding.h"
-#include "ws.h"
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-
-static CURLcode cr_hyper_add(struct Curl_easy *data);
-
-typedef enum {
- USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
- USERDATA_RESP_BODY
-} userdata_t;
-
-size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
- uint8_t *buf, size_t buflen)
-{
- struct hyp_io_ctx *io_ctx = userp;
- struct Curl_easy *data = io_ctx->data;
- struct connectdata *conn = data->conn;
- CURLcode result;
- ssize_t nread;
- DEBUGASSERT(conn);
- (void)ctx;
-
- DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
- result = Curl_conn_recv(data, io_ctx->sockindex,
- (char *)buf, buflen, &nread);
- if(result == CURLE_AGAIN) {
- /* would block, register interest */
- DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
- if(data->hyp.read_waker)
- hyper_waker_free(data->hyp.read_waker);
- data->hyp.read_waker = hyper_context_waker(ctx);
- if(!data->hyp.read_waker) {
- failf(data, "Couldn't make the read hyper_context_waker");
- return HYPER_IO_ERROR;
- }
- return HYPER_IO_PENDING;
- }
- else if(result) {
- failf(data, "Curl_read failed");
- return HYPER_IO_ERROR;
- }
- DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread));
- return (size_t)nread;
-}
-
-size_t Curl_hyper_send(void *userp, hyper_context *ctx,
- const uint8_t *buf, size_t buflen)
-{
- struct hyp_io_ctx *io_ctx = userp;
- struct Curl_easy *data = io_ctx->data;
- CURLcode result;
- size_t nwrote;
-
- DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
- result = Curl_conn_send(data, io_ctx->sockindex,
- (void *)buf, buflen, FALSE, &nwrote);
- if(result == CURLE_AGAIN) {
- DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
- /* would block, register interest */
- if(data->hyp.write_waker)
- hyper_waker_free(data->hyp.write_waker);
- data->hyp.write_waker = hyper_context_waker(ctx);
- if(!data->hyp.write_waker) {
- failf(data, "Couldn't make the write hyper_context_waker");
- return HYPER_IO_ERROR;
- }
- return HYPER_IO_PENDING;
- }
- else if(result) {
- failf(data, "Curl_write failed");
- return HYPER_IO_ERROR;
- }
- DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote));
- return (size_t)nwrote;
-}
-
-static int hyper_each_header(void *userdata,
- const uint8_t *name,
- size_t name_len,
- const uint8_t *value,
- size_t value_len)
-{
- struct Curl_easy *data = (struct Curl_easy *)userdata;
- size_t len;
- char *headp;
- CURLcode result;
- int writetype;
-
- if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
- failf(data, "Too long response header");
- data->state.hresult = CURLE_TOO_LARGE;
- return HYPER_ITER_BREAK;
- }
-
- Curl_dyn_reset(&data->state.headerb);
- if(name_len) {
- if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
- (int) name_len, name, (int) value_len, value))
- return HYPER_ITER_BREAK;
- }
- else {
- if(Curl_dyn_addn(&data->state.headerb, STRCONST("\r\n")))
- return HYPER_ITER_BREAK;
- }
- len = Curl_dyn_len(&data->state.headerb);
- headp = Curl_dyn_ptr(&data->state.headerb);
-
- result = Curl_http_header(data, headp, len);
- if(result) {
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
-
- Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
-
- writetype = CLIENTWRITE_HEADER;
- if(data->state.hconnect)
- writetype |= CLIENTWRITE_CONNECT;
- if(data->req.httpcode/100 == 1)
- writetype |= CLIENTWRITE_1XX;
- result = Curl_client_write(data, writetype, headp, len);
- if(result) {
- data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
- return HYPER_ITER_BREAK;
- }
-
- result = Curl_bump_headersize(data, len, FALSE);
- if(result) {
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
- return HYPER_ITER_CONTINUE;
-}
-
-static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
-{
- char *buf = (char *)hyper_buf_bytes(chunk);
- size_t len = hyper_buf_len(chunk);
- struct Curl_easy *data = (struct Curl_easy *)userdata;
- struct SingleRequest *k = &data->req;
- CURLcode result = CURLE_OK;
-
- if(!k->bodywritten) {
-#if defined(USE_NTLM)
- struct connectdata *conn = data->conn;
- if(conn->bits.close &&
- (((data->req.httpcode == 401) &&
- (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
- ((data->req.httpcode == 407) &&
- (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
- infof(data, "Connection closed while negotiating NTLM");
- data->state.authproblem = TRUE;
- Curl_safefree(data->req.newurl);
- }
-#endif
- if(Curl_http_exp100_is_selected(data)) {
- if(data->req.httpcode < 400) {
- Curl_http_exp100_got100(data);
- if(data->hyp.send_body_waker) {
- hyper_waker_wake(data->hyp.send_body_waker);
- data->hyp.send_body_waker = NULL;
- }
- }
- else { /* >= 4xx */
- Curl_req_abort_sending(data);
- }
- }
- if(data->state.hconnect && (data->req.httpcode/100 != 2) &&
- data->state.authproxy.done) {
- data->req.done = TRUE;
- result = CURLE_OK;
- }
- else
- result = Curl_http_firstwrite(data);
- if(result || data->req.done) {
- infof(data, "Return early from hyper_body_chunk");
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
- }
- result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
-
- if(result) {
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
-
- return HYPER_ITER_CONTINUE;
-}
-
-/*
- * Hyper does not consider the status line, the first line in an HTTP/1
- * response, to be a header. The libcurl API does. This function sends the
- * status line in the header callback. */
-static CURLcode status_line(struct Curl_easy *data,
- struct connectdata *conn,
- uint16_t http_status,
- int http_version,
- const uint8_t *reason, size_t rlen)
-{
- CURLcode result;
- size_t len;
- const char *vstr;
- int writetype;
- vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
- (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
-
- /* We need to set 'httpcodeq' for functions that check the response code in
- a single place. */
- data->req.httpcode = http_status;
- data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
- (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
- if(data->state.hconnect)
- /* CONNECT */
- data->info.httpproxycode = http_status;
- else {
- conn->httpversion = (unsigned char)data->req.httpversion;
- if(http_version == HYPER_HTTP_VERSION_1_0)
- data->state.httpwant = CURL_HTTP_VERSION_1_0;
-
- result = Curl_http_statusline(data, conn);
- if(result)
- return result;
- }
-
- Curl_dyn_reset(&data->state.headerb);
-
- result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
- vstr,
- (int)http_status,
- (int)rlen, reason);
- if(result)
- return result;
- len = Curl_dyn_len(&data->state.headerb);
- Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
- len);
-
- writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
- if(data->state.hconnect)
- writetype |= CLIENTWRITE_CONNECT;
- result = Curl_client_write(data, writetype,
- Curl_dyn_ptr(&data->state.headerb), len);
- if(result)
- return result;
-
- result = Curl_bump_headersize(data, len, FALSE);
- return result;
-}
-
-/*
- * Hyper does not pass on the last empty response header. The libcurl API
- * does. This function sends an empty header in the header callback.
- */
-static CURLcode empty_header(struct Curl_easy *data)
-{
- CURLcode result = Curl_http_size(data);
- if(!result) {
- result = hyper_each_header(data, NULL, 0, NULL, 0) ?
- CURLE_WRITE_ERROR : CURLE_OK;
- if(result)
- failf(data, "hyperstream: could not pass blank header");
- /* Hyper does chunked decoding itself. If it was added during
- * response header processing, remove it again. */
- Curl_cwriter_remove_by_name(data, "chunked");
- }
- return result;
-}
-
-CURLcode Curl_hyper_stream(struct Curl_easy *data,
- struct connectdata *conn,
- int *didwhat,
- int select_res)
-{
- hyper_response *resp = NULL;
- uint16_t http_status;
- int http_version;
- hyper_headers *headers = NULL;
- hyper_body *resp_body = NULL;
- struct hyptransfer *h = &data->hyp;
- hyper_task *task;
- hyper_task *foreach;
- const uint8_t *reasonp;
- size_t reason_len;
- CURLcode result = CURLE_OK;
- struct SingleRequest *k = &data->req;
- (void)conn;
-
- if(data->hyp.send_body_waker) {
- /* If there is still something to upload, wake it to give it
- * another try. */
- hyper_waker_wake(data->hyp.send_body_waker);
- data->hyp.send_body_waker = NULL;
- }
-
- if(select_res & CURL_CSELECT_IN) {
- if(h->read_waker)
- hyper_waker_wake(h->read_waker);
- h->read_waker = NULL;
- }
- if(select_res & CURL_CSELECT_OUT) {
- if(h->write_waker)
- hyper_waker_wake(h->write_waker);
- h->write_waker = NULL;
- }
-
- while(1) {
- hyper_task_return_type t;
- task = hyper_executor_poll(h->exec);
- if(!task) {
- *didwhat = KEEP_RECV;
- break;
- }
- t = hyper_task_type(task);
- if(t == HYPER_TASK_ERROR) {
- hyper_error *hypererr = hyper_task_value(task);
- hyper_task_free(task);
- if(data->state.hresult) {
- /* override Hyper's view, might not even be an error */
- result = data->state.hresult;
- infof(data, "hyperstream is done (by early callback)");
- }
- else {
- uint8_t errbuf[256];
- size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
- hyper_code code = hyper_error_code(hypererr);
- failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- switch(code) {
- case HYPERE_ABORTED_BY_CALLBACK:
- result = CURLE_OK;
- goto out;
- case HYPERE_UNEXPECTED_EOF:
- if(!data->req.bytecount)
- result = CURLE_GOT_NOTHING;
- else
- result = CURLE_RECV_ERROR;
- goto out;
- case HYPERE_INVALID_PEER_MESSAGE:
- /* bump headerbytecount to avoid the count remaining at zero and
- appearing to not having read anything from the peer at all */
- data->req.headerbytecount++;
- result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
- goto out;
- default:
- result = CURLE_RECV_ERROR;
- goto out;
- }
- }
- data->req.done = TRUE;
- hyper_error_free(hypererr);
- break;
- }
- else if(t == HYPER_TASK_EMPTY) {
- void *userdata = hyper_task_userdata(task);
- hyper_task_free(task);
- if(userdata == (void *)USERDATA_RESP_BODY) {
- /* end of transfer */
- data->req.done = TRUE;
- infof(data, "hyperstream is done");
- if(!k->bodywritten) {
- /* hyper does not always call the body write callback */
- result = Curl_http_firstwrite(data);
- }
- break;
- }
- else {
- /* A background task for hyper; ignore */
- DEBUGF(infof(data, "hyper: some background task done"));
- continue;
- }
- }
- else if(t == HYPER_TASK_RESPONSE) {
- resp = hyper_task_value(task);
- hyper_task_free(task);
-
- *didwhat = KEEP_RECV;
- if(!resp) {
- failf(data, "hyperstream: could not get response");
- result = CURLE_RECV_ERROR;
- goto out;
- }
-
- http_status = hyper_response_status(resp);
- http_version = hyper_response_version(resp);
- reasonp = hyper_response_reason_phrase(resp);
- reason_len = hyper_response_reason_phrase_len(resp);
-
- if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
- infof(data, "Got 417 while waiting for a 100");
- data->state.disableexpect = TRUE;
- data->req.newurl = strdup(data->state.url);
- Curl_req_abort_sending(data);
- }
-
- result = status_line(data, conn,
- http_status, http_version, reasonp, reason_len);
- if(result)
- goto out;
-
- headers = hyper_response_headers(resp);
- if(!headers) {
- failf(data, "hyperstream: could not get response headers");
- result = CURLE_RECV_ERROR;
- goto out;
- }
-
- /* the headers are already received */
- hyper_headers_foreach(headers, hyper_each_header, data);
- if(data->state.hresult) {
- result = data->state.hresult;
- goto out;
- }
-
- result = empty_header(data);
- if(result)
- goto out;
-
- k->deductheadercount =
- (100 <= http_status && 199 >= http_status) ? k->headerbytecount : 0;
-#ifndef CURL_DISABLE_WEBSOCKETS
- if(k->upgr101 == UPGR101_WS) {
- if(http_status == 101) {
- /* verify the response */
- result = Curl_ws_accept(data, NULL, 0);
- if(result)
- goto out;
- }
- else {
- failf(data, "Expected 101, got %u", k->httpcode);
- result = CURLE_HTTP_RETURNED_ERROR;
- goto out;
- }
- }
-#endif
-
- /* Curl_http_auth_act() checks what authentication methods that are
- * available and decides which one (if any) to use. It will set 'newurl'
- * if an auth method was picked. */
- result = Curl_http_auth_act(data);
- if(result)
- goto out;
-
- resp_body = hyper_response_body(resp);
- if(!resp_body) {
- failf(data, "hyperstream: could not get response body");
- result = CURLE_RECV_ERROR;
- goto out;
- }
- foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
- if(!foreach) {
- failf(data, "hyperstream: body foreach failed");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
- if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
- failf(data, "Couldn't hyper_executor_push the body-foreach");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- hyper_response_free(resp);
- resp = NULL;
- }
- else {
- DEBUGF(infof(data, "hyper: unhandled tasktype %x", t));
- }
- } /* while(1) */
-
- if(!result && Curl_xfer_needs_flush(data)) {
- DEBUGF(infof(data, "Curl_hyper_stream(), connection needs flush"));
- result = Curl_xfer_flush(data);
- }
-
-out:
- DEBUGF(infof(data, "Curl_hyper_stream() -> %d", result));
- if(resp)
- hyper_response_free(resp);
- return result;
-}
-
-static CURLcode debug_request(struct Curl_easy *data,
- const char *method,
- const char *path)
-{
- char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
- if(!req)
- return CURLE_OUT_OF_MEMORY;
- Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
- free(req);
- return CURLE_OK;
-}
-
-/*
- * Given a full header line "name: value" (optional CRLF in the input, should
- * be in the output), add to Hyper and send to the debug callback.
- *
- * Supports multiple headers.
- */
-
-CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
- const char *line)
-{
- const char *p;
- const char *n;
- size_t nlen;
- const char *v;
- size_t vlen;
- bool newline = TRUE;
- int numh = 0;
-
- if(!line)
- return CURLE_OK;
- n = line;
- do {
- size_t linelen = 0;
-
- p = strchr(n, ':');
- if(!p)
- /* this is fine if we already added at least one header */
- return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
- nlen = p - n;
- p++; /* move past the colon */
- while(*p == ' ')
- p++;
- v = p;
- p = strchr(v, '\r');
- if(!p) {
- p = strchr(v, '\n');
- if(p)
- linelen = 1; /* LF only */
- else {
- p = strchr(v, '\0');
- newline = FALSE; /* no newline */
- }
- }
- else
- linelen = 2; /* CRLF ending */
- linelen += (p - n);
- vlen = p - v;
-
- if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
- (uint8_t *)v, vlen)) {
- failf(data, "hyper refused to add header '%s'", line);
- return CURLE_OUT_OF_MEMORY;
- }
- if(data->set.verbose) {
- char *ptr = NULL;
- if(!newline) {
- ptr = aprintf("%.*s\r\n", (int)linelen, line);
- if(!ptr)
- return CURLE_OUT_OF_MEMORY;
- Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
- free(ptr);
- }
- else
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
- }
- numh++;
- n += linelen;
- } while(newline);
- return CURLE_OK;
-}
-
-static CURLcode request_target(struct Curl_easy *data,
- struct connectdata *conn,
- const char *method,
- hyper_request *req)
-{
- CURLcode result;
- struct dynbuf r;
-
- Curl_dyn_init(&r, DYN_HTTP_REQUEST);
-
- result = Curl_http_target(data, conn, &r);
- if(result)
- return result;
-
- if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
- Curl_dyn_len(&r))) {
- failf(data, "error setting uri to hyper");
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- result = debug_request(data, method, Curl_dyn_ptr(&r));
-
- Curl_dyn_free(&r);
-
- return result;
-}
-
-static int uploadstreamed(void *userdata, hyper_context *ctx,
- hyper_buf **chunk)
-{
- size_t fillcount;
- struct Curl_easy *data = (struct Curl_easy *)userdata;
- CURLcode result;
- char *xfer_ulbuf;
- size_t xfer_ulblen;
- bool eos;
- int rc = HYPER_POLL_ERROR;
- (void)ctx;
-
- result = Curl_multi_xfer_ulbuf_borrow(data, &xfer_ulbuf, &xfer_ulblen);
- if(result)
- goto out;
-
- result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &fillcount, &eos);
- if(result)
- goto out;
-
- if(fillcount) {
- hyper_buf *copy = hyper_buf_copy((uint8_t *)xfer_ulbuf, fillcount);
- if(copy)
- *chunk = copy;
- else {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- /* increasing the writebytecount here is a little premature but we
- do not know exactly when the body is sent */
- data->req.writebytecount += fillcount;
- if(eos)
- data->req.eos_read = TRUE;
- Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- rc = HYPER_POLL_READY;
- }
- else if(eos) {
- data->req.eos_read = TRUE;
- *chunk = NULL;
- rc = HYPER_POLL_READY;
- }
- else {
- /* paused, save a waker */
- if(data->hyp.send_body_waker)
- hyper_waker_free(data->hyp.send_body_waker);
- data->hyp.send_body_waker = hyper_context_waker(ctx);
- rc = HYPER_POLL_PENDING;
- }
-
- if(!data->req.upload_done && data->req.eos_read) {
- DEBUGF(infof(data, "hyper: uploadstreamed(), upload is done"));
- result = Curl_req_set_upload_done(data);
- }
-
-out:
- Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
- data->state.hresult = result;
- DEBUGF(infof(data, "hyper: uploadstreamed() -> %d", result));
- return rc;
-}
-
-/*
- * finalize_request() sets up last headers and optional body settings
- */
-static CURLcode finalize_request(struct Curl_easy *data,
- hyper_headers *headers,
- hyper_request *hyperreq,
- Curl_HttpReq httpreq)
-{
- CURLcode result = CURLE_OK;
- struct dynbuf req;
- if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
- Curl_pgrsSetUploadSize(data, 0); /* no request body */
- }
- else {
- hyper_body *body;
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
- result = Curl_http_req_complete(data, &req, httpreq);
- if(result)
- return result;
-
- /* if the "complete" above did produce more than the closing line,
- parse the added headers */
- if(Curl_dyn_len(&req) != 2 || strcmp(Curl_dyn_ptr(&req), "\r\n")) {
- result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
- if(result)
- return result;
- }
-
- Curl_dyn_free(&req);
-
- body = hyper_body_new();
- hyper_body_set_userdata(body, data);
- hyper_body_set_data_func(body, uploadstreamed);
-
- if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
- /* fail */
- result = CURLE_OUT_OF_MEMORY;
- }
- }
-
- return cr_hyper_add(data);
-}
-
-static CURLcode cookies(struct Curl_easy *data,
- struct connectdata *conn,
- hyper_headers *headers)
-{
- struct dynbuf req;
- CURLcode result;
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
-
- result = Curl_http_cookies(data, conn, &req);
- if(!result)
- result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
- Curl_dyn_free(&req);
- return result;
-}
-
-/* called on 1xx responses */
-static void http1xx_cb(void *arg, struct hyper_response *resp)
-{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- hyper_headers *headers = NULL;
- CURLcode result = CURLE_OK;
- uint16_t http_status;
- int http_version;
- const uint8_t *reasonp;
- size_t reason_len;
-
- infof(data, "Got HTTP 1xx informational");
-
- http_status = hyper_response_status(resp);
- http_version = hyper_response_version(resp);
- reasonp = hyper_response_reason_phrase(resp);
- reason_len = hyper_response_reason_phrase_len(resp);
-
- result = status_line(data, data->conn,
- http_status, http_version, reasonp, reason_len);
- if(!result) {
- headers = hyper_response_headers(resp);
- if(!headers) {
- failf(data, "hyperstream: could not get 1xx response headers");
- result = CURLE_RECV_ERROR;
- }
- }
- data->state.hresult = result;
-
- if(!result) {
- /* the headers are already received */
- hyper_headers_foreach(headers, hyper_each_header, data);
- /* this callback also sets data->state.hresult on error */
-
- if(empty_header(data))
- result = CURLE_OUT_OF_MEMORY;
- }
-
- if(data->state.hresult)
- infof(data, "ERROR in 1xx, bail out");
-}
-
-/*
- * Curl_http() gets called from the generic multi_do() function when an HTTP
- * request is to be performed. This creates and sends a properly constructed
- * HTTP request.
- */
-CURLcode Curl_http(struct Curl_easy *data, bool *done)
-{
- struct connectdata *conn = data->conn;
- struct hyptransfer *h = &data->hyp;
- hyper_io *io = NULL;
- hyper_clientconn_options *options = NULL;
- hyper_task *task = NULL; /* for the handshake */
- hyper_task *sendtask = NULL; /* for the send */
- hyper_clientconn *client = NULL;
- hyper_request *req = NULL;
- hyper_headers *headers = NULL;
- hyper_task *handshake = NULL;
- CURLcode result;
- const char *p_accept; /* Accept: string */
- const char *method;
- Curl_HttpReq httpreq;
- const char *te = NULL; /* transfer-encoding */
- hyper_code rc;
-
- /* Always consider the DO phase done after this function call, even if there
- may be parts of the request that is not yet sent, since we can deal with
- the rest of the request in the PERFORM phase. */
- *done = TRUE;
- result = Curl_client_start(data);
- if(result)
- goto out;
-
- /* Add collecting of headers written to client. For a new connection,
- * we might have done that already, but reuse
- * or multiplex needs it here as well. */
- result = Curl_headers_init(data);
- if(result)
- goto out;
-
- infof(data, "Time for the Hyper dance");
- memset(h, 0, sizeof(struct hyptransfer));
-
- result = Curl_http_host(data, conn);
- if(result)
- goto out;
-
- Curl_http_method(data, conn, &method, &httpreq);
-
- DEBUGASSERT(data->req.bytecount == 0);
-
- /* setup the authentication headers */
- {
- char *pq = NULL;
- if(data->state.up.query) {
- pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
- if(!pq) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- }
- result = Curl_http_output_auth(data, conn, method, httpreq,
- (pq ? pq : data->state.up.path), FALSE);
- free(pq);
- if(result)
- goto out;
- }
-
- result = Curl_http_req_set_reader(data, httpreq, &te);
- if(result)
- goto out;
-
- result = Curl_http_range(data, httpreq);
- if(result)
- goto out;
-
- result = Curl_http_useragent(data);
- if(result)
- goto out;
-
- io = hyper_io_new();
- if(!io) {
- failf(data, "Couldn't create hyper IO");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- /* tell Hyper how to read/write network data */
- h->io_ctx.data = data;
- h->io_ctx.sockindex = FIRSTSOCKET;
- hyper_io_set_userdata(io, &h->io_ctx);
- hyper_io_set_read(io, Curl_hyper_recv);
- hyper_io_set_write(io, Curl_hyper_send);
-
- /* create an executor to poll futures */
- if(!h->exec) {
- h->exec = hyper_executor_new();
- if(!h->exec) {
- failf(data, "Couldn't create hyper executor");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- }
-
- options = hyper_clientconn_options_new();
- if(!options) {
- failf(data, "Couldn't create hyper client options");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- if(conn->alpn == CURL_HTTP_VERSION_2) {
- failf(data, "ALPN protocol h2 not supported with Hyper");
- result = CURLE_UNSUPPORTED_PROTOCOL;
- goto out;
- }
- hyper_clientconn_options_set_preserve_header_case(options, 1);
- hyper_clientconn_options_set_preserve_header_order(options, 1);
- hyper_clientconn_options_http1_allow_multiline_headers(options, 1);
-
- hyper_clientconn_options_exec(options, h->exec);
-
- /* "Both the `io` and the `options` are consumed in this function call" */
- handshake = hyper_clientconn_handshake(io, options);
- if(!handshake) {
- failf(data, "Couldn't create hyper client handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- io = NULL;
- options = NULL;
-
- if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
- failf(data, "Couldn't hyper_executor_push the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- handshake = NULL; /* ownership passed on */
-
- task = hyper_executor_poll(h->exec);
- if(!task) {
- failf(data, "Couldn't hyper_executor_poll the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- client = hyper_task_value(task);
- hyper_task_free(task);
-
- req = hyper_request_new();
- if(!req) {
- failf(data, "Couldn't hyper_request_new");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- if(!Curl_use_http_1_1plus(data, conn)) {
- if(HYPERE_OK != hyper_request_set_version(req,
- HYPER_HTTP_VERSION_1_0)) {
- failf(data, "error setting HTTP version");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- }
-
- if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
- failf(data, "error setting method");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- result = request_target(data, conn, method, req);
- if(result)
- goto out;
-
- headers = hyper_request_headers(req);
- if(!headers) {
- failf(data, "hyper_request_headers");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- rc = hyper_request_on_informational(req, http1xx_cb, data);
- if(rc) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- if(data->state.aptr.host) {
- result = Curl_hyper_header(data, headers, data->state.aptr.host);
- if(result)
- goto out;
- }
-
-#ifndef CURL_DISABLE_PROXY
- if(data->state.aptr.proxyuserpwd) {
- result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
- if(result)
- goto out;
- }
-#endif
-
- if(data->state.aptr.userpwd) {
- result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
- if(result)
- goto out;
- }
-
- if((data->state.use_range && data->state.aptr.rangeline)) {
- result = Curl_hyper_header(data, headers, data->state.aptr.rangeline);
- if(result)
- goto out;
- }
-
- if(data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] &&
- data->state.aptr.uagent) {
- result = Curl_hyper_header(data, headers, data->state.aptr.uagent);
- if(result)
- goto out;
- }
-
- p_accept = Curl_checkheaders(data,
- STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
- if(p_accept) {
- result = Curl_hyper_header(data, headers, p_accept);
- if(result)
- goto out;
- }
- if(te) {
- result = Curl_hyper_header(data, headers, te);
- if(result)
- goto out;
- }
-
-#ifndef CURL_DISABLE_ALTSVC
- if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
- char *altused = aprintf("Alt-Used: %s:%d\r\n",
- conn->conn_to_host.name, conn->conn_to_port);
- if(!altused) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- result = Curl_hyper_header(data, headers, altused);
- if(result)
- goto out;
- free(altused);
- }
-#endif
-
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
- !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
- !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
- result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive");
- if(result)
- goto out;
- }
-#endif
-
- Curl_safefree(data->state.aptr.ref);
- if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
- if(!data->state.aptr.ref)
- result = CURLE_OUT_OF_MEMORY;
- else
- result = Curl_hyper_header(data, headers, data->state.aptr.ref);
- if(result)
- goto out;
- }
-
-#ifdef HAVE_LIBZ
- /* we only consider transfer-encoding magic if libz support is built-in */
- result = Curl_transferencode(data);
- if(result)
- goto out;
- result = Curl_hyper_header(data, headers, data->state.aptr.te);
- if(result)
- goto out;
-#endif
-
- if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
- data->set.str[STRING_ENCODING]) {
- Curl_safefree(data->state.aptr.accept_encoding);
- data->state.aptr.accept_encoding =
- aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
- if(!data->state.aptr.accept_encoding)
- result = CURLE_OUT_OF_MEMORY;
- else
- result = Curl_hyper_header(data, headers,
- data->state.aptr.accept_encoding);
- if(result)
- goto out;
- }
- else
- Curl_safefree(data->state.aptr.accept_encoding);
-
- result = cookies(data, conn, headers);
- if(result)
- goto out;
-
- if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
- result = Curl_ws_request(data, headers);
-
- result = Curl_add_timecondition(data, headers);
- if(result)
- goto out;
-
- result = Curl_add_custom_headers(data, FALSE, headers);
- if(result)
- goto out;
-
- result = finalize_request(data, headers, req, httpreq);
- if(result)
- goto out;
-
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
-
- if(data->req.upload_chunky && data->req.authneg) {
- data->req.upload_chunky = TRUE;
- }
- else {
- data->req.upload_chunky = FALSE;
- }
- sendtask = hyper_clientconn_send(client, req);
- if(!sendtask) {
- failf(data, "hyper_clientconn_send");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- req = NULL;
-
- if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
- failf(data, "Couldn't hyper_executor_push the send");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- sendtask = NULL; /* ownership passed on */
-
- hyper_clientconn_free(client);
- client = NULL;
-
- if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
- /* HTTP GET/HEAD download */
- Curl_pgrsSetUploadSize(data, 0); /* nothing */
- result = Curl_req_set_upload_done(data);
- if(result)
- goto out;
- }
-
- Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
- conn->datastream = Curl_hyper_stream;
-
- /* clear userpwd and proxyuserpwd to avoid reusing old credentials
- * from reused connections */
- Curl_safefree(data->state.aptr.userpwd);
-#ifndef CURL_DISABLE_PROXY
- Curl_safefree(data->state.aptr.proxyuserpwd);
-#endif
-
-out:
- if(result) {
- if(io)
- hyper_io_free(io);
- if(options)
- hyper_clientconn_options_free(options);
- if(handshake)
- hyper_task_free(handshake);
- if(client)
- hyper_clientconn_free(client);
- if(req)
- hyper_request_free(req);
- }
- return result;
-}
-
-void Curl_hyper_done(struct Curl_easy *data)
-{
- struct hyptransfer *h = &data->hyp;
- if(h->exec) {
- hyper_executor_free(h->exec);
- h->exec = NULL;
- }
- if(h->read_waker) {
- hyper_waker_free(h->read_waker);
- h->read_waker = NULL;
- }
- if(h->write_waker) {
- hyper_waker_free(h->write_waker);
- h->write_waker = NULL;
- }
- if(h->send_body_waker) {
- hyper_waker_free(h->send_body_waker);
- h->send_body_waker = NULL;
- }
-}
-
-static CURLcode cr_hyper_unpause(struct Curl_easy *data,
- struct Curl_creader *reader)
-{
- (void)reader;
- if(data->hyp.send_body_waker) {
- hyper_waker_wake(data->hyp.send_body_waker);
- data->hyp.send_body_waker = NULL;
- }
- return CURLE_OK;
-}
-
-/* Hyper client reader, handling unpausing */
-static const struct Curl_crtype cr_hyper_protocol = {
- "cr-hyper",
- Curl_creader_def_init,
- Curl_creader_def_read,
- Curl_creader_def_close,
- Curl_creader_def_needs_rewind,
- Curl_creader_def_total_length,
- Curl_creader_def_resume_from,
- Curl_creader_def_rewind,
- cr_hyper_unpause,
- Curl_creader_def_is_paused,
- Curl_creader_def_done,
- sizeof(struct Curl_creader)
-};
-
-static CURLcode cr_hyper_add(struct Curl_easy *data)
-{
- struct Curl_creader *reader = NULL;
- CURLcode result;
-
- result = Curl_creader_create(&reader, data, &cr_hyper_protocol,
- CURL_CR_PROTOCOL);
- if(!result)
- result = Curl_creader_add(data, reader);
-
- if(result && reader)
- Curl_creader_free(data, reader);
- return result;
-}
-
-#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
diff --git a/libs/libcurl/src/c-hyper.h b/libs/libcurl/src/c-hyper.h deleted file mode 100644 index 422e6e4935..0000000000 --- a/libs/libcurl/src/c-hyper.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef HEADER_CURL_HYPER_H
-#define HEADER_CURL_HYPER_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "curl_setup.h"
-
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
-
-#include <hyper.h>
-
-struct hyp_io_ctx {
- struct Curl_easy *data;
- int sockindex;
-};
-
-/* per-transfer data for the Hyper backend */
-struct hyptransfer {
- hyper_waker *write_waker;
- hyper_waker *read_waker;
- const hyper_executor *exec;
- hyper_waker *send_body_waker;
- struct hyp_io_ctx io_ctx;
-};
-
-size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
- uint8_t *buf, size_t buflen);
-size_t Curl_hyper_send(void *userp, hyper_context *ctx,
- const uint8_t *buf, size_t buflen);
-CURLcode Curl_hyper_stream(struct Curl_easy *data,
- struct connectdata *conn,
- int *didwhat,
- int select_res);
-
-CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
- const char *line);
-void Curl_hyper_done(struct Curl_easy *);
-
-#else
-#define Curl_hyper_done(x)
-
-#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
-#endif /* HEADER_CURL_HYPER_H */
diff --git a/libs/libcurl/src/cf-h1-proxy.c b/libs/libcurl/src/cf-h1-proxy.c index 7dfe499e1e..8f71ea4c72 100644 --- a/libs/libcurl/src/cf-h1-proxy.c +++ b/libs/libcurl/src/cf-h1-proxy.c @@ -27,9 +27,6 @@ #if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
#include <curl/curl.h>
-#ifdef USE_HYPER
-#include <hyper.h>
-#endif
#include "urldata.h"
#include "dynbuf.h"
#include "sendf.h"
@@ -184,9 +181,6 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf, make sure that it is not accidentally used for the document request
after we have connected. So let's free and clear it here. */
Curl_safefree(data->state.aptr.proxyuserpwd);
-#ifdef USE_HYPER
- data->state.hconnect = FALSE;
-#endif
break;
}
}
@@ -209,10 +203,9 @@ static void tunnel_free(struct Curl_cfilter *cf, static bool tunnel_want_send(struct h1_tunnel_state *ts)
{
- return (ts->tunnel_state == H1_TUNNEL_CONNECT);
+ return ts->tunnel_state == H1_TUNNEL_CONNECT;
}
-#ifndef USE_HYPER
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)
@@ -529,337 +522,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, return result;
}
-#else /* USE_HYPER */
-
-static CURLcode CONNECT_host(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char **pauthority,
- char **phost_header)
-{
- const char *hostname;
- int port;
- bool ipv6_ip;
- CURLcode result;
- char *authority; /* for CONNECT, the destination host + port */
- char *host_header = NULL; /* Host: authority */
-
- result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
- if(result)
- return result;
-
- authority = aprintf("%s%s%s:%d", ipv6_ip ? "[":"", hostname,
- ipv6_ip ? "]" : "", port);
- if(!authority)
- return CURLE_OUT_OF_MEMORY;
-
- /* If user is not overriding the Host header later */
- if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
- host_header = aprintf("Host: %s\r\n", authority);
- if(!host_header) {
- free(authority);
- return CURLE_OUT_OF_MEMORY;
- }
- }
- *pauthority = authority;
- *phost_header = host_header;
- return CURLE_OK;
-}
-
-/* The Hyper version of CONNECT */
-static CURLcode start_CONNECT(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h1_tunnel_state *ts)
-{
- struct connectdata *conn = cf->conn;
- struct hyptransfer *h = &data->hyp;
- curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
- hyper_io *io = NULL;
- hyper_request *req = NULL;
- hyper_headers *headers = NULL;
- hyper_clientconn_options *options = NULL;
- hyper_task *handshake = NULL;
- hyper_task *task = NULL; /* for the handshake */
- hyper_clientconn *client = NULL;
- hyper_task *sendtask = NULL; /* for the send */
- char *authority = NULL; /* for CONNECT */
- char *host_header = NULL; /* Host: */
- CURLcode result = CURLE_OUT_OF_MEMORY;
- (void)ts;
-
- io = hyper_io_new();
- if(!io) {
- failf(data, "Couldn't create hyper IO");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- /* tell Hyper how to read/write network data */
- h->io_ctx.data = data;
- h->io_ctx.sockindex = cf->sockindex;
- hyper_io_set_userdata(io, &h->io_ctx);
- hyper_io_set_read(io, Curl_hyper_recv);
- hyper_io_set_write(io, Curl_hyper_send);
- conn->sockfd = tunnelsocket;
-
- data->state.hconnect = TRUE;
-
- /* create an executor to poll futures */
- if(!h->exec) {
- h->exec = hyper_executor_new();
- if(!h->exec) {
- failf(data, "Couldn't create hyper executor");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- }
-
- options = hyper_clientconn_options_new();
- if(!options) {
- failf(data, "Couldn't create hyper client options");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- hyper_clientconn_options_set_preserve_header_case(options, 1);
- hyper_clientconn_options_set_preserve_header_order(options, 1);
-
- hyper_clientconn_options_exec(options, h->exec);
-
- /* "Both the `io` and the `options` are consumed in this function
- call" */
- handshake = hyper_clientconn_handshake(io, options);
- if(!handshake) {
- failf(data, "Couldn't create hyper client handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- io = NULL;
- options = NULL;
-
- if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
- failf(data, "Couldn't hyper_executor_push the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- handshake = NULL; /* ownership passed on */
-
- task = hyper_executor_poll(h->exec);
- if(!task) {
- failf(data, "Couldn't hyper_executor_poll the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- client = hyper_task_value(task);
- hyper_task_free(task);
-
- req = hyper_request_new();
- if(!req) {
- failf(data, "Couldn't hyper_request_new");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
- strlen("CONNECT"))) {
- failf(data, "error setting method");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- /* This only happens if we have looped here due to authentication
- reasons, and we do not really use the newly cloned URL here
- then. Just free() it. */
- Curl_safefree(data->req.newurl);
-
- result = CONNECT_host(cf, data, &authority, &host_header);
- if(result)
- goto error;
-
- infof(data, "Establish HTTP proxy tunnel to %s", authority);
-
- if(hyper_request_set_uri(req, (uint8_t *)authority,
- strlen(authority))) {
- failf(data, "error setting path");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(data->set.verbose) {
- char *se = aprintf("CONNECT %s HTTP/1.1\r\n", authority);
- if(!se) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- Curl_debug(data, CURLINFO_HEADER_OUT, se, strlen(se));
- free(se);
- }
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
- authority, TRUE);
- if(result)
- goto error;
- Curl_safefree(authority);
-
- /* default is 1.1 */
- if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
- (HYPERE_OK != hyper_request_set_version(req,
- HYPER_HTTP_VERSION_1_0))) {
- failf(data, "error setting HTTP version");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- headers = hyper_request_headers(req);
- if(!headers) {
- failf(data, "hyper_request_headers");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(host_header) {
- result = Curl_hyper_header(data, headers, host_header);
- if(result)
- goto error;
- Curl_safefree(host_header);
- }
-
- if(data->state.aptr.proxyuserpwd) {
- result = Curl_hyper_header(data, headers,
- data->state.aptr.proxyuserpwd);
- if(result)
- goto error;
- }
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
- data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
- struct dynbuf ua;
- Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
- result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
- data->set.str[STRING_USERAGENT]);
- if(result)
- goto error;
- result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua));
- if(result)
- goto error;
- Curl_dyn_free(&ua);
- }
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
- result = Curl_hyper_header(data, headers,
- "Proxy-Connection: Keep-Alive");
- if(result)
- goto error;
- }
-
- result = Curl_add_custom_headers(data, TRUE, headers);
- if(result)
- goto error;
-
- result = Curl_creader_set_null(data);
- if(result)
- goto error;
-
- sendtask = hyper_clientconn_send(client, req);
- if(!sendtask) {
- failf(data, "hyper_clientconn_send");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- req = NULL;
-
- if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
- failf(data, "Couldn't hyper_executor_push the send");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- sendtask = NULL; /* ownership passed on */
-
- hyper_clientconn_free(client);
- client = NULL;
-
-error:
- free(host_header);
- free(authority);
- if(io)
- hyper_io_free(io);
- if(options)
- hyper_clientconn_options_free(options);
- if(handshake)
- hyper_task_free(handshake);
- if(client)
- hyper_clientconn_free(client);
- if(req)
- hyper_request_free(req);
-
- return result;
-}
-
-static CURLcode send_CONNECT(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h1_tunnel_state *ts,
- bool *done)
-{
- struct hyptransfer *h = &data->hyp;
- struct connectdata *conn = cf->conn;
- hyper_task *task = NULL;
- hyper_error *hypererr = NULL;
- CURLcode result = CURLE_OK;
-
- (void)ts;
- (void)conn;
- do {
- task = hyper_executor_poll(h->exec);
- if(task) {
- bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
- if(error)
- hypererr = hyper_task_value(task);
- hyper_task_free(task);
- if(error) {
- /* this could probably use a better error code? */
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- }
- } while(task);
-error:
- *done = (result == CURLE_OK);
- if(hypererr) {
- uint8_t errbuf[256];
- size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
- failf(data, "Hyper: %.*s", (int)errlen, errbuf);
- hyper_error_free(hypererr);
- }
- return result;
-}
-
-static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h1_tunnel_state *ts,
- bool *done)
-{
- struct hyptransfer *h = &data->hyp;
- CURLcode result;
- int didwhat;
-
- (void)ts;
- result = Curl_hyper_stream(data, cf->conn, &didwhat,
- CURL_CSELECT_IN | CURL_CSELECT_OUT);
- *done = data->req.done;
- if(result || !*done)
- return result;
- if(h->exec) {
- hyper_executor_free(h->exec);
- h->exec = NULL;
- }
- if(h->read_waker) {
- hyper_waker_free(h->read_waker);
- h->read_waker = NULL;
- }
- if(h->write_waker) {
- hyper_waker_free(h->write_waker);
- h->write_waker = NULL;
- }
- return result;
-}
-
-#endif /* USE_HYPER */
-
static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)
@@ -998,7 +660,6 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf, cf->ctx = ts;
}
- /* TODO: can we do blocking? */
/* We want "seamless" operations through HTTP proxy tunnel */
result = H1_CONNECT(cf, data, ts);
diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c index 92c2bbb93c..34fde28ca6 100644 --- a/libs/libcurl/src/cf-h2-proxy.c +++ b/libs/libcurl/src/cf-h2-proxy.c @@ -865,7 +865,9 @@ static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags, if(nwritten < 0) {
if(result != CURLE_AGAIN)
return NGHTTP2_ERR_CALLBACK_FAILURE;
+#ifdef DEBUGBUILD
nwritten = 0;
+#endif
}
DEBUGASSERT((size_t)nwritten == len);
return 0;
@@ -1406,7 +1408,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf, ssize_t nwritten;
CURLcode result;
- (void)eos; /* TODO, maybe useful for blocks? */
+ (void)eos;
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
*err = CURLE_SEND_ERROR;
return -1;
diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c index 3d1cdca111..ad1090f4a0 100644 --- a/libs/libcurl/src/cf-https-connect.c +++ b/libs/libcurl/src/cf-https-connect.c @@ -24,13 +24,14 @@ #include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+#if !defined(CURL_DISABLE_HTTP)
#include "urldata.h"
#include <curl/curl.h>
#include "curl_trc.h"
#include "cfilters.h"
#include "connect.h"
+#include "hostip.h"
#include "multiif.h"
#include "cf-https-connect.h"
#include "http2.h"
@@ -41,7 +42,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-
typedef enum {
CF_HC_INIT,
CF_HC_CONNECT,
@@ -55,7 +55,7 @@ struct cf_hc_baller { CURLcode result;
struct curltime started;
int reply_ms;
- BIT(enabled);
+ enum alpnid alpn_id;
BIT(shutdown);
};
@@ -73,7 +73,7 @@ static void cf_hc_baller_reset(struct cf_hc_baller *b, static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
{
- return b->enabled && b->cf && !b->result;
+ return b->cf && !b->result;
}
static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
@@ -84,7 +84,7 @@ static bool cf_hc_baller_has_started(struct cf_hc_baller *b) static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
struct Curl_easy *data)
{
- if(b->reply_ms < 0)
+ if(b->cf && (b->reply_ms < 0))
b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
&b->reply_ms, NULL);
return b->reply_ms;
@@ -116,26 +116,53 @@ struct cf_hc_ctx { const struct Curl_dns_entry *remotehost;
struct curltime started; /* when connect started */
CURLcode result; /* overall result */
- struct cf_hc_baller h3_baller;
- struct cf_hc_baller h21_baller;
+ struct cf_hc_baller ballers[2];
+ size_t baller_count;
unsigned int soft_eyeballs_timeout_ms;
unsigned int hard_eyeballs_timeout_ms;
};
+static void cf_hc_baller_assign(struct cf_hc_baller *b,
+ enum alpnid alpn_id)
+{
+ b->alpn_id = alpn_id;
+ switch(b->alpn_id) {
+ case ALPN_h3:
+ b->name = "h3";
+ break;
+ case ALPN_h2:
+ b->name = "h2";
+ break;
+ case ALPN_h1:
+ b->name = "h1";
+ break;
+ default:
+ b->result = CURLE_FAILED_INIT;
+ break;
+ }
+}
+
static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
- const char *name,
int transport)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *save = cf->next;
- b->name = name;
cf->next = NULL;
b->started = Curl_now();
- b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
- transport, CURL_CF_SSL_ENABLE);
+ switch(b->alpn_id) {
+ case ALPN_h3:
+ transport = TRNSPRT_QUIC;
+ break;
+ default:
+ break;
+ }
+
+ if(!b->result)
+ b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
+ transport, CURL_CF_SSL_ENABLE);
b->cf = cf->next;
cf->next = save;
}
@@ -157,10 +184,11 @@ static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b, static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
+ size_t i;
if(ctx) {
- cf_hc_baller_reset(&ctx->h3_baller, data);
- cf_hc_baller_reset(&ctx->h21_baller, data);
+ for(i = 0; i < ctx->baller_count; ++i)
+ cf_hc_baller_reset(&ctx->ballers[i], data);
ctx->state = CF_HC_INIT;
ctx->result = CURLE_OK;
ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
@@ -175,12 +203,12 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
int reply_ms;
+ size_t i;
DEBUGASSERT(winner->cf);
- if(winner != &ctx->h3_baller)
- cf_hc_baller_reset(&ctx->h3_baller, data);
- if(winner != &ctx->h21_baller)
- cf_hc_baller_reset(&ctx->h21_baller, data);
+ for(i = 0; i < ctx->baller_count; ++i)
+ if(winner != &ctx->ballers[i])
+ cf_hc_baller_reset(&ctx->ballers[i], data);
reply_ms = cf_hc_baller_reply_ms(winner, data);
if(reply_ms >= 0)
@@ -218,31 +246,40 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, }
-static bool time_to_start_h21(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct curltime now)
+static bool time_to_start_next(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ size_t idx, struct curltime now)
{
struct cf_hc_ctx *ctx = cf->ctx;
timediff_t elapsed_ms;
+ size_t i;
- if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
+ if(idx >= ctx->baller_count)
return FALSE;
-
- if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
+ if(cf_hc_baller_has_started(&ctx->ballers[idx]))
+ return FALSE;
+ for(i = 0; i < idx; i++) {
+ if(!ctx->ballers[i].result)
+ break;
+ }
+ if(i == idx) {
+ CURL_TRC_CF(data, cf, "all previous ballers have failed, time to start "
+ "baller %zu [%s]", idx, ctx->ballers[idx].name);
return TRUE;
-
+ }
elapsed_ms = Curl_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
- CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
- ctx->hard_eyeballs_timeout_ms);
+ CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting %s",
+ ctx->hard_eyeballs_timeout_ms, ctx->ballers[idx].name);
return TRUE;
}
- if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
- if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
- CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
- "seen any data, starting h21",
- ctx->soft_eyeballs_timeout_ms);
+ if((idx > 0) && (elapsed_ms >= ctx->soft_eyeballs_timeout_ms)) {
+ if(cf_hc_baller_reply_ms(&ctx->ballers[idx - 1], data) < 0) {
+ CURL_TRC_CF(data, cf, "soft timeout of %dms reached, %s has not "
+ "seen any data, starting %s",
+ ctx->soft_eyeballs_timeout_ms,
+ ctx->ballers[idx - 1].name, ctx->ballers[idx].name);
return TRUE;
}
/* set the effective hard timeout again */
@@ -259,6 +296,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, struct cf_hc_ctx *ctx = cf->ctx;
struct curltime now;
CURLcode result = CURLE_OK;
+ size_t i, failed_ballers;
(void)blocking;
if(cf->connected) {
@@ -270,51 +308,57 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, now = Curl_now();
switch(ctx->state) {
case CF_HC_INIT:
- DEBUGASSERT(!ctx->h3_baller.cf);
- DEBUGASSERT(!ctx->h21_baller.cf);
DEBUGASSERT(!cf->next);
+ for(i = 0; i < ctx->baller_count; i++)
+ DEBUGASSERT(!ctx->ballers[i].cf);
CURL_TRC_CF(data, cf, "connect, init");
ctx->started = now;
- if(ctx->h3_baller.enabled) {
- cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
- if(ctx->h21_baller.enabled)
- Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
+ cf_hc_baller_init(&ctx->ballers[0], cf, data, cf->conn->transport);
+ if(ctx->baller_count > 1) {
+ Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
+ CURL_TRC_CF(data, cf, "set expire for starting next baller in %ums",
+ ctx->soft_eyeballs_timeout_ms);
}
- else if(ctx->h21_baller.enabled)
- cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
- cf->conn->transport);
ctx->state = CF_HC_CONNECT;
FALLTHROUGH();
case CF_HC_CONNECT:
- if(cf_hc_baller_is_active(&ctx->h3_baller)) {
- result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
+ if(cf_hc_baller_is_active(&ctx->ballers[0])) {
+ result = cf_hc_baller_connect(&ctx->ballers[0], cf, data, done);
if(!result && *done) {
- result = baller_connected(cf, data, &ctx->h3_baller);
+ result = baller_connected(cf, data, &ctx->ballers[0]);
goto out;
}
}
- if(time_to_start_h21(cf, data, now)) {
- cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
- cf->conn->transport);
+ if(time_to_start_next(cf, data, 1, now)) {
+ cf_hc_baller_init(&ctx->ballers[1], cf, data, cf->conn->transport);
}
- if(cf_hc_baller_is_active(&ctx->h21_baller)) {
- CURL_TRC_CF(data, cf, "connect, check h21");
- result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
+ if((ctx->baller_count > 1) && cf_hc_baller_is_active(&ctx->ballers[1])) {
+ CURL_TRC_CF(data, cf, "connect, check %s", ctx->ballers[1].name);
+ result = cf_hc_baller_connect(&ctx->ballers[1], cf, data, done);
if(!result && *done) {
- result = baller_connected(cf, data, &ctx->h21_baller);
+ result = baller_connected(cf, data, &ctx->ballers[1]);
goto out;
}
}
- if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
- (!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
- /* both failed or disabled. we give up */
+ failed_ballers = 0;
+ for(i = 0; i < ctx->baller_count; i++) {
+ if(ctx->ballers[i].result)
+ ++failed_ballers;
+ }
+
+ if(failed_ballers == ctx->baller_count) {
+ /* all have failed. we give up */
CURL_TRC_CF(data, cf, "connect, all failed");
- result = ctx->result = ctx->h3_baller.enabled ?
- ctx->h3_baller.result : ctx->h21_baller.result;
+ for(i = 0; i < ctx->baller_count; i++) {
+ if(ctx->ballers[i].result) {
+ result = ctx->ballers[i].result;
+ break;
+ }
+ }
ctx->state = CF_HC_FAILURE;
goto out;
}
@@ -344,7 +388,6 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done)
{
struct cf_hc_ctx *ctx = cf->ctx;
- struct cf_hc_baller *ballers[2];
size_t i;
CURLcode result = CURLE_OK;
@@ -356,10 +399,8 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf, /* shutdown all ballers that have not done so already. If one fails,
* continue shutting down others until all are shutdown. */
- ballers[0] = &ctx->h3_baller;
- ballers[1] = &ctx->h21_baller;
- for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- struct cf_hc_baller *b = ballers[i];
+ for(i = 0; i < ctx->baller_count; i++) {
+ struct cf_hc_baller *b = &ctx->ballers[i];
bool bdone = FALSE;
if(!cf_hc_baller_is_active(b) || b->shutdown)
continue;
@@ -369,14 +410,14 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf, }
*done = TRUE;
- for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- if(ballers[i] && !ballers[i]->shutdown)
+ for(i = 0; i < ctx->baller_count; i++) {
+ if(!ctx->ballers[i].shutdown)
*done = FALSE;
}
if(*done) {
- for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- if(ballers[i] && ballers[i]->result)
- result = ballers[i]->result;
+ for(i = 0; i < ctx->baller_count; i++) {
+ if(ctx->ballers[i].result)
+ result = ctx->ballers[i].result;
}
}
CURL_TRC_CF(data, cf, "shutdown -> %d, done=%d", result, *done);
@@ -389,13 +430,10 @@ static void cf_hc_adjust_pollset(struct Curl_cfilter *cf, {
if(!cf->connected) {
struct cf_hc_ctx *ctx = cf->ctx;
- struct cf_hc_baller *ballers[2];
size_t i;
- ballers[0] = &ctx->h3_baller;
- ballers[1] = &ctx->h21_baller;
- for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- struct cf_hc_baller *b = ballers[i];
+ for(i = 0; i < ctx->baller_count; i++) {
+ struct cf_hc_baller *b = &ctx->ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
Curl_conn_cf_adjust_pollset(b->cf, data, ps);
@@ -408,13 +446,16 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
+ size_t i;
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
- return cf_hc_baller_data_pending(&ctx->h3_baller, data)
- || cf_hc_baller_data_pending(&ctx->h21_baller, data);
+ for(i = 0; i < ctx->baller_count; i++)
+ if(cf_hc_baller_data_pending(&ctx->ballers[i], data))
+ return TRUE;
+ return FALSE;
}
static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
@@ -422,21 +463,17 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf, int query)
{
struct cf_hc_ctx *ctx = cf->ctx;
- struct Curl_cfilter *cfb;
struct curltime t, tmax;
+ size_t i;
memset(&tmax, 0, sizeof(tmax));
- memset(&t, 0, sizeof(t));
- cfb = ctx->h21_baller.enabled ? ctx->h21_baller.cf : NULL;
- if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
- if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
- tmax = t;
- }
- memset(&t, 0, sizeof(t));
- cfb = ctx->h3_baller.enabled ? ctx->h3_baller.cf : NULL;
- if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
- if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
- tmax = t;
+ for(i = 0; i < ctx->baller_count; i++) {
+ struct Curl_cfilter *cfb = ctx->ballers[i].cf;
+ memset(&t, 0, sizeof(t));
+ if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
+ if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ tmax = t;
+ }
}
return tmax;
}
@@ -446,6 +483,7 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf, int query, int *pres1, void *pres2)
{
struct cf_hc_ctx *ctx = cf->ctx;
+ size_t i;
if(!cf->connected) {
switch(query) {
@@ -460,11 +498,11 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf, return CURLE_OK;
}
case CF_QUERY_NEED_FLUSH: {
- if(cf_hc_baller_needs_flush(&ctx->h3_baller, data)
- || cf_hc_baller_needs_flush(&ctx->h21_baller, data)) {
- *pres1 = TRUE;
- return CURLE_OK;
- }
+ for(i = 0; i < ctx->baller_count; i++)
+ if(cf_hc_baller_needs_flush(&ctx->ballers[i], data)) {
+ *pres1 = TRUE;
+ return CURLE_OK;
+ }
break;
}
default:
@@ -482,14 +520,17 @@ static CURLcode cf_hc_cntrl(struct Curl_cfilter *cf, {
struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
+ size_t i;
if(!cf->connected) {
- result = cf_hc_baller_cntrl(&ctx->h3_baller, data, event, arg1, arg2);
- if(!result || (result == CURLE_AGAIN))
- result = cf_hc_baller_cntrl(&ctx->h21_baller, data, event, arg1, arg2);
- if(result == CURLE_AGAIN)
- result = CURLE_OK;
+ for(i = 0; i < ctx->baller_count; i++) {
+ result = cf_hc_baller_cntrl(&ctx->ballers[i], data, event, arg1, arg2);
+ if(result && (result != CURLE_AGAIN))
+ goto out;
+ }
+ result = CURLE_OK;
}
+out:
return result;
}
@@ -537,23 +578,37 @@ struct Curl_cftype Curl_cft_http_connect = { static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
- bool try_h3, bool try_h21)
+ enum alpnid *alpnids, size_t alpn_count)
{
struct Curl_cfilter *cf = NULL;
struct cf_hc_ctx *ctx;
CURLcode result = CURLE_OK;
+ size_t i;
+
+ DEBUGASSERT(alpnids);
+ DEBUGASSERT(alpn_count);
+ DEBUGASSERT(alpn_count <= CURL_ARRAYSIZE(ctx->ballers));
+ if(!alpn_count || (alpn_count > CURL_ARRAYSIZE(ctx->ballers))) {
+ failf(data, "https-connect filter create with unsupported %zu ALPN ids",
+ alpn_count);
+ return CURLE_FAILED_INIT;
+ }
- (void)data;
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
ctx->remotehost = remotehost;
- ctx->h3_baller.enabled = try_h3;
- ctx->h21_baller.enabled = try_h21;
+ for(i = 0; i < alpn_count; ++i)
+ cf_hc_baller_assign(&ctx->ballers[i], alpnids[i]);
+ for(; i < CURL_ARRAYSIZE(ctx->ballers); ++i)
+ ctx->ballers[i].alpn_id = ALPN_none;
+ ctx->baller_count = alpn_count;
result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
+ CURL_TRC_CF(data, cf, "created with %zu ALPNs -> %d",
+ ctx->baller_count, result);
if(result)
goto out;
ctx = NULL;
@@ -569,13 +624,13 @@ static CURLcode cf_http_connect_add(struct Curl_easy *data, struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
- bool try_h3, bool try_h21)
+ enum alpnid *alpn_ids, size_t alpn_count)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
- result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
+ result = cf_hc_create(&cf, data, remotehost, alpn_ids, alpn_count);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
@@ -588,33 +643,87 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, int sockindex,
const struct Curl_dns_entry *remotehost)
{
- bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
+ enum alpnid alpn_ids[2];
+ size_t alpn_count = 0;
CURLcode result = CURLE_OK;
(void)sockindex;
(void)remotehost;
- if(!conn->bits.tls_enable_alpn)
- goto out;
-
- if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
- result = Curl_conn_may_http3(data, conn);
- if(result) /* cannot do it */
- goto out;
- try_h3 = TRUE;
- try_h21 = FALSE;
+ if(conn->bits.tls_enable_alpn) {
+ switch(data->state.httpwant) {
+ case CURL_HTTP_VERSION_NONE:
+ /* No preferences by transfer setup. Choose best defaults */
+#ifdef USE_HTTPSRR
+ if(conn->dns_entry && conn->dns_entry->hinfo &&
+ !conn->dns_entry->hinfo->no_def_alpn) {
+ size_t i, j;
+ for(i = 0; i < CURL_ARRAYSIZE(conn->dns_entry->hinfo->alpns) &&
+ alpn_count < CURL_ARRAYSIZE(alpn_ids); ++i) {
+ bool present = FALSE;
+ enum alpnid alpn = conn->dns_entry->hinfo->alpns[i];
+ for(j = 0; j < alpn_count; ++j) {
+ if(alpn == alpn_ids[j]) {
+ present = TRUE;
+ break;
+ }
+ }
+ if(!present) {
+ switch(alpn) {
+ case ALPN_h3:
+ if(Curl_conn_may_http3(data, conn))
+ break; /* not possible */
+ FALLTHROUGH();
+ case ALPN_h2:
+ case ALPN_h1:
+ alpn_ids[alpn_count++] = alpn;
+ break;
+ default: /* ignore */
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if(!alpn_count)
+ alpn_ids[alpn_count++] = ALPN_h2;
+ break;
+ case CURL_HTTP_VERSION_3ONLY:
+ result = Curl_conn_may_http3(data, conn);
+ if(result) /* cannot do it */
+ goto out;
+ alpn_ids[alpn_count++] = ALPN_h3;
+ break;
+ case CURL_HTTP_VERSION_3:
+ /* We assume that silently not even trying H3 is ok here */
+ if(Curl_conn_may_http3(data, conn) == CURLE_OK)
+ alpn_ids[alpn_count++] = ALPN_h3;
+ alpn_ids[alpn_count++] = ALPN_h2;
+ break;
+ case CURL_HTTP_VERSION_2_0:
+ case CURL_HTTP_VERSION_2TLS:
+ case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
+ alpn_ids[alpn_count++] = ALPN_h2;
+ break;
+ case CURL_HTTP_VERSION_1_0:
+ case CURL_HTTP_VERSION_1_1:
+ alpn_ids[alpn_count++] = ALPN_h1;
+ break;
+ default:
+ alpn_ids[alpn_count++] = ALPN_h2;
+ break;
+ }
}
- else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
- /* We assume that silently not even trying H3 is ok here */
- /* TODO: should we fail instead? */
- try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
- try_h21 = TRUE;
+
+ /* If we identified ALPNs to use, install our filter. Otherwise,
+ * install nothing, so our call will use a default connect setup. */
+ if(alpn_count) {
+ result = cf_http_connect_add(data, conn, sockindex, remotehost,
+ alpn_ids, alpn_count);
}
- result = cf_http_connect_add(data, conn, sockindex, remotehost,
- try_h3, try_h21);
out:
return result;
}
-#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
+#endif /* !defined(CURL_DISABLE_HTTP) */
diff --git a/libs/libcurl/src/cf-https-connect.h b/libs/libcurl/src/cf-https-connect.h index 3ca1468ea9..047550e383 100644 --- a/libs/libcurl/src/cf-https-connect.h +++ b/libs/libcurl/src/cf-https-connect.h @@ -25,7 +25,7 @@ ***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+#if !defined(CURL_DISABLE_HTTP)
struct Curl_cfilter;
struct Curl_easy;
@@ -54,5 +54,5 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, const struct Curl_dns_entry *remotehost);
-#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
+#endif /* !defined(CURL_DISABLE_HTTP) */
#endif /* HEADER_CURL_CF_HTTP_H */
diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c index c2e633f7e6..e552120b31 100644 --- a/libs/libcurl/src/cf-socket.c +++ b/libs/libcurl/src/cf-socket.c @@ -306,9 +306,9 @@ tcpkeepalive(struct Curl_easy *data, * Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
-void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
- const struct Curl_addrinfo *ai,
- int transport)
+CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
+ const struct Curl_addrinfo *ai,
+ int transport)
{
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -334,9 +334,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, }
dest->addrlen = (unsigned int)ai->ai_addrlen;
- if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
- dest->addrlen = sizeof(struct Curl_sockaddr_storage);
+ if(dest->addrlen > sizeof(struct Curl_sockaddr_storage)) {
+ DEBUGASSERT(0);
+ return CURLE_TOO_LARGE;
+ }
+
memcpy(&dest->curl_sa_addr, ai->ai_addr, dest->addrlen);
+ return CURLE_OK;
}
static CURLcode socket_open(struct Curl_easy *data,
@@ -395,12 +399,16 @@ CURLcode Curl_socket_open(struct Curl_easy *data, curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
+ CURLcode result;
if(!addr)
/* if the caller does not want info back, use a local temp copy */
addr = &dummy;
- Curl_sock_assign_addr(addr, ai, transport);
+ result = Curl_sock_assign_addr(addr, ai, transport);
+ if(result)
+ return result;
+
return socket_open(data, addr, sockfd);
}
@@ -959,14 +967,20 @@ struct cf_socket_ctx { BIT(active);
};
-static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
- const struct Curl_addrinfo *ai,
- int transport)
+static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
+ const struct Curl_addrinfo *ai,
+ int transport)
{
+ CURLcode result;
+
memset(ctx, 0, sizeof(*ctx));
ctx->sock = CURL_SOCKET_BAD;
ctx->transport = transport;
- Curl_sock_assign_addr(&ctx->addr, ai, transport);
+
+ result = Curl_sock_assign_addr(&ctx->addr, ai, transport);
+ if(result)
+ return result;
+
#ifdef DEBUGBUILD
{
char *p = getenv("CURL_DBG_SOCK_WBLOCK");
@@ -995,6 +1009,8 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx, }
}
#endif
+
+ return result;
}
static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1282,7 +1298,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data, rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
#elif defined(MSG_FASTOPEN) /* old Linux */
- if(cf->conn->given->flags & PROTOPT_SSL)
+ if(Curl_conn_is_ssl(cf->conn, cf->sockindex))
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
else
rc = 0; /* Do nothing */
@@ -1309,7 +1325,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, return CURLE_OK;
}
- /* TODO: need to support blocking connect? */
if(blocking)
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -1416,7 +1431,7 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf, /* A listening socket filter needs to be connected before the accept
* for some weird FTP interaction. This should be rewritten, so that
* FTP no longer does the socket checks and accept calls and delegates
- * all that to the filter. TODO. */
+ * all that to the filter. */
if(ctx->listening) {
Curl_pollset_set_in_only(data, ps, ctx->sock);
CURL_TRC_CF(data, cf, "adjust_pollset, listening, POLLIN fd=%"
@@ -1443,7 +1458,7 @@ static bool cf_socket_data_pending(struct Curl_cfilter *cf, (void)data;
readable = SOCKET_READABLE(ctx->sock, 0);
- return (readable > 0 && (readable & CURL_CSELECT_IN));
+ return readable > 0 && (readable & CURL_CSELECT_IN);
}
#ifdef USE_WINSOCK
@@ -1805,7 +1820,10 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
@@ -1831,7 +1849,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf, /* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
- rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
+ rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, /* NOLINT */
(curl_socklen_t)ctx->addr.addrlen);
if(-1 == rc) {
return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
@@ -1954,7 +1972,10 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
@@ -2006,7 +2027,10 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);
@@ -2188,7 +2212,7 @@ struct Curl_cftype Curl_cft_tcp_accept = { cf_tcp_accept_connect,
cf_socket_close,
cf_socket_shutdown,
- cf_socket_get_host, /* TODO: not accurate */
+ cf_socket_get_host,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
diff --git a/libs/libcurl/src/cf-socket.h b/libs/libcurl/src/cf-socket.h index e62c064cff..44cae12879 100644 --- a/libs/libcurl/src/cf-socket.h +++ b/libs/libcurl/src/cf-socket.h @@ -95,9 +95,9 @@ void Curl_sndbuf_init(curl_socket_t sockfd); * Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
-void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
- const struct Curl_addrinfo *ai,
- int transport);
+CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
+ const struct Curl_addrinfo *ai,
+ int transport);
/**
* Creates a cfilter that opens a TCP socket to the given address
diff --git a/libs/libcurl/src/cfilters.c b/libs/libcurl/src/cfilters.c index f2aaa1e864..c7f3c2d88c 100644 --- a/libs/libcurl/src/cfilters.c +++ b/libs/libcurl/src/cfilters.c @@ -41,10 +41,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
static void cf_cntrl_update_info(struct Curl_easy *data,
struct connectdata *conn);
@@ -494,13 +490,35 @@ bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex) for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_MULTIPLEX)
return TRUE;
- if(cf->cft->flags & CF_TYPE_IP_CONNECT
- || cf->cft->flags & CF_TYPE_SSL)
+ if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
return FALSE;
}
return FALSE;
}
+unsigned char Curl_conn_http_version(struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result = CURLE_UNKNOWN_OPTION;
+ unsigned char v = 0;
+
+ cf = data->conn ? data->conn->cfilter[FIRSTSOCKET] : NULL;
+ for(; cf; cf = cf->next) {
+ if(cf->cft->flags & CF_TYPE_HTTP) {
+ int value = 0;
+ result = cf->cft->query(cf, data, CF_QUERY_HTTP_VERSION, &value, NULL);
+ if(!result && ((value < 0) || (value > 255)))
+ result = CURLE_FAILED_INIT;
+ else
+ v = (unsigned char)value;
+ break;
+ }
+ if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
+ break;
+ }
+ return (unsigned char)(result ? 0 : v);
+}
+
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
@@ -702,7 +720,7 @@ static CURLcode cf_cntrl_all(struct connectdata *conn, CURLcode result = CURLE_OK;
size_t i;
- for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
event, arg1, arg2);
if(!ignore_result && result)
@@ -711,18 +729,6 @@ static CURLcode cf_cntrl_all(struct connectdata *conn, return result;
}
-void Curl_conn_ev_data_attach(struct connectdata *conn,
- struct Curl_easy *data)
-{
- cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
-}
-
-void Curl_conn_ev_data_detach(struct connectdata *conn,
- struct Curl_easy *data)
-{
- cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
-}
-
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,
diff --git a/libs/libcurl/src/cfilters.h b/libs/libcurl/src/cfilters.h index 9d835fdbf3..f5d5dde19c 100644 --- a/libs/libcurl/src/cfilters.h +++ b/libs/libcurl/src/cfilters.h @@ -132,8 +132,6 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf, * to all filters in the chain. Overall result is always CURLE_OK.
*/
/* data event arg1 arg2 return */
-#define CF_CTRL_DATA_ATTACH 1 /* 0 NULL ignored */
-#define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
#define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
@@ -178,6 +176,7 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf, #define CF_QUERY_STREAM_ERROR 6 /* error code - */
#define CF_QUERY_NEED_FLUSH 7 /* TRUE/FALSE - */
#define CF_QUERY_IP_INFO 8 /* TRUE/FALSE struct ip_quadruple */
+#define CF_QUERY_HTTP_VERSION 9 /* number (10/11/20/30) - */
/**
* Query the cfilter for properties. Filters ignorant of a query will
@@ -197,11 +196,13 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf, * CF_TYPE_SSL: provide SSL/TLS
* CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
* CF_TYPE_PROXY provides proxying
+ * CF_TYPE_HTTP implement a version of the HTTP protocol
*/
#define CF_TYPE_IP_CONNECT (1 << 0)
#define CF_TYPE_SSL (1 << 1)
#define CF_TYPE_MULTIPLEX (1 << 2)
#define CF_TYPE_PROXY (1 << 3)
+#define CF_TYPE_HTTP (1 << 4)
/* A connection filter type, e.g. specific implementation. */
struct Curl_cftype {
@@ -395,6 +396,12 @@ bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex); bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
/**
+ * Return the HTTP version used on the FIRSTSOCKET connection filters
+ * or 0 if unknown. Value otherwise is 09, 10, 11, etc.
+ */
+unsigned char Curl_conn_http_version(struct Curl_easy *data);
+
+/**
* Close the filter chain at `sockindex` for connection `data->conn`.
* Filters remain in place and may be connected again afterwards.
*/
@@ -477,24 +484,6 @@ ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex, const void *buf, size_t len, bool eos, CURLcode *code);
/**
- * The easy handle `data` is being attached to `conn`. This does
- * not mean that data will actually do a transfer. Attachment is
- * also used for temporary actions on the connection.
- */
-void Curl_conn_ev_data_attach(struct connectdata *conn,
- struct Curl_easy *data);
-
-/**
- * The easy handle `data` is being detached (no longer served)
- * by connection `conn`. All filters are informed to release any resources
- * related to `data`.
- * Note: there may be several `data` attached to a connection at the same
- * time.
- */
-void Curl_conn_ev_data_detach(struct connectdata *conn,
- struct Curl_easy *data);
-
-/**
* Notify connection filters that they need to setup data for
* a transfer.
*/
diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h deleted file mode 100644 index 82765a0f72..0000000000 --- a/libs/libcurl/src/config-amigaos.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef HEADER_CURL_CONFIG_AMIGAOS_H
-#define HEADER_CURL_CONFIG_AMIGAOS_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/* ================================================================ */
-/* Hand crafted config file for AmigaOS */
-/* ================================================================ */
-
-#ifdef __AMIGA__ /* Any AmigaOS flavour */
-
-#define HAVE_ARPA_INET_H 1
-#define HAVE_CLOSESOCKET_CAMEL 1
-#define HAVE_IOCTLSOCKET_CAMEL 1
-#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
-#define HAVE_LONGLONG 1
-#define HAVE_NETDB_H 1
-#define HAVE_NETINET_IN_H 1
-#define HAVE_NET_IF_H 1
-#define HAVE_PWD_H 1
-#define HAVE_SELECT 1
-#define HAVE_SIGNAL 1
-#define HAVE_SOCKET 1
-#define HAVE_STRCASECMP 1
-#define HAVE_STRDUP 1
-#define HAVE_STRICMP 1
-#define HAVE_STRINGS_H 1
-#define HAVE_STRUCT_TIMEVAL 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_SOCKET_H 1
-#define HAVE_SYS_SOCKIO_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_UTIME 1
-#define HAVE_UTIME_H 1
-#define HAVE_WRITABLE_ARGV 1
-#define HAVE_SYS_IOCTL_H 1
-
-#define NEED_MALLOC_H 1
-
-#define SIZEOF_INT 4
-#define SIZEOF_SIZE_T 4
-
-#ifndef SIZEOF_CURL_OFF_T
-#define SIZEOF_CURL_OFF_T 8
-#endif
-
-#define USE_MANUAL 1
-#define CURL_DISABLE_LDAP 1
-
-#ifndef CURL_OS
-#define CURL_OS "AmigaOS"
-#endif
-
-#define PACKAGE "curl"
-#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
-#define PACKAGE_NAME "curl"
-#define PACKAGE_STRING "curl -"
-#define PACKAGE_TARNAME "curl"
-#define PACKAGE_VERSION "-"
-
-#if defined(USE_AMISSL)
-#define CURL_CA_PATH "AmiSSL:Certs"
-#elif defined(__MORPHOS__)
-#define CURL_CA_BUNDLE "MOSSYS:Data/SSL/curl-ca-bundle.crt"
-#else
-#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
-#endif
-
-#define STDC_HEADERS 1
-
-#define in_addr_t int
-
-#ifndef F_OK
-# define F_OK 0
-#endif
-
-#ifndef O_RDONLY
-# define O_RDONLY 0x0000
-#endif
-
-#ifndef LONG_MAX
-# define LONG_MAX 0x7fffffffL
-#endif
-
-#ifndef LONG_MIN
-# define LONG_MIN (-0x7fffffffL-1)
-#endif
-
-#define HAVE_RECV 1
-#define RECV_TYPE_ARG1 long
-#define RECV_TYPE_ARG2 char *
-#define RECV_TYPE_ARG3 long
-#define RECV_TYPE_ARG4 long
-#define RECV_TYPE_RETV long
-
-#define HAVE_SEND 1
-#define SEND_TYPE_ARG1 int
-#define SEND_QUAL_ARG2 const
-#define SEND_TYPE_ARG2 char *
-#define SEND_TYPE_ARG3 int
-#define SEND_TYPE_ARG4 int
-#define SEND_TYPE_RETV int
-
-#endif /* __AMIGA__ */
-#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */
diff --git a/libs/libcurl/src/config-dos.h b/libs/libcurl/src/config-dos.h deleted file mode 100644 index 2c326f2049..0000000000 --- a/libs/libcurl/src/config-dos.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef HEADER_CURL_CONFIG_DOS_H
-#define HEADER_CURL_CONFIG_DOS_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-
-/* ================================================================ */
-/* lib/config-dos.h - Hand crafted config file for DOS */
-/* ================================================================ */
-
-#ifndef CURL_OS
-#if defined(DJGPP)
- #define CURL_OS "MSDOS/djgpp"
-#elif defined(__HIGHC__)
- #define CURL_OS "MSDOS/HighC"
-#else
- #define CURL_OS "MSDOS/?"
-#endif
-#endif
-
-#define PACKAGE "curl"
-
-#define USE_MANUAL 1
-
-#define HAVE_ARPA_INET_H 1
-#define HAVE_FCNTL_H 1
-#define HAVE_FREEADDRINFO 1
-#define HAVE_GETADDRINFO 1
-#define HAVE_GETTIMEOFDAY 1
-#define HAVE_IO_H 1
-#define HAVE_IOCTL_FIONBIO 1
-#define HAVE_IOCTLSOCKET 1
-#define HAVE_IOCTLSOCKET_FIONBIO 1
-#define HAVE_LOCALE_H 1
-#define HAVE_LONGLONG 1
-#define HAVE_NETDB_H 1
-#define HAVE_NETINET_IN_H 1
-#define HAVE_NETINET_TCP_H 1
-#define HAVE_NET_IF_H 1
-#define HAVE_RECV 1
-#define HAVE_SELECT 1
-#define HAVE_SEND 1
-#define HAVE_SETLOCALE 1
-#define HAVE_SETMODE 1
-#define HAVE_SIGNAL 1
-#define HAVE_SOCKET 1
-#define HAVE_STRDUP 1
-#define HAVE_STRICMP 1
-#define HAVE_STRTOLL 1
-#define HAVE_STRUCT_TIMEVAL 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_SOCKET_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_UNISTD_H 1
-
-#define NEED_MALLOC_H 1
-
-#define SIZEOF_INT 4
-#define SIZEOF_LONG 4
-#define SIZEOF_SIZE_T 4
-#define SIZEOF_CURL_OFF_T 8
-#define STDC_HEADERS 1
-
-/* Qualifiers for send() and recv() */
-
-#define SEND_TYPE_ARG1 int
-#define SEND_QUAL_ARG2 const
-#define SEND_TYPE_ARG2 void *
-#define SEND_TYPE_ARG3 int
-#define SEND_TYPE_ARG4 int
-#define SEND_TYPE_RETV int
-
-#define RECV_TYPE_ARG1 int
-#define RECV_TYPE_ARG2 void *
-#define RECV_TYPE_ARG3 int
-#define RECV_TYPE_ARG4 int
-#define RECV_TYPE_RETV int
-
-#define BSD
-
-/* CURLDEBUG definition enables memory tracking */
-/* #define CURLDEBUG */
-
-/* to disable LDAP */
-#define CURL_DISABLE_LDAP 1
-
-#define in_addr_t u_long
-
-#if defined(__HIGHC__) || \
- (defined(__GNUC__) && (__GNUC__ < 4))
- #define ssize_t int
-#endif
-
-/* Target HAVE_x section */
-
-#if defined(DJGPP)
- #define HAVE_BASENAME 1
- #define HAVE_STRCASECMP 1
- #define HAVE_SIGACTION 1
- #define HAVE_SIGSETJMP 1
- #define HAVE_SYS_TIME_H 1
- #define HAVE_TERMIOS_H 1
-
-#elif defined(__HIGHC__)
- #define HAVE_SYS_TIME_H 1
- #define strerror(e) strerror_s_((e))
-#endif
-
-#ifdef MSDOS /* Watt-32 */
- #define HAVE_CLOSE_S 1
-#endif
-
-#undef word
-#undef byte
-
-#endif /* HEADER_CURL_CONFIG_DOS_H */
diff --git a/libs/libcurl/src/config-mac.h b/libs/libcurl/src/config-mac.h index f167831ccb..cb67d3321d 100644 --- a/libs/libcurl/src/config-mac.h +++ b/libs/libcurl/src/config-mac.h @@ -65,10 +65,6 @@ #define HAVE_SIGACTION 1
-#ifdef MACOS_SSL_SUPPORT
-# define USE_OPENSSL 1
-#endif
-
#define CURL_DISABLE_LDAP 1
#define HAVE_IOCTL_FIONBIO 1
@@ -97,7 +93,4 @@ #define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV ssize_t
-#define HAVE_EXTRA_STRICMP_H 1
-#define HAVE_EXTRA_STRDUP_H 1
-
#endif /* HEADER_CURL_CONFIG_MAC_H */
diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h index aed0f1490d..ee43e8cd8a 100644 --- a/libs/libcurl/src/config-os400.h +++ b/libs/libcurl/src/config-os400.h @@ -30,11 +30,6 @@ #pragma enum(int)
-#undef PACKAGE
-
-/* Version number of this archive. */
-#undef VERSION
-
/* Define cpu-machine-OS */
#ifndef CURL_OS
#define CURL_OS "OS/400"
@@ -110,9 +105,6 @@ /* Define if you have the GNU gssapi libraries */
#undef HAVE_GSSGNU
-/* Define if you need the malloc.h header file even with stdlib.h */
-/* #define NEED_MALLOC_H 1 */
-
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
@@ -202,9 +194,6 @@ /* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
-/* Name of package */
-#undef PACKAGE
-
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h index 50bb1081dd..d93c8a03e5 100644 --- a/libs/libcurl/src/config-plan9.h +++ b/libs/libcurl/src/config-plan9.h @@ -35,13 +35,6 @@ #ifndef CURL_OS
#define CURL_OS "plan9"
#endif
-#define PACKAGE "curl"
-#define PACKAGE_NAME "curl"
-#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
-#define PACKAGE_STRING "curl -"
-#define PACKAGE_TARNAME "curl"
-#define PACKAGE_VERSION "-"
-#define VERSION "0.0.0" /* TODO */
#define STDC_HEADERS 1
@@ -113,7 +106,6 @@ #define HAVE_SIGSETJMP 1
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
#define HAVE_SOCKET 1
-#define HAVE_SSL_GET_SHUTDOWN 1
#define HAVE_STDBOOL_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h index 8d6fbb6ea5..67ed83cf33 100644 --- a/libs/libcurl/src/config-riscos.h +++ b/libs/libcurl/src/config-riscos.h @@ -28,12 +28,6 @@ /* Hand crafted config file for RISC OS */
/* ================================================================ */
-/* Name of this package! */
-#undef PACKAGE
-
-/* Version number of this archive. */
-#undef VERSION
-
/* Define cpu-machine-OS */
#ifndef CURL_OS
#define CURL_OS "ARM-RISC OS"
@@ -105,9 +99,6 @@ /* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
-/* Define if you need the malloc.h header file even with stdlib.h */
-/* #define NEED_MALLOC_H 1 */
-
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
@@ -183,9 +174,6 @@ /* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
-/* Name of package */
-#undef PACKAGE
-
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 43a1586cfd..5d06e89488 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -42,10 +42,9 @@ #define HAVE_IO_H 1
/* Define if you have the <locale.h> header file. */
+#ifndef UNDER_CE
#define HAVE_LOCALE_H 1
-
-/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
-#define NEED_MALLOC_H 1
+#endif
/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
@@ -59,7 +58,7 @@ #endif
/* Define if you have the <sys/param.h> header file. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_SYS_PARAM_H 1
#endif
@@ -76,7 +75,7 @@ #define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_SYS_TIME_H 1
#endif
@@ -93,12 +92,12 @@ /* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_UNISTD_H 1
#endif
/* Define to 1 if you have the <libgen.h> header file. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_LIBGEN_H 1
#endif
@@ -122,7 +121,7 @@ #define HAVE_CLOSESOCKET 1
/* Define if you have the ftruncate function. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_FTRUNCATE 1
#endif
@@ -136,7 +135,7 @@ #define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_GETTIMEOFDAY 1
#endif
@@ -149,10 +148,7 @@ /* Define if you have the select function. */
#define HAVE_SELECT 1
-/* Define if libSSH2 is in use */
-#define USE_LIBSSH2 1
-#define HAVE_LIBSSH2_H 1
-
+#ifndef UNDER_CE
/* Define if you have the setlocale function. */
#define HAVE_SETLOCALE 1
@@ -161,21 +157,14 @@ /* Define if you have the _setmode function. */
#define HAVE__SETMODE 1
+#endif
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
-/* Define if you have the strcasecmp function. */
-#if defined(__MINGW32__)
-#define HAVE_STRCASECMP 1
-#endif
-
/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
-/* Define if you have the stricmp function. */
-#define HAVE_STRICMP 1
-
/* Define if you have the strtoll function. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_STRTOLL 1
@@ -228,7 +217,8 @@ #define HAVE_SNPRINTF 1
#endif
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 /* Vista */
+/* Vista */
+#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600) && !defined(UNDER_CE)
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#define HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
@@ -236,17 +226,19 @@ #endif
/* Define to 1 if you have the `basename' function. */
-#if defined(__MINGW32__)
+#ifdef __MINGW32__
#define HAVE_BASENAME 1
#endif
/* Define to 1 if you have the strtok_r function. */
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) && !defined(__MINGW32CE__)
#define HAVE_STRTOK_R 1
#endif
/* Define to 1 if you have the signal function. */
+#ifndef UNDER_CE
#define HAVE_SIGNAL 1
+#endif
/* ---------------------------------------------------------------- */
/* TYPEDEF REPLACEMENTS */
@@ -257,7 +249,7 @@ /* Define if ssize_t is not an available 'typedefed' type. */
#ifndef _SSIZE_T_DEFINED
-# if defined(__MINGW32__)
+# ifdef __MINGW32__
# elif defined(_WIN64)
# define _SSIZE_T_DEFINED
# define ssize_t __int64
@@ -281,7 +273,7 @@ #define SIZEOF_LONG 4
/* Define to the size of `size_t', as computed by sizeof. */
-#if defined(_WIN64)
+#ifdef _WIN64
# define SIZEOF_SIZE_T 8
#else
# define SIZEOF_SIZE_T 4
@@ -308,12 +300,6 @@ #define HAVE_LONGLONG 1
#endif
-/* Define to avoid VS2005 complaining about portable C functions. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define _CRT_SECURE_NO_DEPRECATE 1
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#endif
-
/* mingw-w64 and visual studio >= 2005 (MSVCR80)
all default to 64-bit time_t unless _USE_32BIT_TIME_T is defined */
#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) || defined(__MINGW32__)
@@ -324,8 +310,10 @@ # endif
#endif
+#ifndef UNDER_CE
+
/* Define some minimum and default build targets for Visual Studio */
-#if defined(_MSC_VER)
+#ifdef _MSC_VER
/* Officially, Microsoft's Windows SDK versions 6.X does not support Windows
2000 as a supported build target. VS2008 default installations provides
an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
@@ -336,7 +324,7 @@ /* The minimum build target for VS2012 is Vista unless Update 1 is installed
and the v110_xp toolset is chosen. */
-# if defined(_USING_V110_SDK71_)
+# ifdef _USING_V110_SDK71_
# define VS2012_MIN_TARGET 0x0501
# else
# define VS2012_MIN_TARGET 0x0600
@@ -348,7 +336,7 @@ /* VS2012 default build target is Windows Vista unless Update 1 is installed
and the v110_xp toolset is chosen. */
-# if defined(_USING_V110_SDK71_)
+# ifdef _USING_V110_SDK71_
# define VS2012_DEF_TARGET 0x0501
# else
# define VS2012_DEF_TARGET 0x0600
@@ -358,10 +346,10 @@ /* VS2008 default target settings and minimum build target check. */
#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600)
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT VS2008_DEF_TARGET
+# define _WIN32_WINNT VS2008_DEF_TARGET
# endif
# ifndef WINVER
-# define WINVER VS2008_DEF_TARGET
+# define WINVER VS2008_DEF_TARGET
# endif
# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET)
# error VS2008 does not support Windows build targets prior to Windows 2000
@@ -371,13 +359,13 @@ /* VS2012 default target settings and minimum build target check. */
#if defined(_MSC_VER) && (_MSC_VER >= 1700)
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT VS2012_DEF_TARGET
+# define _WIN32_WINNT VS2012_DEF_TARGET
# endif
# ifndef WINVER
-# define WINVER VS2012_DEF_TARGET
+# define WINVER VS2012_DEF_TARGET
# endif
# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET)
-# if defined(_USING_V110_SDK71_)
+# ifdef _USING_V110_SDK71_
# error VS2012 does not support Windows build targets prior to Windows XP
# else
# error VS2012 does not support Windows build targets prior to Windows \
@@ -386,10 +374,14 @@ Vista # endif
#endif
+#endif /* UNDER_CE */
+
/* Windows XP is required for freeaddrinfo, getaddrinfo */
+#ifndef UNDER_CE
#define HAVE_FREEADDRINFO 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETADDRINFO_THREADSAFE 1
+#endif
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
@@ -408,26 +400,16 @@ Vista /* LARGE FILE SUPPORT */
/* ---------------------------------------------------------------- */
-#if defined(_MSC_VER) && !defined(_WIN32_WCE)
-# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
-# define USE_WIN32_LARGE_FILES
-# else
-# define USE_WIN32_SMALL_FILES
-# endif
-#endif
+#ifndef UNDER_CE
-#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES)
+/* _fseeki64() requires VS2005 */
+#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) || defined(__MINGW32__)
# define USE_WIN32_LARGE_FILES
-#endif
-
-#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
-# define USE_WIN32_SMALL_FILES
-#endif
-
/* Number of bits in a file offset, on hosts where this is settable. */
-#if defined(USE_WIN32_LARGE_FILES) && defined(__MINGW32__)
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
+# ifdef __MINGW32__
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
# endif
#endif
@@ -439,6 +421,8 @@ Vista # define SIZEOF_OFF_T 4
#endif
+#endif /* UNDER_CE */
+
/* ---------------------------------------------------------------- */
/* DNS RESOLVER SPECIALTY */
/* ---------------------------------------------------------------- */
@@ -464,29 +448,24 @@ Vista /* LDAP SUPPORT */
/* ---------------------------------------------------------------- */
-#if defined(CURL_HAS_NOVELL_LDAPSDK)
+#ifdef CURL_HAS_OPENLDAP_LDAPSDK
#undef USE_WIN32_LDAP
-#define HAVE_LDAP_SSL_H 1
#define HAVE_LDAP_URL_PARSE 1
-#elif defined(CURL_HAS_OPENLDAP_LDAPSDK)
-#undef USE_WIN32_LDAP
-#define HAVE_LDAP_URL_PARSE 1
-#else
+#elif !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE)
#undef HAVE_LDAP_URL_PARSE
#define HAVE_LDAP_SSL 1
#define USE_WIN32_LDAP 1
#endif
-/* if SSL is enabled */
-#define USE_OPENSSL 1
-
/* Define to use the Windows crypto library. */
-#if !defined(CURL_WINDOWS_UWP)
+#ifndef CURL_WINDOWS_UWP
#define USE_WIN32_CRYPTO
#endif
/* Define to use Unix sockets. */
+#ifndef UNDER_CE
#define USE_UNIX_SOCKETS
+#endif
/* ---------------------------------------------------------------- */
/* ADDITIONAL DEFINITIONS */
@@ -494,25 +473,53 @@ Vista /* Define cpu-machine-OS */
#ifndef CURL_OS
-#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
-#define CURL_OS "i386-pc-win32"
-#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
-#define CURL_OS "x86_64-pc-win32"
-#elif defined(_M_IA64) || defined(__ia64__) /* Itanium */
-#define CURL_OS "ia64-pc-win32"
-#elif defined(_M_ARM_NT) || defined(__arm__) /* ARMv7-Thumb2 (Windows RT) */
-#define CURL_OS "thumbv7a-pc-win32"
-#elif defined(_M_ARM64) || defined(__aarch64__) /* ARM64 (Windows 10) */
-#define CURL_OS "aarch64-pc-win32"
-#else
-#define CURL_OS "unknown-pc-win32"
+# ifdef UNDER_CE
+# ifdef _M_ARM
+# define CURL_OS "arm-pc-win32ce"
+# else
+# define CURL_OS "i386-pc-win32ce"
+# endif
+# else /* !UNDER_CE */
+# if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
+# define CURL_OS "i386-pc-win32"
+# elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (VS2005+ or gcc) */
+# define CURL_OS "x86_64-pc-win32"
+# elif defined(_M_IA64) || defined(__ia64__) /* Itanium */
+# define CURL_OS "ia64-pc-win32"
+# elif defined(_M_ARM_NT) || defined(__arm__) /* ARMv7-Thumb2 */
+# define CURL_OS "thumbv7a-pc-win32"
+# elif defined(_M_ARM64) || defined(__aarch64__) /* ARM64 (Windows 10) */
+# define CURL_OS "aarch64-pc-win32"
+# else
+# define CURL_OS "unknown-pc-win32"
+# endif
+# endif /* UNDER_CE */
+#endif /* !CURL_OS */
+
+/* ---------------------------------------------------------------- */
+/* Windows CE */
+/* ---------------------------------------------------------------- */
+
+#ifdef UNDER_CE
+
+#ifndef UNICODE
+#define UNICODE
#endif
+
+#ifndef _UNICODE
+#define _UNICODE
#endif
-/* Name of package */
-#define PACKAGE "curl"
+#define CURL_DISABLE_FILE 1
+#define CURL_DISABLE_TELNET 1
+#define CURL_DISABLE_LDAP 1
+
+#define ENOSPC 1
+#define ENOMEM 2
+#define EAGAIN 3
+
+extern int stat(const char *path, struct stat *buffer);
-/* If you want to build curl with the built-in manual */
-#define USE_MANUAL 1
+#endif /* UNDER_CE */
#endif /* HEADER_CURL_CONFIG_WIN32_H */
diff --git a/libs/libcurl/src/config-win32ce.h b/libs/libcurl/src/config-win32ce.h deleted file mode 100644 index 2ea8dceded..0000000000 --- a/libs/libcurl/src/config-win32ce.h +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef HEADER_CURL_CONFIG_WIN32CE_H
-#define HEADER_CURL_CONFIG_WIN32CE_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/* ================================================================ */
-/* lib/config-win32ce.h - Hand crafted config file for Windows CE */
-/* ================================================================ */
-
-/* ---------------------------------------------------------------- */
-/* HEADER FILES */
-/* ---------------------------------------------------------------- */
-
-/* Define if you have the <arpa/inet.h> header file. */
-/* #define HAVE_ARPA_INET_H 1 */
-
-/* Define if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define if you have the <io.h> header file. */
-#define HAVE_IO_H 1
-
-/* Define if you need the malloc.h header file even with stdlib.h */
-#define NEED_MALLOC_H 1
-
-/* Define if you have the <netdb.h> header file. */
-/* #define HAVE_NETDB_H 1 */
-
-/* Define if you have the <netinet/in.h> header file. */
-/* #define HAVE_NETINET_IN_H 1 */
-
-/* Define if you have the <sys/param.h> header file. */
-/* #define HAVE_SYS_PARAM_H 1 */
-
-/* Define if you have the <sys/select.h> header file. */
-/* #define HAVE_SYS_SELECT_H 1 */
-
-/* Define if you have the <sys/socket.h> header file. */
-/* #define HAVE_SYS_SOCKET_H 1 */
-
-/* Define if you have the <sys/sockio.h> header file. */
-/* #define HAVE_SYS_SOCKIO_H 1 */
-
-/* Define if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define if you have the <sys/time.h> header file */
-/* #define HAVE_SYS_TIME_H 1 */
-
-/* Define if you have the <sys/types.h> header file. */
-/* #define HAVE_SYS_TYPES_H 1 */
-
-/* Define if you have the <sys/utime.h> header file */
-#define HAVE_SYS_UTIME_H 1
-
-/* Define if you have the <termio.h> header file. */
-/* #define HAVE_TERMIO_H 1 */
-
-/* Define if you have the <termios.h> header file. */
-/* #define HAVE_TERMIOS_H 1 */
-
-/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__)
-#define HAVE_UNISTD_H 1
-#endif
-
-/* ---------------------------------------------------------------- */
-/* OTHER HEADER INFO */
-/* ---------------------------------------------------------------- */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* ---------------------------------------------------------------- */
-/* FUNCTIONS */
-/* ---------------------------------------------------------------- */
-
-/* Define if you have the closesocket function. */
-#define HAVE_CLOSESOCKET 1
-
-/* Define if you have the gethostname function. */
-#define HAVE_GETHOSTNAME 1
-
-/* Define if you have the gettimeofday function. */
-/* #define HAVE_GETTIMEOFDAY 1 */
-
-/* Define if you have the ioctlsocket function. */
-#define HAVE_IOCTLSOCKET 1
-
-/* Define if you have a working ioctlsocket FIONBIO function. */
-#define HAVE_IOCTLSOCKET_FIONBIO 1
-
-/* Define if you have the select function. */
-#define HAVE_SELECT 1
-
-/* Define if you have the socket function. */
-#define HAVE_SOCKET 1
-
-/* Define if you have the strcasecmp function. */
-/* #define HAVE_STRCASECMP 1 */
-
-/* Define if you have the strdup function. */
-/* #define HAVE_STRDUP 1 */
-
-/* Define if you have the stricmp function. */
-/* #define HAVE_STRICMP 1 */
-
-/* Define if you have the strtoll function. */
-#if defined(__MINGW32__)
-#define HAVE_STRTOLL 1
-#endif
-
-/* Define if you have the utime function */
-#define HAVE_UTIME 1
-
-/* Define if you have the recv function. */
-#define HAVE_RECV 1
-
-/* Define to the type of arg 1 for recv. */
-#define RECV_TYPE_ARG1 SOCKET
-
-/* Define to the type of arg 2 for recv. */
-#define RECV_TYPE_ARG2 char *
-
-/* Define to the type of arg 3 for recv. */
-#define RECV_TYPE_ARG3 int
-
-/* Define to the type of arg 4 for recv. */
-#define RECV_TYPE_ARG4 int
-
-/* Define to the function return type for recv. */
-#define RECV_TYPE_RETV int
-
-/* Define if you have the send function. */
-#define HAVE_SEND 1
-
-/* Define to the type of arg 1 for send. */
-#define SEND_TYPE_ARG1 SOCKET
-
-/* Define to the type qualifier of arg 2 for send. */
-#define SEND_QUAL_ARG2 const
-
-/* Define to the type of arg 2 for send. */
-#define SEND_TYPE_ARG2 char *
-
-/* Define to the type of arg 3 for send. */
-#define SEND_TYPE_ARG3 int
-
-/* Define to the type of arg 4 for send. */
-#define SEND_TYPE_ARG4 int
-
-/* Define to the function return type for send. */
-#define SEND_TYPE_RETV int
-
-/* ---------------------------------------------------------------- */
-/* TYPEDEF REPLACEMENTS */
-/* ---------------------------------------------------------------- */
-
-/* Define this if in_addr_t is not an available 'typedefed' type */
-#define in_addr_t unsigned long
-
-/* Define ssize_t if it is not an available 'typedefed' type */
-#if defined(_WIN64)
-#define ssize_t __int64
-#else
-#define ssize_t int
-#endif
-
-/* ---------------------------------------------------------------- */
-/* TYPE SIZES */
-/* ---------------------------------------------------------------- */
-
-/* The size of `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of `long long', as computed by sizeof. */
-/* #define SIZEOF_LONG_LONG 8 */
-
-/* Define to the size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* The size of `size_t', as computed by sizeof. */
-#if defined(_WIN64)
-# define SIZEOF_SIZE_T 8
-#else
-# define SIZEOF_SIZE_T 4
-#endif
-
-/* ---------------------------------------------------------------- */
-/* STRUCT RELATED */
-/* ---------------------------------------------------------------- */
-
-/* Define this if you have struct sockaddr_storage */
-/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */
-
-/* Define this if you have struct timeval */
-#define HAVE_STRUCT_TIMEVAL 1
-
-/* Define this if struct sockaddr_in6 has the sin6_scope_id member */
-#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
-
-/* ---------------------------------------------------------------- */
-/* COMPILER SPECIFIC */
-/* ---------------------------------------------------------------- */
-
-/* Undef keyword 'const' if it does not work. */
-/* #undef const */
-
-/* Define to avoid VS2005 complaining about portable C functions */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define _CRT_SECURE_NO_DEPRECATE 1
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#endif
-
-/* VS2005 and later default size for time_t is 64-bit, unless */
-/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-# ifndef _USE_32BIT_TIME_T
-# define SIZEOF_TIME_T 8
-# else
-# define SIZEOF_TIME_T 4
-# endif
-#endif
-
-/* ---------------------------------------------------------------- */
-/* LARGE FILE SUPPORT */
-/* ---------------------------------------------------------------- */
-
-#if defined(_MSC_VER) && !defined(_WIN32_WCE)
-# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
-# define USE_WIN32_LARGE_FILES
-# else
-# define USE_WIN32_SMALL_FILES
-# endif
-#endif
-
-#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
-# define USE_WIN32_SMALL_FILES
-#endif
-
-/* ---------------------------------------------------------------- */
-/* LDAP SUPPORT */
-/* ---------------------------------------------------------------- */
-
-#define USE_WIN32_LDAP 1
-#undef HAVE_LDAP_URL_PARSE
-
-/* ---------------------------------------------------------------- */
-/* ADDITIONAL DEFINITIONS */
-/* ---------------------------------------------------------------- */
-
-/* Define cpu-machine-OS */
-#ifndef CURL_OS
-#define CURL_OS "i386-pc-win32ce"
-#endif
-
-/* Name of package */
-#define PACKAGE "curl"
-
-/* ---------------------------------------------------------------- */
-/* Windows CE */
-/* ---------------------------------------------------------------- */
-
-#ifndef UNICODE
-# define UNICODE
-#endif
-
-#ifndef _UNICODE
-# define _UNICODE
-#endif
-
-#define CURL_DISABLE_FILE 1
-#define CURL_DISABLE_TELNET 1
-#define CURL_DISABLE_LDAP 1
-
-#define ENOSPC 1
-#define ENOMEM 2
-#define EAGAIN 3
-
-extern int stat(const char *path, struct stat *buffer);
-
-#endif /* HEADER_CURL_CONFIG_WIN32CE_H */
diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c index 17431a181c..15c932f7a5 100644 --- a/libs/libcurl/src/conncache.c +++ b/libs/libcurl/src/conncache.c @@ -100,6 +100,8 @@ static void cpool_shutdown_all(struct cpool *cpool, struct Curl_easy *data, int timeout_ms);
static void cpool_close_and_destroy_all(struct cpool *cpool);
static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool);
+static size_t cpool_shutdown_dest_count(struct cpool *cpool,
+ const char *destination);
static struct cpool_bundle *cpool_bundle_create(const char *dest,
size_t dest_len)
@@ -164,11 +166,11 @@ int Curl_cpool_init(struct cpool *cpool, if(!cpool->idata)
return 1; /* bad */
cpool->idata->state.internal = TRUE;
- /* TODO: this is quirky. We need an internal handle for certain
- * operations, but we do not add it to the multi (if there is one).
- * But we give it the multi so that socket event operations can work.
- * Probably better to have an internal handle owned by the multi that
- * can be used for cpool operations. */
+ /* This is quirky. We need an internal handle for certain operations, but we
+ * do not add it to the multi (if there is one). We give it the multi so
+ * that socket event operations can work. Probably better to have an
+ * internal handle owned by the multi that can be used for cpool
+ * operations. */
cpool->idata->multi = multi;
#ifdef DEBUGBUILD
if(getenv("CURL_DEBUG"))
@@ -285,6 +287,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data, struct cpool_bundle *bundle;
size_t dest_limit = 0;
size_t total_limit = 0;
+ size_t shutdowns;
int result = CPOOL_LIMIT_OK;
if(!cpool)
@@ -300,8 +303,12 @@ int Curl_cpool_check_limits(struct Curl_easy *data, CPOOL_LOCK(cpool);
if(dest_limit) {
+ size_t live;
+
bundle = cpool_find_bundle(cpool, conn);
- while(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
+ live = bundle ? Curl_llist_count(&bundle->conns) : 0;
+ shutdowns = cpool_shutdown_dest_count(cpool, conn->destination);
+ while(!shutdowns && bundle && live >= dest_limit) {
struct connectdata *oldest_idle = NULL;
/* The bundle is full. Extract the oldest connection that may
* be removed now, if there is one. */
@@ -317,15 +324,18 @@ int Curl_cpool_check_limits(struct Curl_easy *data, /* in case the bundle was destroyed in disconnect, look it up again */
bundle = cpool_find_bundle(cpool, conn);
+ live = bundle ? Curl_llist_count(&bundle->conns) : 0;
+ shutdowns = cpool_shutdown_dest_count(cpool, conn->destination);
}
- if(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
+ if((live + shutdowns) >= dest_limit) {
result = CPOOL_LIMIT_DEST;
goto out;
}
}
if(total_limit) {
- while(cpool->num_conn >= total_limit) {
+ shutdowns = Curl_llist_count(&cpool->shutdowns);
+ while((cpool->num_conn + shutdowns) >= total_limit) {
struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
if(!oldest_idle)
break;
@@ -335,8 +345,9 @@ int Curl_cpool_check_limits(struct Curl_easy *data, "limit of %zu",
oldest_idle->connection_id, cpool->num_conn, total_limit));
Curl_cpool_disconnect(data, oldest_idle, FALSE);
+ shutdowns = Curl_llist_count(&cpool->shutdowns);
}
- if(cpool->num_conn >= total_limit) {
+ if((cpool->num_conn + shutdowns) >= total_limit) {
result = CPOOL_LIMIT_TOTAL;
goto out;
}
@@ -374,7 +385,8 @@ CURLcode Curl_cpool_add_conn(struct Curl_easy *data, cpool->num_conn++;
DEBUGF(infof(data, "Added connection %" FMT_OFF_T ". "
"The cache now contains %zu members",
- conn->connection_id, cpool->num_conn));
+ conn->connection_id,
+ cpool->num_conn + Curl_llist_count(&cpool->shutdowns)));
out:
CPOOL_UNLOCK(cpool);
@@ -612,6 +624,21 @@ bool Curl_cpool_find(struct Curl_easy *data, return result;
}
+/* How many connections to the given destination are in shutdown? */
+static size_t cpool_shutdown_dest_count(struct cpool *cpool,
+ const char *destination)
+{
+ size_t n = 0;
+ struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
+ while(e) {
+ struct connectdata *conn = Curl_node_elem(e);
+ if(!strcmp(destination, conn->destination))
+ ++n;
+ e = Curl_node_next(e);
+ }
+ return n;
+}
+
static void cpool_shutdown_discard_all(struct cpool *cpool)
{
struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
@@ -742,12 +769,12 @@ static void cpool_discard_conn(struct cpool *cpool, /* Add the connection to our shutdown list for non-blocking shutdown
* during multi processing. */
- if(data->multi && data->multi->max_shutdown_connections > 0 &&
- (data->multi->max_shutdown_connections >=
- (long)Curl_llist_count(&cpool->shutdowns))) {
+ if(data->multi && data->multi->max_total_connections > 0 &&
+ (data->multi->max_total_connections <=
+ (long)(cpool->num_conn + Curl_llist_count(&cpool->shutdowns)))) {
DEBUGF(infof(data, "[CCACHE] discarding oldest shutdown connection "
- "due to limit of %ld",
- data->multi->max_shutdown_connections));
+ "due to connection limit of %ld",
+ data->multi->max_total_connections));
cpool_shutdown_destroy_oldest(cpool);
}
@@ -767,8 +794,8 @@ static void cpool_discard_conn(struct cpool *cpool, Curl_llist_append(&cpool->shutdowns, conn, &conn->cpool_node);
DEBUGF(infof(data, "[CCACHE] added #%" FMT_OFF_T
- " to shutdown list of length %zu", conn->connection_id,
- Curl_llist_count(&cpool->shutdowns)));
+ " to shutdowns, now %zu conns in shutdown",
+ conn->connection_id, Curl_llist_count(&cpool->shutdowns)));
}
void Curl_cpool_disconnect(struct Curl_easy *data,
@@ -926,10 +953,11 @@ CURLcode Curl_cpool_add_pollfds(struct cpool *cpool, return result;
}
-CURLcode Curl_cpool_add_waitfds(struct cpool *cpool,
- struct curl_waitfds *cwfds)
+/* return information about the shutdown connections */
+unsigned int Curl_cpool_add_waitfds(struct cpool *cpool,
+ struct Curl_waitfds *cwfds)
{
- CURLcode result = CURLE_OK;
+ unsigned int need = 0;
CPOOL_LOCK(cpool);
if(Curl_llist_head(&cpool->shutdowns)) {
@@ -945,14 +973,51 @@ CURLcode Curl_cpool_add_waitfds(struct cpool *cpool, Curl_conn_adjust_pollset(cpool->idata, &ps);
Curl_detach_connection(cpool->idata);
- result = Curl_waitfds_add_ps(cwfds, &ps);
- if(result)
- goto out;
+ need += Curl_waitfds_add_ps(cwfds, &ps);
+ }
+ }
+ CPOOL_UNLOCK(cpool);
+ return need;
+}
+
+/* return fd_set info about the shutdown connections */
+void Curl_cpool_setfds(struct cpool *cpool,
+ fd_set *read_fd_set, fd_set *write_fd_set,
+ int *maxfd)
+{
+ CPOOL_LOCK(cpool);
+ if(Curl_llist_head(&cpool->shutdowns)) {
+ struct Curl_llist_node *e;
+
+ for(e = Curl_llist_head(&cpool->shutdowns); e;
+ e = Curl_node_next(e)) {
+ struct easy_pollset ps;
+ unsigned int i;
+ struct connectdata *conn = Curl_node_elem(e);
+ memset(&ps, 0, sizeof(ps));
+ Curl_attach_connection(cpool->idata, conn);
+ Curl_conn_adjust_pollset(cpool->idata, &ps);
+ Curl_detach_connection(cpool->idata);
+
+ for(i = 0; i < ps.num; i++) {
+#if defined(__DJGPP__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warith-conversion"
+#endif
+ if(ps.actions[i] & CURL_POLL_IN)
+ FD_SET(ps.sockets[i], read_fd_set);
+ if(ps.actions[i] & CURL_POLL_OUT)
+ FD_SET(ps.sockets[i], write_fd_set);
+#if defined(__DJGPP__)
+#pragma GCC diagnostic pop
+#endif
+ if((ps.actions[i] & (CURL_POLL_OUT | CURL_POLL_IN)) &&
+ ((int)ps.sockets[i] > *maxfd))
+ *maxfd = (int)ps.sockets[i];
+ }
}
}
-out:
CPOOL_UNLOCK(cpool);
- return result;
}
static void cpool_perform(struct cpool *cpool)
@@ -1052,6 +1117,11 @@ static void cpool_close_and_destroy(struct cpool *cpool, Curl_detach_connection(data);
Curl_conn_free(data, conn);
+
+ if(cpool && cpool->multi) {
+ DEBUGF(infof(data, "[CCACHE] trigger multi connchanged"));
+ Curl_multi_connchanged(cpool->multi);
+ }
}
@@ -1232,7 +1302,6 @@ static int conn_upkeep(struct Curl_easy *data, void *param)
{
struct curltime *now = param;
- /* TODO, shall we reap connections that return an error here? */
Curl_conn_upkeep(data, conn, now);
return 0; /* continue iteration */
}
diff --git a/libs/libcurl/src/conncache.h b/libs/libcurl/src/conncache.h index df1f1353aa..ab3a1828ba 100644 --- a/libs/libcurl/src/conncache.h +++ b/libs/libcurl/src/conncache.h @@ -31,7 +31,7 @@ struct connectdata;
struct Curl_easy;
struct curl_pollfds;
-struct curl_waitfds;
+struct Curl_waitfds;
struct Curl_multi;
struct Curl_share;
@@ -113,8 +113,6 @@ typedef bool Curl_cpool_done_match_cb(bool result, void *userdata); * @param dest_len destination length, including terminating NUL
* @param conn_cb must be present, called for each connection in the
* bundle until it returns TRUE
- * @param result_cb if not NULL, is called at the end with the result
- * of the `conn_cb` or FALSE if never called.
* @return combined result of last conn_db and result_cb or FALSE if no
connections were present.
*/
@@ -185,8 +183,12 @@ void Curl_cpool_do_locked(struct Curl_easy *data, */
CURLcode Curl_cpool_add_pollfds(struct cpool *connc,
struct curl_pollfds *cpfds);
-CURLcode Curl_cpool_add_waitfds(struct cpool *connc,
- struct curl_waitfds *cwfds);
+unsigned int Curl_cpool_add_waitfds(struct cpool *connc,
+ struct Curl_waitfds *cwfds);
+
+void Curl_cpool_setfds(struct cpool *cpool,
+ fd_set *read_fd_set, fd_set *write_fd_set,
+ int *maxfd);
/**
* Perform maintenance on connections in the pool. Specifically,
diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index 6fcdd3eac7..4c29377783 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -78,14 +78,32 @@ #include "vquic/vquic.h" /* for quic cfilters */
#include "http_proxy.h"
#include "socks.h"
+#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#if !defined(CURL_DISABLE_ALTSVC) || defined(USE_HTTPSRR)
+
+enum alpnid Curl_alpn2alpnid(char *name, size_t len)
+{
+ if(len == 2) {
+ if(strncasecompare(name, "h1", 2))
+ return ALPN_h1;
+ if(strncasecompare(name, "h2", 2))
+ return ALPN_h2;
+ if(strncasecompare(name, "h3", 2))
+ return ALPN_h3;
+ }
+ else if(len == 8) {
+ if(strncasecompare(name, "http/1.1", 8))
+ return ALPN_h1;
+ }
+ return ALPN_none; /* unknown, probably rubbish input */
+}
+
#endif
/*
@@ -622,7 +640,7 @@ evaluate: *connected = FALSE; /* a negative world view is best */
now = Curl_now();
ongoing = not_started = 0;
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->is_done)
@@ -683,7 +701,7 @@ evaluate: if(not_started > 0) {
int added = 0;
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->has_started)
@@ -717,7 +735,7 @@ evaluate: /* all ballers have failed to connect. */
CURL_TRC_CF(data, cf, "all eyeballers failed");
result = CURLE_COULDNT_CONNECT;
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller)
continue;
@@ -862,7 +880,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(ctx);
DEBUGASSERT(data);
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
baller_free(ctx->baller[i], data);
ctx->baller[i] = NULL;
}
@@ -885,7 +903,7 @@ static CURLcode cf_he_shutdown(struct Curl_cfilter *cf, /* shutdown all ballers that have not done so already. If one fails,
* continue shutting down others until all are shutdown. */
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
bool bdone = FALSE;
if(!baller || !baller->cf || baller->shutdown)
@@ -896,12 +914,12 @@ static CURLcode cf_he_shutdown(struct Curl_cfilter *cf, }
*done = TRUE;
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
if(ctx->baller[i] && !ctx->baller[i]->shutdown)
*done = FALSE;
}
if(*done) {
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
if(ctx->baller[i] && ctx->baller[i]->result)
result = ctx->baller[i]->result;
}
@@ -918,7 +936,7 @@ static void cf_he_adjust_pollset(struct Curl_cfilter *cf, size_t i;
if(!cf->connected) {
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
@@ -940,7 +958,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf, return CURLE_OK;
}
- (void)blocking; /* TODO: do we want to support this? */
+ (void)blocking;
DEBUGASSERT(ctx);
*done = FALSE;
@@ -1015,7 +1033,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf, if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
@@ -1034,7 +1052,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf, size_t i;
memset(&tmax, 0, sizeof(tmax));
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
memset(&t, 0, sizeof(t));
@@ -1059,7 +1077,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf, int reply_ms = -1;
size_t i;
- for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
int breply_ms;
@@ -1193,7 +1211,7 @@ struct transport_provider transport_providers[] = { static cf_ip_connect_create *get_cf_create(int transport)
{
size_t i;
- for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) {
if(transport == transport_providers[i].transport)
return transport_providers[i].cf_create;
}
@@ -1447,7 +1465,7 @@ void Curl_debug_set_transport_provider(int transport, cf_ip_connect_create *cf_create)
{
size_t i;
- for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) {
if(transport == transport_providers[i].transport) {
transport_providers[i].cf_create = cf_create;
return;
@@ -1485,7 +1503,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data, DEBUGASSERT(data);
DEBUGASSERT(conn->handler);
-#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+#if !defined(CURL_DISABLE_HTTP)
if(!conn->cfilter[sockindex] &&
conn->handler->protocol == CURLPROTO_HTTPS) {
DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
@@ -1493,7 +1511,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data, if(result)
goto out;
}
-#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
+#endif /* !defined(CURL_DISABLE_HTTP) */
/* Still no cfilter set, apply default. */
if(!conn->cfilter[sockindex]) {
diff --git a/libs/libcurl/src/connect.h b/libs/libcurl/src/connect.h index c9a12188c4..60cec0a9b3 100644 --- a/libs/libcurl/src/connect.h +++ b/libs/libcurl/src/connect.h @@ -32,6 +32,8 @@ struct Curl_dns_entry;
struct ip_quadruple;
+enum alpnid Curl_alpn2alpnid(char *name, size_t len);
+
/* generic function that returns how much time there is left to run, according
to the timeouts set */
timediff_t Curl_timeleft(struct Curl_easy *data,
diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c index cfd3a51c35..5f1a8089e9 100644 --- a/libs/libcurl/src/content_encoding.c +++ b/libs/libcurl/src/content_encoding.c @@ -65,34 +65,19 @@ /* allow no more than 5 "chained" compression steps */
#define MAX_ENCODE_STACK 5
-
-#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
-
+#define DECOMPRESS_BUFFER_SIZE 16384 /* buffer size for decompressed data */
#ifdef HAVE_LIBZ
-/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
- (doing so will reduce code size slightly). */
-#define OLD_ZLIB_SUPPORT 1
-
-#define GZIP_MAGIC_0 0x1f
-#define GZIP_MAGIC_1 0x8b
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
-#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original filename present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define RESERVED 0xE0 /* bits 5..7: reserved */
+#if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
+#error "requires zlib 1.2.0.4 or newer"
+#endif
typedef enum {
ZLIB_UNINIT, /* uninitialized */
ZLIB_INIT, /* initialized */
ZLIB_INFLATING, /* inflating started. */
ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
- ZLIB_GZIP_HEADER, /* reading gzip header */
- ZLIB_GZIP_INFLATING, /* inflating gzip stream */
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
@@ -100,6 +85,7 @@ typedef enum { struct zlib_writer {
struct Curl_cwriter super;
zlibInitState zlib_init; /* zlib init state */
+ char buffer[DECOMPRESS_BUFFER_SIZE]; /* Put the decompressed data here. */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
};
@@ -137,9 +123,6 @@ static CURLcode exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
- if(*zlib_init == ZLIB_GZIP_HEADER)
- Curl_safefree(z->next_in);
-
if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK)
result = process_zlib_error(data, z);
@@ -183,21 +166,13 @@ static CURLcode inflate_stream(struct Curl_easy *data, Bytef *orig_in = z->next_in;
bool done = FALSE;
CURLcode result = CURLE_OK; /* Curl_client_write status */
- char *decomp; /* Put the decompressed data here. */
/* Check state. */
if(zp->zlib_init != ZLIB_INIT &&
zp->zlib_init != ZLIB_INFLATING &&
- zp->zlib_init != ZLIB_INIT_GZIP &&
- zp->zlib_init != ZLIB_GZIP_INFLATING)
+ zp->zlib_init != ZLIB_INIT_GZIP)
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
- /* Dynamically allocate a buffer for decompression because it is uncommonly
- large to hold on the stack */
- decomp = malloc(DSIZ);
- if(!decomp)
- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
-
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via next_write function. */
while(!done) {
@@ -205,8 +180,8 @@ static CURLcode inflate_stream(struct Curl_easy *data, done = TRUE;
/* (re)set buffer for decompressed output for every iteration */
- z->next_out = (Bytef *) decomp;
- z->avail_out = DSIZ;
+ z->next_out = (Bytef *) zp->buffer;
+ z->avail_out = DECOMPRESS_BUFFER_SIZE;
#ifdef Z_BLOCK
/* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
@@ -217,11 +192,11 @@ static CURLcode inflate_stream(struct Curl_easy *data, #endif
/* Flush output data if some. */
- if(z->avail_out != DSIZ) {
+ if(z->avail_out != DECOMPRESS_BUFFER_SIZE) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
- result = Curl_cwriter_write(data, writer->next, type, decomp,
- DSIZ - z->avail_out);
+ result = Curl_cwriter_write(data, writer->next, type, zp->buffer,
+ DECOMPRESS_BUFFER_SIZE - z->avail_out);
if(result) {
exit_zlib(data, z, &zp->zlib_init, result);
break;
@@ -264,7 +239,6 @@ static CURLcode inflate_stream(struct Curl_easy *data, break;
}
}
- free(decomp);
/* We are about to leave this call so the `nread' data bytes will not be seen
again. If we are in a state that would wrongly allow restart in raw mode
@@ -278,7 +252,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, /* Deflate handler. */
static CURLcode deflate_do_init(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -294,8 +268,8 @@ static CURLcode deflate_do_init(struct Curl_easy *data, }
static CURLcode deflate_do_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -315,7 +289,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data, }
static void deflate_do_close(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -335,7 +309,7 @@ static const struct Curl_cwtype deflate_encoding = { /* Gzip handler. */
static CURLcode gzip_do_init(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -344,115 +318,16 @@ static CURLcode gzip_do_init(struct Curl_easy *data, z->zalloc = (alloc_func) zalloc_cb;
z->zfree = (free_func) zfree_cb;
- if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
- /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
- if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
- return process_zlib_error(data, z);
- }
- zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
- }
- else {
- /* we must parse the gzip header and trailer ourselves */
- if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
- return process_zlib_error(data, z);
- }
- zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
- zp->zlib_init = ZLIB_INIT; /* Initial call state */
- }
+ if(inflateInit2(z, MAX_WBITS + 32) != Z_OK)
+ return process_zlib_error(data, z);
+ zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
return CURLE_OK;
}
-#ifdef OLD_ZLIB_SUPPORT
-/* Skip over the gzip header */
-typedef enum {
- GZIP_OK,
- GZIP_BAD,
- GZIP_UNDERFLOW
-} gzip_status;
-
-static gzip_status check_gzip_header(unsigned char const *data, ssize_t len,
- ssize_t *headerlen)
-{
- int method, flags;
- const ssize_t totallen = len;
-
- /* The shortest header is 10 bytes */
- if(len < 10)
- return GZIP_UNDERFLOW;
-
- if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
- return GZIP_BAD;
-
- method = data[2];
- flags = data[3];
-
- if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
- /* cannot handle this compression method or unknown flag */
- return GZIP_BAD;
- }
-
- /* Skip over time, xflags, OS code and all previous bytes */
- len -= 10;
- data += 10;
-
- if(flags & EXTRA_FIELD) {
- ssize_t extra_len;
-
- if(len < 2)
- return GZIP_UNDERFLOW;
-
- extra_len = (data[1] << 8) | data[0];
-
- if(len < (extra_len + 2))
- return GZIP_UNDERFLOW;
-
- len -= (extra_len + 2);
- data += (extra_len + 2);
- }
-
- if(flags & ORIG_NAME) {
- /* Skip over NUL-terminated filename */
- while(len && *data) {
- --len;
- ++data;
- }
- if(!len || *data)
- return GZIP_UNDERFLOW;
-
- /* Skip over the NUL */
- --len;
- ++data;
- }
-
- if(flags & COMMENT) {
- /* Skip over NUL-terminated comment */
- while(len && *data) {
- --len;
- ++data;
- }
- if(!len || *data)
- return GZIP_UNDERFLOW;
-
- /* Skip over the NUL */
- --len;
- }
-
- if(flags & HEAD_CRC) {
- if(len < 2)
- return GZIP_UNDERFLOW;
-
- len -= 2;
- }
-
- *headerlen = totallen - len;
- return GZIP_OK;
-}
-#endif
-
static CURLcode gzip_do_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -468,117 +343,8 @@ static CURLcode gzip_do_write(struct Curl_easy *data, return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
}
-#ifndef OLD_ZLIB_SUPPORT
- /* Support for old zlib versions is compiled away and we are running with
- an old version, so return an error. */
+ /* We are running with an old version: return error. */
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
-
-#else
- /* This next mess is to get around the potential case where there is not
- * enough data passed in to skip over the gzip header. If that happens, we
- * malloc a block and copy what we have then wait for the next call. If
- * there still is not enough (this is definitely a worst-case scenario), we
- * make the block bigger, copy the next part in and keep waiting.
- *
- * This is only required with zlib versions < 1.2.0.4 as newer versions
- * can handle the gzip header themselves.
- */
-
- switch(zp->zlib_init) {
- /* Skip over gzip header? */
- case ZLIB_INIT:
- {
- /* Initial call state */
- ssize_t hlen;
-
- switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) {
- case GZIP_OK:
- z->next_in = (Bytef *) buf + hlen;
- z->avail_in = (uInt) (nbytes - hlen);
- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
- break;
-
- case GZIP_UNDERFLOW:
- /* We need more data so we can find the end of the gzip header. it is
- * possible that the memory block we malloc here will never be freed if
- * the transfer abruptly aborts after this point. Since it is unlikely
- * that circumstances will be right for this code path to be followed in
- * the first place, and it is even more unlikely for a transfer to fail
- * immediately afterwards, it should seldom be a problem.
- */
- z->avail_in = (uInt) nbytes;
- z->next_in = malloc(z->avail_in);
- if(!z->next_in) {
- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
- }
- memcpy(z->next_in, buf, z->avail_in);
- zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
- /* We do not have any data to inflate yet */
- return CURLE_OK;
-
- case GZIP_BAD:
- default:
- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
- }
-
- }
- break;
-
- case ZLIB_GZIP_HEADER:
- {
- /* Need more gzip header data state */
- ssize_t hlen;
- z->avail_in += (uInt) nbytes;
- z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
- if(!z->next_in) {
- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
- }
- /* Append the new block of data to the previous one */
- memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
-
- switch(check_gzip_header(z->next_in, (ssize_t)z->avail_in, &hlen)) {
- case GZIP_OK:
- /* This is the zlib stream data */
- free(z->next_in);
- /* Do not point into the malloced block since we just freed it */
- z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in;
- z->avail_in = z->avail_in - (uInt)hlen;
- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
- break;
-
- case GZIP_UNDERFLOW:
- /* We still do not have any data to inflate! */
- return CURLE_OK;
-
- case GZIP_BAD:
- default:
- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
- }
-
- }
- break;
-
- case ZLIB_EXTERNAL_TRAILER:
- z->next_in = (Bytef *) buf;
- z->avail_in = (uInt) nbytes;
- return process_trailer(data, zp);
-
- case ZLIB_GZIP_INFLATING:
- default:
- /* Inflating stream state */
- z->next_in = (Bytef *) buf;
- z->avail_in = (uInt) nbytes;
- break;
- }
-
- if(z->avail_in == 0) {
- /* We do not have any data to inflate; wait until next time */
- return CURLE_OK;
- }
-
- /* We have parsed the header, now uncompress the data */
- return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
-#endif
}
static void gzip_do_close(struct Curl_easy *data,
@@ -601,11 +367,11 @@ static const struct Curl_cwtype gzip_encoding = { #endif /* HAVE_LIBZ */
-
#ifdef HAVE_BROTLI
/* Brotli writer. */
struct brotli_writer {
struct Curl_cwriter super;
+ char buffer[DECOMPRESS_BUFFER_SIZE];
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -648,7 +414,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) }
static CURLcode brotli_do_init(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
@@ -658,12 +424,11 @@ static CURLcode brotli_do_init(struct Curl_easy *data, }
static CURLcode brotli_do_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf;
- char *decomp;
uint8_t *dst;
size_t dstleft;
CURLcode result = CURLE_OK;
@@ -675,18 +440,14 @@ static CURLcode brotli_do_write(struct Curl_easy *data, if(!bp->br)
return CURLE_WRITE_ERROR; /* Stream already ended. */
- decomp = malloc(DSIZ);
- if(!decomp)
- return CURLE_OUT_OF_MEMORY;
-
while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
result == CURLE_OK) {
- dst = (uint8_t *) decomp;
- dstleft = DSIZ;
+ dst = (uint8_t *) bp->buffer;
+ dstleft = DECOMPRESS_BUFFER_SIZE;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
result = Curl_cwriter_write(data, writer->next, type,
- decomp, DSIZ - dstleft);
+ bp->buffer, DECOMPRESS_BUFFER_SIZE - dstleft);
if(result)
break;
switch(r) {
@@ -704,7 +465,6 @@ static CURLcode brotli_do_write(struct Curl_easy *data, break;
}
}
- free(decomp);
return result;
}
@@ -712,7 +472,6 @@ static void brotli_do_close(struct Curl_easy *data, struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
-
(void) data;
if(bp->br) {
@@ -731,30 +490,51 @@ static const struct Curl_cwtype brotli_encoding = { };
#endif
-
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
struct Curl_cwriter super;
ZSTD_DStream *zds; /* State structure for zstd. */
- void *decomp;
+ char buffer[DECOMPRESS_BUFFER_SIZE];
};
+#ifdef ZSTD_STATIC_LINKING_ONLY
+static void *Curl_zstd_alloc(void *opaque, size_t size)
+{
+ (void)opaque;
+ return Curl_cmalloc(size);
+}
+
+static void Curl_zstd_free(void *opaque, void *address)
+{
+ (void)opaque;
+ Curl_cfree(address);
+}
+#endif
+
static CURLcode zstd_do_init(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
(void)data;
+#ifdef ZSTD_STATIC_LINKING_ONLY
+ zp->zds = ZSTD_createDStream_advanced((ZSTD_customMem) {
+ .customAlloc = Curl_zstd_alloc,
+ .customFree = Curl_zstd_free,
+ .opaque = NULL
+ });
+#else
zp->zds = ZSTD_createDStream();
- zp->decomp = NULL;
+#endif
+
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
static CURLcode zstd_do_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -765,19 +545,14 @@ static CURLcode zstd_do_write(struct Curl_easy *data, if(!(type & CLIENTWRITE_BODY) || !nbytes)
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
- if(!zp->decomp) {
- zp->decomp = malloc(DSIZ);
- if(!zp->decomp)
- return CURLE_OUT_OF_MEMORY;
- }
in.pos = 0;
in.src = buf;
in.size = nbytes;
for(;;) {
out.pos = 0;
- out.dst = zp->decomp;
- out.size = DSIZ;
+ out.dst = zp->buffer;
+ out.size = DECOMPRESS_BUFFER_SIZE;
errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
if(ZSTD_isError(errorCode)) {
@@ -785,7 +560,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, }
if(out.pos > 0) {
result = Curl_cwriter_write(data, writer->next, type,
- zp->decomp, out.pos);
+ zp->buffer, out.pos);
if(result)
break;
}
@@ -800,13 +575,8 @@ static void zstd_do_close(struct Curl_easy *data, struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
-
(void)data;
- if(zp->decomp) {
- free(zp->decomp);
- zp->decomp = NULL;
- }
if(zp->zds) {
ZSTD_freeDStream(zp->zds);
zp->zds = NULL;
@@ -823,7 +593,6 @@ static const struct Curl_cwtype zstd_encoding = { };
#endif
-
/* Identity handler. */
static const struct Curl_cwtype identity_encoding = {
"identity",
@@ -834,7 +603,6 @@ static const struct Curl_cwtype identity_encoding = { sizeof(struct Curl_cwriter)
};
-
/* supported general content decoders. */
static const struct Curl_cwtype * const general_unencoders[] = {
&identity_encoding,
@@ -898,7 +666,7 @@ void Curl_all_content_encodings(char *buf, size_t blen) /* Deferred error dummy writer. */
static CURLcode error_do_init(struct Curl_easy *data,
- struct Curl_cwriter *writer)
+ struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
@@ -906,8 +674,8 @@ static CURLcode error_do_init(struct Curl_easy *data, }
static CURLcode error_do_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
(void) writer;
(void) buf;
@@ -1082,5 +850,4 @@ void Curl_all_content_encodings(char *buf, size_t blen) strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
-
#endif /* CURL_DISABLE_HTTP */
diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index 44197b586c..147378d812 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -97,6 +97,26 @@ Example set of cookies: static void strstore(char **str, const char *newstr, size_t len);
+/* number of seconds in 400 days */
+#define COOKIES_MAXAGE (400*24*3600)
+
+/* Make sure cookies never expire further away in time than 400 days into the
+ future. (from RFC6265bis draft-19)
+
+ For the sake of easier testing, align the capped time to an even 60 second
+ boundary.
+*/
+static void cap_expires(time_t now, struct Cookie *co)
+{
+ if((TIME_T_MAX - COOKIES_MAXAGE - 30) > now) {
+ timediff_t cap = now + COOKIES_MAXAGE;
+ if(co->expires > cap) {
+ cap += 30;
+ co->expires = (cap/60)*60;
+ }
+ }
+}
+
static void freecookie(struct Cookie *co)
{
free(co->domain);
@@ -438,7 +458,7 @@ static bool bad_domain(const char *domain, size_t len) fine. The prime reason for filtering out control bytes is that some HTTP
servers return 400 for requests that contain such.
*/
-static int invalid_octets(const char *p)
+static bool invalid_octets(const char *p)
{
/* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */
static const char badoctets[] = {
@@ -449,7 +469,7 @@ static int invalid_octets(const char *p) size_t len;
/* scan for all the octets that are *not* in cookie-octet */
len = strcspn(p, badoctets);
- return (p[len] != '\0');
+ return p[len] != '\0';
}
#define CERR_OK 0
@@ -469,6 +489,13 @@ static int invalid_octets(const char *p) #define CERR_PSL 14 /* a public suffix */
#define CERR_LIVE_WINS 15
+/* The maximum length we accept a date string for the 'expire' keyword. The
+ standard date formats are within the 30 bytes range. This adds an extra
+ margin just to make sure it realistically works with what is used out
+ there.
+*/
+#define MAX_DATE_LENGTH 80
+
static int
parse_cookie_header(struct Curl_easy *data,
struct Cookie *co,
@@ -707,16 +734,20 @@ parse_cookie_header(struct Curl_easy *data, co->expires += now;
break;
}
+ cap_expires(now, co);
}
else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
- if(!co->expires) {
+ if(!co->expires && (vlen < MAX_DATE_LENGTH)) {
/*
* Let max-age have priority.
*
* If the date cannot get parsed for whatever reason, the cookie
* will be treated as a session cookie
*/
- co->expires = Curl_getdate_capped(valuep);
+ char dbuf[MAX_DATE_LENGTH + 1];
+ memcpy(dbuf, valuep, vlen);
+ dbuf[vlen] = 0;
+ co->expires = Curl_getdate_capped(dbuf);
/*
* Session cookies have expires set to 0 so if we get that back
@@ -727,6 +758,7 @@ parse_cookie_header(struct Curl_easy *data, co->expires = 1;
else if(co->expires < 0)
co->expires = 0;
+ cap_expires(now, co);
}
}
@@ -805,10 +837,9 @@ parse_netscape(struct Cookie *co, * This line is NOT an HTTP header style line, we do offer support for
* reading the odd netscape cookies-file format here
*/
- char *ptr;
- char *firstptr;
- char *tok_buf = NULL;
+ const char *ptr, *next;
int fields;
+ size_t len;
/*
* In 2008, Internet Explorer introduced HTTP-only cookies to prevent XSS
@@ -825,29 +856,22 @@ parse_netscape(struct Cookie *co, /* do not even try the comments */
return CERR_COMMENT;
- /* strip off the possible end-of-line characters */
- ptr = strchr(lineptr, '\r');
- if(ptr)
- *ptr = 0; /* clear it */
- ptr = strchr(lineptr, '\n');
- if(ptr)
- *ptr = 0; /* clear it */
-
- /* tokenize on TAB */
- firstptr = Curl_strtok_r((char *)lineptr, "\t", &tok_buf);
-
/*
* Now loop through the fields and init the struct we already have
* allocated
*/
fields = 0;
- for(ptr = firstptr; ptr;
- ptr = Curl_strtok_r(NULL, "\t", &tok_buf), fields++) {
+ for(next = lineptr; next; fields++) {
+ ptr = next;
+ len = strcspn(ptr, "\t\r\n");
+ next = (ptr[len] == '\t' ? &ptr[len + 1] : NULL);
switch(fields) {
case 0:
- if(ptr[0]=='.') /* skip preceding dots */
+ if(ptr[0]=='.') { /* skip preceding dots */
ptr++;
- co->domain = strdup(ptr);
+ len--;
+ }
+ co->domain = Curl_memdup0(ptr, len);
if(!co->domain)
return CERR_OUT_OF_MEMORY;
break;
@@ -855,15 +879,15 @@ parse_netscape(struct Cookie *co, /*
* flag: A TRUE/FALSE value indicating if all machines within a given
* domain can access the variable. Set TRUE when the cookie says
- * .domain.com and to false when the domain is complete www.domain.com
+ * .example.com and to false when the domain is complete www.example.com
*/
- co->tailmatch = !!strcasecompare(ptr, "TRUE");
+ co->tailmatch = !!strncasecompare(ptr, "TRUE", len);
break;
case 2:
/* The file format allows the path field to remain not filled in */
- if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
+ if(strncmp("TRUE", ptr, len) && strncmp("FALSE", ptr, len)) {
/* only if the path does not look like a boolean option! */
- co->path = strdup(ptr);
+ co->path = Curl_memdup0(ptr, len);
if(!co->path)
return CERR_OUT_OF_MEMORY;
else {
@@ -884,7 +908,7 @@ parse_netscape(struct Cookie *co, FALLTHROUGH();
case 3:
co->secure = FALSE;
- if(strcasecompare(ptr, "TRUE")) {
+ if(strncasecompare(ptr, "TRUE", len)) {
if(secure || ci->running)
co->secure = TRUE;
else
@@ -892,11 +916,19 @@ parse_netscape(struct Cookie *co, }
break;
case 4:
- if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
- return CERR_RANGE;
+ {
+ char *endp;
+ const char *p;
+ /* make sure curlx_strtoofft won't read past the current field */
+ for(p = ptr; p < &ptr[len] && ISDIGIT(*p); ++p)
+ ;
+ if(p == ptr || p != &ptr[len] ||
+ curlx_strtoofft(ptr, &endp, 10, &co->expires) || endp != &ptr[len])
+ return CERR_RANGE;
+ }
break;
case 5:
- co->name = strdup(ptr);
+ co->name = Curl_memdup0(ptr, len);
if(!co->name)
return CERR_OUT_OF_MEMORY;
else {
@@ -908,7 +940,7 @@ parse_netscape(struct Cookie *co, }
break;
case 6:
- co->value = strdup(ptr);
+ co->value = Curl_memdup0(ptr, len);
if(!co->value)
return CERR_OUT_OF_MEMORY;
break;
@@ -1303,14 +1335,14 @@ static int cookie_sort(const void *p1, const void *p2) l2 = c2->path ? strlen(c2->path) : 0;
if(l1 != l2)
- return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+ return (l2 > l1) ? 1 : -1; /* avoid size_t <=> int conversions */
/* 2 - compare cookie domain lengths */
l1 = c1->domain ? strlen(c1->domain) : 0;
l2 = c2->domain ? strlen(c2->domain) : 0;
if(l1 != l2)
- return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+ return (l2 > l1) ? 1 : -1; /* avoid size_t <=> int conversions */
/* 3 - compare cookie name lengths */
l1 = c1->name ? strlen(c1->name) : 0;
diff --git a/libs/libcurl/src/cookie.h b/libs/libcurl/src/cookie.h index 9064c694ec..d8e92e94b2 100644 --- a/libs/libcurl/src/cookie.h +++ b/libs/libcurl/src/cookie.h @@ -38,7 +38,7 @@ struct Cookie { char *spath; /* sanitized cookie path */
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
- int creationtime; /* time when the cookie was written */
+ unsigned int creationtime; /* time when the cookie was written */
BIT(tailmatch); /* tail-match the domain name */
BIT(secure); /* the 'secure' keyword was used */
BIT(livecookie); /* updated from a server, not a stored file */
@@ -60,10 +60,10 @@ struct CookieInfo { /* linked lists of cookies we know of */
struct Curl_llist cookielist[COOKIE_HASH_SIZE];
curl_off_t next_expiration; /* the next time at which expiration happens */
- int numcookies; /* number of cookies in the "jar" */
- int lastct; /* last creation-time used in the jar */
- bool running; /* state info, for cookie adding information */
- bool newsession; /* new session, discard session cookies on load */
+ unsigned int numcookies; /* number of cookies in the "jar" */
+ unsigned int lastct; /* last creation-time used in the jar */
+ BIT(running); /* state info, for cookie adding information */
+ BIT(newsession); /* new session, discard session cookies on load */
};
/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
diff --git a/libs/libcurl/src/curl_addrinfo.c b/libs/libcurl/src/curl_addrinfo.c index 1f895263c8..446c566be9 100644 --- a/libs/libcurl/src/curl_addrinfo.c +++ b/libs/libcurl/src/curl_addrinfo.c @@ -318,11 +318,7 @@ Curl_he2ai(const struct hostent *he, int port) addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
-#ifdef __MINGW32__
- addr->sin_family = (short)(he->h_addrtype);
-#else
addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
-#endif
addr->sin_port = htons((unsigned short)port);
break;
@@ -331,11 +327,7 @@ Curl_he2ai(const struct hostent *he, int port) addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
-#ifdef __MINGW32__
- addr6->sin6_family = (short)(he->h_addrtype);
-#else
addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
-#endif
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index 3fa058aa19..c6ecb255ba 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -433,6 +433,9 @@ /* If you have poll */
#cmakedefine HAVE_POLL 1
+/* If you have realpath */
+#cmakedefine HAVE_REALPATH 1
+
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
@@ -565,9 +568,6 @@ /* Define to 1 if you have the <sys/filio.h> header file. */
#cmakedefine HAVE_SYS_FILIO_H 1
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#cmakedefine HAVE_SYS_WAIT_H 1
-
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H 1
@@ -625,8 +625,8 @@ /* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
-/* Define to 1 if you need the malloc.h header file even with stdlib.h */
-#cmakedefine NEED_MALLOC_H 1
+/* Define this if time_t is unsigned */
+#cmakedefine HAVE_TIME_T_UNSIGNED 1
/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
#cmakedefine NEED_REENTRANT 1
@@ -634,24 +634,6 @@ /* cpu-machine-OS */
#cmakedefine CURL_OS ${CURL_OS}
-/* Name of package */
-#cmakedefine PACKAGE ${PACKAGE}
-
-/* Define to the address where bug reports for this package should be sent. */
-#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT}
-
-/* Define to the full name of this package. */
-#cmakedefine PACKAGE_NAME ${PACKAGE_NAME}
-
-/* Define to the full name and version of this package. */
-#cmakedefine PACKAGE_STRING ${PACKAGE_STRING}
-
-/* Define to the one symbol short name of this package. */
-#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME}
-
-/* Define to the version of this package. */
-#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
-
/*
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
As per CMake documentation on CheckTypeSize, C preprocessor code is
@@ -703,6 +685,9 @@ ${SIZEOF_TIME_T_CODE} /* if Secure Transport is enabled */
#cmakedefine USE_SECTRANSP 1
+/* if SSL session export support is available */
+#cmakedefine USE_SSLS_EXPORT 1
+
/* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1
@@ -742,6 +727,9 @@ ${SIZEOF_TIME_T_CODE} /* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
+/* if AmiSSL is in use */
+#cmakedefine USE_AMISSL 1
+
/* if librtmp/rtmpdump is in use */
#cmakedefine USE_LIBRTMP 1
@@ -791,12 +779,12 @@ ${SIZEOF_TIME_T_CODE} /* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
+/* if Watt-32 is in use */
+#cmakedefine USE_WATT32 1
+
/* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1
-/* Version number of package */
-#cmakedefine VERSION ${VERSION}
-
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
@@ -841,3 +829,9 @@ ${SIZEOF_TIME_T_CODE} /* if ECH support is available */
#cmakedefine USE_ECH 1
+
+/* Define to 1 if you have the wolfSSL_CTX_GenerateEchConfig function. */
+#cmakedefine HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
+
+/* Define to 1 if you have the SSL_set1_ech_config_list function. */
+#cmakedefine HAVE_SSL_SET1_ECH_CONFIG_LIST
diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index 60ad77859b..c139f814cb 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -1,8 +1,5 @@ /* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
-/* Ignore c-ares deprecation warnings */
-#undef CARES_NO_DEPRECATED
-
/* to enable curl debug memory tracking */
#undef CURLDEBUG
@@ -162,9 +159,6 @@ /* cpu-machine-OS */
#undef CURL_OS
-/* IP address type in sockaddr */
-#undef CURL_SA_FAMILY_T
-
/* built with multiple SSL backends */
#undef CURL_WITH_MULTI_SSL
@@ -174,6 +168,9 @@ /* Define to the type of arg 2 for gethostname. */
#undef GETHOSTNAME_TYPE_ARG2
+/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
+#undef HAVE_ADDRESS_FAMILY
+
/* Define to 1 if you have the alarm function. */
#undef HAVE_ALARM
@@ -214,28 +211,15 @@ /* Define to 1 if you have the CloseSocket camel case function. */
#undef HAVE_CLOSESOCKET_CAMEL
-/* Define to 1 if you have the <crypto.h> header file. */
-#undef HAVE_CRYPTO_H
-
/* Define to 1 if you have the fseeko declaration */
#undef HAVE_DECL_FSEEKO
-/* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you
- don't. */
-#undef HAVE_DECL_GETPWUID_R
-
-/* "Set if getpwuid_r() declaration is missing" */
-#undef HAVE_DECL_GETPWUID_R_MISSING
-
/* if you have <dirent.h> */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
-/* Define to 1 if you have the <err.h> header file. */
-#undef HAVE_ERR_H
-
/* Define to 1 if you have the `eventfd' function. */
#undef HAVE_EVENTFD
@@ -278,9 +262,6 @@ /* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
-/* Define to 1 if you have the gethostbyname function. */
-#undef HAVE_GETHOSTBYNAME
-
/* Define to 1 if you have the gethostbyname_r function. */
#undef HAVE_GETHOSTBYNAME_R
@@ -347,9 +328,6 @@ /* if you have GNU GSS */
#undef HAVE_GSSGNU
-/* Define to 1 if you have the <hyper.h> header file. */
-#undef HAVE_HYPER_H
-
/* Define to 1 if you have the <idn2.h> header file. */
#undef HAVE_IDN2_H
@@ -368,9 +346,6 @@ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
-/* Define to 1 if you have the ioctl function. */
-#undef HAVE_IOCTL
-
/* Define to 1 if you have the ioctlsocket function. */
#undef HAVE_IOCTLSOCKET
@@ -423,9 +398,6 @@ /* Define to 1 if you have the <libpsl.h> header file. */
#undef HAVE_LIBPSL_H
-/* Define to 1 if using LibreSSL. */
-#undef HAVE_LIBRESSL
-
/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
#undef HAVE_LIBRTMP_RTMP_H
@@ -527,9 +499,6 @@ /* Define to 1 if you have the <openssl/x509.h> header file. */
#undef HAVE_OPENSSL_X509_H
-/* Define to 1 if you have the <pem.h> header file. */
-#undef HAVE_PEM_H
-
/* Define to 1 if you have the `pipe' function. */
#undef HAVE_PIPE
@@ -557,11 +526,14 @@ /* Define to 1 if you have the <quiche.h> header file. */
#undef HAVE_QUICHE_H
+/* Define to 1 if you have the `realpath' function. */
+#undef HAVE_REALPATH
+
/* Define to 1 if you have the recv function. */
#undef HAVE_RECV
-/* Define to 1 if you have the <rsa.h> header file. */
-#undef HAVE_RSA_H
+/* Define to 1 if symbol `sa_family_t' exists */
+#undef HAVE_SA_FAMILY_T
/* Define to 1 if you have the `sched_yield' function. */
#undef HAVE_SCHED_YIELD
@@ -578,9 +550,6 @@ /* Define to 1 if you have the `sendmsg' function. */
#undef HAVE_SENDMSG
-/* Define to 1 if you have the <setjmp.h> header file. */
-#undef HAVE_SETJMP_H
-
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
@@ -614,12 +583,6 @@ /* Define to 1 if you have the socketpair function. */
#undef HAVE_SOCKETPAIR
-/* Define to 1 if you have the `SSL_ech_set1_echconfig' function. */
-#undef HAVE_SSL_ECH_SET1_ECHCONFIG
-
-/* Define to 1 if you have the <ssl.h> header file. */
-#undef HAVE_SSL_H
-
/* Define to 1 if you have the `SSL_set0_wbio' function. */
#undef HAVE_SSL_SET0_WBIO
@@ -726,9 +689,6 @@ /* Define to 1 if you have the <sys/utime.h> header file. */
#undef HAVE_SYS_UTIME_H
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
/* Define to 1 if you have the <sys/xattr.h> header file. */
#undef HAVE_SYS_XATTR_H
@@ -783,9 +743,6 @@ /* Define this symbol if your OS supports changing the contents of argv */
#undef HAVE_WRITABLE_ARGV
-/* Define to 1 if you have the <x509.h> header file. */
-#undef HAVE_X509_H
-
/* if libzstd is in use */
#undef HAVE_ZSTD
@@ -881,9 +838,6 @@ /* enable HTTPS RR support */
#undef USE_HTTPSRR
-/* if hyper is in use */
-#undef USE_HYPER
-
/* Define if you want to enable IPv6 support */
#undef USE_IPV6
@@ -917,30 +871,12 @@ /* if ngtcp2 is in use */
#undef USE_NGTCP2
-/* if ngtcp2_crypto_boringssl is in use */
-#undef USE_NGTCP2_CRYPTO_BORINGSSL
-
-/* if ngtcp2_crypto_gnutls is in use */
-#undef USE_NGTCP2_CRYPTO_GNUTLS
-
-/* if ngtcp2_crypto_quictls is in use */
-#undef USE_NGTCP2_CRYPTO_QUICTLS
-
-/* if ngtcp2_crypto_wolfssl is in use */
-#undef USE_NGTCP2_CRYPTO_WOLFSSL
-
-/* if ngtcp2 + nghttp3 is in use */
-#undef USE_NGTCP2_H3
-
/* Use OpenLDAP-specific code */
#undef USE_OPENLDAP
/* if OpenSSL is in use */
#undef USE_OPENSSL
-/* if openssl quic + nghttp3 is in use */
-#undef USE_OPENSSL_H3
-
/* if openssl QUIC is in use */
#undef USE_OPENSSL_QUIC
@@ -956,6 +892,9 @@ /* enable Secure Transport */
#undef USE_SECTRANSP
+/* if SSL session export support is available */
+#undef USE_SSLS_EXPORT
+
/* if you want POSIX threaded DNS lookup */
#undef USE_THREADS_POSIX
@@ -968,6 +907,9 @@ /* Use Unix domain sockets */
#undef USE_UNIX_SOCKETS
+/* if Watt-32 is in use */
+#undef USE_WATT32
+
/* Define to 1 if you are building a Windows target with crypto API support.
*/
#undef USE_WIN32_CRYPTO
@@ -982,10 +924,6 @@ /* Use Windows LDAP implementation */
#undef USE_WIN32_LDAP
-/* Define to 1 if you are building a Windows target without large file
- support. */
-#undef USE_WIN32_SMALL_FILES
-
/* to enable SSPI support */
#undef USE_WINDOWS_SSPI
diff --git a/libs/libcurl/src/curl_ctype.h b/libs/libcurl/src/curl_ctype.h index a04dc358ea..02fa4e685e 100644 --- a/libs/libcurl/src/curl_ctype.h +++ b/libs/libcurl/src/curl_ctype.h @@ -46,6 +46,6 @@ #define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
((x) == '~'))
#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
-
+#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
#endif /* HEADER_CURL_CTYPE_H */
diff --git a/libs/libcurl/src/curl_get_line.c b/libs/libcurl/src/curl_get_line.c index dda1d63c1e..e88d0cc34d 100644 --- a/libs/libcurl/src/curl_get_line.c +++ b/libs/libcurl/src/curl_get_line.c @@ -28,7 +28,9 @@ !defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
+#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
+#endif
/* The last #include file should be: */
#include "memdebug.h"
diff --git a/libs/libcurl/src/curl_get_line.h b/libs/libcurl/src/curl_get_line.h index 9b8c0d8410..9debce926d 100644 --- a/libs/libcurl/src/curl_get_line.h +++ b/libs/libcurl/src/curl_get_line.h @@ -26,6 +26,12 @@ #include "dynbuf.h"
+#ifndef BUILDING_LIBCURL
+/* this renames functions so that the tool code can use the same code
+ without getting symbol collisions */
+#define Curl_get_line(a,b) curlx_get_line(a,b)
+#endif
+
/* Curl_get_line() returns complete lines that end with a newline. */
int Curl_get_line(struct dynbuf *buf, FILE *input);
diff --git a/libs/libcurl/src/curl_gethostname.c b/libs/libcurl/src/curl_gethostname.c index f55514acad..9aefde3f26 100644 --- a/libs/libcurl/src/curl_gethostname.c +++ b/libs/libcurl/src/curl_gethostname.c @@ -73,7 +73,11 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen) #else /* DEBUGBUILD */
name[0] = '\0';
+#ifdef __AMIGA__
+ err = gethostname((unsigned char *)name, namelen);
+#else
err = gethostname(name, namelen);
+#endif
#endif
diff --git a/libs/libcurl/src/curl_gssapi.c b/libs/libcurl/src/curl_gssapi.c index 5988348812..e963bc487a 100644 --- a/libs/libcurl/src/curl_gssapi.c +++ b/libs/libcurl/src/curl_gssapi.c @@ -40,6 +40,11 @@ #define CURL_ALIGN8
#endif
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
gss_OID_desc Curl_spnego_mech_oid CURL_ALIGN8 = {
6, (char *)"\x2b\x06\x01\x05\x05\x02"
};
@@ -149,4 +154,8 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, #endif
}
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* HAVE_GSSAPI */
diff --git a/libs/libcurl/src/curl_hmac.h b/libs/libcurl/src/curl_hmac.h index dee12456ea..14b004d232 100644 --- a/libs/libcurl/src/curl_hmac.h +++ b/libs/libcurl/src/curl_hmac.h @@ -24,9 +24,9 @@ *
***************************************************************************/
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
- || defined(USE_LIBSSH2)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \
+ !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ defined(USE_SSL)
#include <curl/curl.h>
diff --git a/libs/libcurl/src/curl_multibyte.c b/libs/libcurl/src/curl_multibyte.c index a991df2906..5da11e1c38 100644 --- a/libs/libcurl/src/curl_multibyte.c +++ b/libs/libcurl/src/curl_multibyte.c @@ -32,7 +32,7 @@ #include "curl_setup.h"
-#if defined(_WIN32)
+#ifdef _WIN32
#include "curl_multibyte.h"
@@ -84,16 +84,170 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8;
}
-#endif /* _WIN32 */
+/* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */
+#if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN10)
+WINBASEAPI DWORD WINAPI GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR *);
+#endif
+
+/* Fix excessive paths (paths that exceed MAX_PATH length of 260).
+ *
+ * This is a helper function to fix paths that would exceed the MAX_PATH
+ * limitation check done by Windows APIs. It does so by normalizing the passed
+ * in filename or path 'in' to its full canonical path, and if that path is
+ * longer than MAX_PATH then setting 'out' to "\\?\" prefix + that full path.
+ *
+ * For example 'in' filename255chars in current directory C:\foo\bar is
+ * fixed as \\?\C:\foo\bar\filename255chars for 'out' which will tell Windows
+ * it is ok to access that filename even though the actual full path is longer
+ * than 260 chars.
+ *
+ * For non-Unicode builds this function may fail sometimes because only the
+ * Unicode versions of some Windows API functions can access paths longer than
+ * MAX_PATH, for example GetFullPathNameW which is used in this function. When
+ * the full path is then converted from Unicode to multibyte that fails if any
+ * directories in the path contain characters not in the current codepage.
+ */
+static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
+{
+ size_t needed, count;
+ const wchar_t *in_w;
+ wchar_t *fbuf = NULL;
+
+ /* MS documented "approximate" limit for the maximum path length */
+ const size_t max_path_len = 32767;
+
+#ifndef _UNICODE
+ wchar_t *ibuf = NULL;
+ char *obuf = NULL;
+#endif
+
+ *out = NULL;
+
+ /* skip paths already normalized */
+ if(!_tcsncmp(in, _T("\\\\?\\"), 4))
+ goto cleanup;
+
+#ifndef _UNICODE
+ /* convert multibyte input to unicode */
+ needed = mbstowcs(NULL, in, 0);
+ if(needed == (size_t)-1 || needed >= max_path_len)
+ goto cleanup;
+ ++needed; /* for NUL */
+ ibuf = malloc(needed * sizeof(wchar_t));
+ if(!ibuf)
+ goto cleanup;
+ count = mbstowcs(ibuf, in, needed);
+ if(count == (size_t)-1 || count >= needed)
+ goto cleanup;
+ in_w = ibuf;
+#else
+ in_w = in;
+#endif
+
+ /* GetFullPathNameW returns the normalized full path in unicode. It converts
+ forward slashes to backslashes, processes .. to remove directory segments,
+ etc. Unlike GetFullPathNameA it can process paths that exceed MAX_PATH. */
+ needed = (size_t)GetFullPathNameW(in_w, 0, NULL, NULL);
+ if(!needed || needed > max_path_len)
+ goto cleanup;
+ /* skip paths that are not excessive and do not need modification */
+ if(needed <= MAX_PATH)
+ goto cleanup;
+ fbuf = malloc(needed * sizeof(wchar_t));
+ if(!fbuf)
+ goto cleanup;
+ count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL);
+ if(!count || count >= needed)
+ goto cleanup;
+
+ /* prepend \\?\ or \\?\UNC\ to the excessively long path.
+ *
+ * c:\longpath ---> \\?\c:\longpath
+ * \\.\c:\longpath ---> \\?\c:\longpath
+ * \\?\c:\longpath ---> \\?\c:\longpath (unchanged)
+ * \\server\c$\longpath ---> \\?\UNC\server\c$\longpath
+ *
+ * https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
+ */
+ if(!wcsncmp(fbuf, L"\\\\?\\", 4))
+ ; /* do nothing */
+ else if(!wcsncmp(fbuf, L"\\\\.\\", 4))
+ fbuf[2] = '?';
+ else if(!wcsncmp(fbuf, L"\\\\.", 3) || !wcsncmp(fbuf, L"\\\\?", 3)) {
+ /* Unexpected, not UNC. The formatting doc doesn't allow this AFAICT. */
+ goto cleanup;
+ }
+ else {
+ wchar_t *temp;
+
+ if(!wcsncmp(fbuf, L"\\\\", 2)) {
+ /* "\\?\UNC\" + full path without "\\" + null */
+ needed = 8 + (count - 2) + 1;
+ if(needed > max_path_len)
+ goto cleanup;
+
+ temp = malloc(needed * sizeof(wchar_t));
+ if(!temp)
+ goto cleanup;
-#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
+ wcsncpy(temp, L"\\\\?\\UNC\\", 8);
+ wcscpy(temp + 8, fbuf + 2);
+ }
+ else {
+ /* "\\?\" + full path + null */
+ needed = 4 + count + 1;
+ if(needed > max_path_len)
+ goto cleanup;
+
+ temp = malloc(needed * sizeof(wchar_t));
+ if(!temp)
+ goto cleanup;
+
+ wcsncpy(temp, L"\\\\?\\", 4);
+ wcscpy(temp + 4, fbuf);
+ }
+
+ free(fbuf);
+ fbuf = temp;
+ }
+
+#ifndef _UNICODE
+ /* convert unicode full path to multibyte output */
+ needed = wcstombs(NULL, fbuf, 0);
+ if(needed == (size_t)-1 || needed >= max_path_len)
+ goto cleanup;
+ ++needed; /* for NUL */
+ obuf = malloc(needed);
+ if(!obuf)
+ goto cleanup;
+ count = wcstombs(obuf, fbuf, needed);
+ if(count == (size_t)-1 || count >= needed)
+ goto cleanup;
+ *out = obuf;
+ obuf = NULL;
+#else
+ *out = fbuf;
+ fbuf = NULL;
+#endif
+
+cleanup:
+ free(fbuf);
+#ifndef _UNICODE
+ free(ibuf);
+ free(obuf);
+#endif
+ return *out ? true : false;
+}
int curlx_win32_open(const char *filename, int oflag, ...)
{
int pmode = 0;
+ int result = -1;
+ TCHAR *fixed = NULL;
+ const TCHAR *target = NULL;
#ifdef _UNICODE
- int result = -1;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
#endif
@@ -105,58 +259,95 @@ int curlx_win32_open(const char *filename, int oflag, ...) #ifdef _UNICODE
if(filename_w) {
- result = _wopen(filename_w, oflag, pmode);
+ if(fix_excessive_path(filename_w, &fixed))
+ target = fixed;
+ else
+ target = filename_w;
+ result = _wopen(target, oflag, pmode);
curlx_unicodefree(filename_w);
}
else
errno = EINVAL;
- return result;
#else
- return (_open)(filename, oflag, pmode);
+ if(fix_excessive_path(filename, &fixed))
+ target = fixed;
+ else
+ target = filename;
+ result = (_open)(target, oflag, pmode);
#endif
+
+ free(fixed);
+ return result;
}
FILE *curlx_win32_fopen(const char *filename, const char *mode)
{
-#ifdef _UNICODE
FILE *result = NULL;
+ TCHAR *fixed = NULL;
+ const TCHAR *target = NULL;
+
+#ifdef _UNICODE
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
- if(filename_w && mode_w)
- result = _wfopen(filename_w, mode_w);
+ if(filename_w && mode_w) {
+ if(fix_excessive_path(filename_w, &fixed))
+ target = fixed;
+ else
+ target = filename_w;
+ result = _wfopen(target, mode_w);
+ }
else
errno = EINVAL;
curlx_unicodefree(filename_w);
curlx_unicodefree(mode_w);
- return result;
#else
- return (fopen)(filename, mode);
+ if(fix_excessive_path(filename, &fixed))
+ target = fixed;
+ else
+ target = filename;
+ result = (fopen)(target, mode);
#endif
+
+ free(fixed);
+ return result;
}
int curlx_win32_stat(const char *path, struct_stat *buffer)
{
-#ifdef _UNICODE
int result = -1;
+ TCHAR *fixed = NULL;
+ const TCHAR *target = NULL;
+
+#ifdef _UNICODE
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
-#if defined(USE_WIN32_SMALL_FILES)
- result = _wstat(path_w, buffer);
+ if(fix_excessive_path(path_w, &fixed))
+ target = fixed;
+ else
+ target = path_w;
+#ifndef USE_WIN32_LARGE_FILES
+ result = _wstat(target, buffer);
#else
- result = _wstati64(path_w, buffer);
+ result = _wstati64(target, buffer);
#endif
curlx_unicodefree(path_w);
}
else
errno = EINVAL;
- return result;
#else
-#if defined(USE_WIN32_SMALL_FILES)
- return _stat(path, buffer);
+ if(fix_excessive_path(path, &fixed))
+ target = fixed;
+ else
+ target = path;
+#ifndef USE_WIN32_LARGE_FILES
+ result = _stat(target, buffer);
#else
- return _stati64(path, buffer);
+ result = _stati64(target, buffer);
#endif
#endif
+
+ free(fixed);
+ return result;
}
-#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
+#endif /* _WIN32 */
diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c index 9e1d578db1..d00c1f4e22 100644 --- a/libs/libcurl/src/curl_rtmp.c +++ b/libs/libcurl/src/curl_rtmp.c @@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_rtmp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -109,6 +110,7 @@ const struct Curl_handler Curl_handler_rtmpt = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
@@ -133,6 +135,7 @@ const struct Curl_handler Curl_handler_rtmpe = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
@@ -157,6 +160,7 @@ const struct Curl_handler Curl_handler_rtmpte = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
@@ -181,6 +185,7 @@ const struct Curl_handler Curl_handler_rtmps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -205,6 +210,7 @@ const struct Curl_handler Curl_handler_rtmpts = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h index 1d0a3965a4..bc863fbb97 100644 --- a/libs/libcurl/src/curl_setup.h +++ b/libs/libcurl/src/curl_setup.h @@ -31,13 +31,6 @@ /* Tell "curl/curl.h" not to include "curl/mprintf.h" */
#define CURL_SKIP_INCLUDE_MPRINTF
-/* FIXME: Delete this once the warnings have been fixed. */
-#if !defined(CURL_WARN_SIGN_CONVERSION)
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic ignored "-Wsign-conversion"
-#endif
-#endif
-
/* Set default _WIN32_WINNT */
#ifdef __MINGW32__
#include <_mingw.h>
@@ -85,13 +78,17 @@ #endif
#endif
-/*
- * Disable Visual Studio warnings:
- * 4127 "conditional expression is constant"
- */
#ifdef _MSC_VER
+/* Disable Visual Studio warnings: 4127 "conditional expression is constant" */
#pragma warning(disable:4127)
+/* Avoid VS2005 and upper complaining about portable C functions. */
+#ifndef _CRT_NONSTDC_NO_DEPRECATE
+#define _CRT_NONSTDC_NO_DEPRECATE /* for strdup(), write(), etc. */
+#endif
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE /* for fopen(), getenv(), etc. */
#endif
+#endif /* _MSC_VER */
#ifdef _WIN32
/*
@@ -100,16 +97,26 @@ * Make sure to define this macro before including any Windows headers.
*/
# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOGDI
-# define NOGDI
+# define NOGDI
+# endif
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+ defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_UWP
+# endif
# endif
#endif
/* Compatibility */
-#if defined(ENABLE_IPV6)
-# define USE_IPV6 1
+#ifdef ENABLE_IPV6
+#define USE_IPV6 1
#endif
/*
@@ -123,12 +130,8 @@ #else /* HAVE_CONFIG_H */
-#ifdef _WIN32_WCE
-# include "config-win32ce.h"
-#else
-# ifdef _WIN32
-# include "config-win32.h"
-# endif
+#ifdef _WIN32
+# include "config-win32.h"
#endif
#ifdef macintosh
@@ -139,10 +142,6 @@ # include "config-riscos.h"
#endif
-#ifdef __AMIGA__
-# include "config-amigaos.h"
-#endif
-
#ifdef __OS400__
# include "config-os400.h"
#endif
@@ -151,10 +150,6 @@ # include "config-plan9.h"
#endif
-#ifdef MSDOS
-# include "config-dos.h"
-#endif
-
#endif /* HAVE_CONFIG_H */
/* ================================================================ */
@@ -173,7 +168,7 @@ #ifdef NEED_THREAD_SAFE
# ifndef _THREAD_SAFE
-# define _THREAD_SAFE
+# define _THREAD_SAFE
# endif
#endif
@@ -185,14 +180,14 @@ #ifdef NEED_REENTRANT
# ifndef _REENTRANT
-# define _REENTRANT
+# define _REENTRANT
# endif
#endif
/* Solaris needs this to get a POSIX-conformant getpwuid_r */
#if defined(sun) || defined(__sun)
# ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
+# define _POSIX_PTHREAD_SEMANTICS 1
# endif
#endif
@@ -280,14 +275,6 @@ # define CURL_DISABLE_HTTP_AUTH 1
#endif
-/*
- * ECH requires HTTPSRR.
- */
-
-#if defined(USE_ECH) && !defined(USE_HTTPSRR)
-# define USE_HTTPSRR
-#endif
-
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
@@ -383,17 +370,23 @@ # endif
#endif
+#ifdef USE_ARES
+# ifndef CARES_NO_DEPRECATED
+# define CARES_NO_DEPRECATED /* for ares_getsock() */
+# endif
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && defined(_WIN32)
+# define CARES_STATICLIB /* define it before including ares.h */
+# endif
+#endif
+
#ifdef USE_LWIPSOCK
# include <lwip/init.h>
# include <lwip/sockets.h>
# include <lwip/netdb.h>
#endif
-#ifdef HAVE_EXTRA_STRICMP_H
+#ifdef macintosh
# include <extra/stricmp.h>
-#endif
-
-#ifdef HAVE_EXTRA_STRDUP_H
# include <extra/strdup.h>
#endif
@@ -446,9 +439,9 @@ #include <assert.h>
#ifdef __TANDEM /* for ns*-tandem-nsk systems */
-# if ! defined __LP64
-# include <floss.h> /* FLOSS is only used for 32-bit builds. */
-# endif
+# if ! defined __LP64
+# include <floss.h> /* FLOSS is only used for 32-bit builds. */
+# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
@@ -484,11 +477,19 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode);
#endif
+#ifdef __DJGPP__
+/* Requires DJGPP 2.04 */
+# include <unistd.h>
+# undef lseek
+# define lseek(fdes,offset,whence) llseek(fdes, offset, whence)
+# define LSEEK_ERROR (offset_t)-1
+#endif
+
/*
* Small file (<2Gb) support using Win32 functions.
*/
-#ifdef USE_WIN32_SMALL_FILES
+#if defined(_WIN32) && !defined(USE_WIN32_LARGE_FILES)
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
@@ -508,11 +509,11 @@ #endif
#ifndef struct_stat
-# define struct_stat struct stat
+#define struct_stat struct stat
#endif
#ifndef LSEEK_ERROR
-# define LSEEK_ERROR (off_t)-1
+#define LSEEK_ERROR (off_t)-1
#endif
#ifndef SIZEOF_TIME_T
@@ -583,8 +584,8 @@ # endif
# define CURL_UINT64_SUFFIX CURL_SUFFIX_CURL_OFF_TU
# define CURL_UINT64_C(val) CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX)
-# define FMT_PRId64 CURL_FORMAT_CURL_OFF_T
-# define FMT_PRIu64 CURL_FORMAT_CURL_OFF_TU
+# define FMT_PRId64 CURL_FORMAT_CURL_OFF_T
+# define FMT_PRIu64 CURL_FORMAT_CURL_OFF_TU
#endif
#define FMT_OFF_T CURL_FORMAT_CURL_OFF_T
@@ -683,9 +684,9 @@ /*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
+ * Single-threaded option was last available in VS2005: _MSC_VER <= 1400
*/
-
-#if defined(_MSC_VER) && !defined(_MT)
+#if defined(_MSC_VER) && !defined(_MT) /* available in _MSC_VER <= 1400 */
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
@@ -703,15 +704,15 @@ # define CURLRES_IPV4
#endif
-#ifdef USE_ARES
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+# define CURLRES_ASYNCH
+# define CURLRES_THREADED
+#elif defined(USE_ARES)
# define CURLRES_ASYNCH
# define CURLRES_ARES
/* now undef the stock libc functions just to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
-#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
-# define CURLRES_ASYNCH
-# define CURLRES_THREADED
#else
# define CURLRES_SYNCH
#endif
@@ -728,14 +729,23 @@ #error "libidn2 cannot be enabled with WinIDN or AppleIDN, choose one."
#endif
-#define LIBIDN_REQUIRED_VERSION "0.4.1"
-
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_BEARSSL) || defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
+#if defined(USE_OPENSSL) && defined(USE_WOLFSSL)
+# include <wolfssl/version.h>
+# if LIBWOLFSSL_VERSION_HEX >= 0x05007006
+# ifndef OPENSSL_COEXIST
+# define OPENSSL_COEXIST
+# endif
+# else
+# error "OpenSSL can only coexist with wolfSSL v5.7.6 or upper"
+# endif
+#endif
+
#if defined(USE_WOLFSSL) && defined(USE_GNUTLS)
/* Avoid defining unprefixed wolfSSL SHA macros colliding with nettle ones */
#define NO_OLD_WC_NAMES
@@ -766,10 +776,6 @@ # endif
#endif
-#ifdef CURL_WANTS_CA_BUNDLE_ENV
-#error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
-#endif
-
#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
#define USE_SSH
#endif
@@ -802,7 +808,7 @@ #if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) || \
defined(__IAR_SYSTEMS_ICC__)
# define CURL_NORETURN __attribute__((__noreturn__))
-#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+#elif defined(_MSC_VER)
# define CURL_NORETURN __declspec(noreturn)
#else
# define CURL_NORETURN
@@ -833,7 +839,7 @@ */
#ifndef Curl_nop_stmt
-# define Curl_nop_stmt do { } while(0)
+#define Curl_nop_stmt do { } while(0)
#endif
/*
@@ -872,6 +878,14 @@ #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
+/* Since O_BINARY is used in bitmasks, setting it to zero makes it usable in
+ source code but yet it does not ruin anything */
+#ifdef O_BINARY
+#define CURL_O_BINARY O_BINARY
+#else
+#define CURL_O_BINARY 0
+#endif
+
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
@@ -901,6 +915,8 @@ endings either CRLF or LF so 't' is appropriate. # define CURL_SA_FAMILY_T sa_family_t
# elif defined(HAVE_ADDRESS_FAMILY)
# define CURL_SA_FAMILY_T ADDRESS_FAMILY
+# elif defined(__AMIGA__)
+# define CURL_SA_FAMILY_T unsigned char
# else
/* use a sensible default */
# define CURL_SA_FAMILY_T unsigned short
@@ -917,8 +933,11 @@ endings either CRLF or LF so 't' is appropriate. as their argument */
#define STRCONST(x) x,sizeof(x)-1
-/* Some versions of the Android SDK is missing the declaration */
-#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
+#define CURL_ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+
+/* Some versions of the Android NDK is missing the declaration */
+#if defined(HAVE_GETPWUID_R) && \
+ defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
struct passwd;
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
size_t buflen, struct passwd **result);
@@ -930,8 +949,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define UNITTEST static
#endif
-/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
-#if defined(USE_NGHTTP2)
+#ifdef USE_NGHTTP2
#define USE_HTTP2
#endif
@@ -940,7 +958,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, defined(USE_QUICHE) || defined(USE_MSH3)
#ifdef CURL_WITH_MULTI_SSL
-#error "Multi-SSL combined with QUIC is not supported"
+#error "MultiSSL combined with QUIC is not supported"
#endif
#define USE_HTTP3
@@ -960,39 +978,45 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, # define UNIX_PATH_MAX 108
/* !checksrc! disable TYPEDEFSTRUCT 1 */
typedef struct sockaddr_un {
- ADDRESS_FAMILY sun_family;
+ CURL_SA_FAMILY_T sun_family;
char sun_path[UNIX_PATH_MAX];
} SOCKADDR_UN, *PSOCKADDR_UN;
# define WIN32_SOCKADDR_UN
# endif
#endif
+#ifdef USE_OPENSSL
/* OpenSSLv3 marks DES, MD5 and ENGINE functions deprecated but we have no
replacements (yet) so tell the compiler to not warn for them. */
-#ifdef USE_OPENSSL
-#define OPENSSL_SUPPRESS_DEPRECATED
+# define OPENSSL_SUPPRESS_DEPRECATED
+# ifdef _WIN32
+/* Silence LibreSSL warnings about wincrypt.h collision. Works in 3.8.2+ */
+# ifndef LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING
+# define LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING
+# endif
+# endif
#endif
-#if defined(inline)
- /* 'inline' is defined as macro and assumed to be correct */
- /* No need for 'inline' replacement */
+#if defined(CURL_INLINE)
+/* 'CURL_INLINE' defined, use as-is */
+#elif defined(inline)
+# define CURL_INLINE inline /* 'inline' defined, assumed correct */
#elif defined(__cplusplus)
- /* The code is compiled with C++ compiler.
- C++ always supports 'inline'. */
- /* No need for 'inline' replacement */
+/* The code is compiled with C++ compiler.
+ C++ always supports 'inline'. */
+# define CURL_INLINE inline /* 'inline' keyword supported */
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
- /* C99 (and later) supports 'inline' keyword */
- /* No need for 'inline' replacement */
+/* C99 (and later) supports 'inline' keyword */
+# define CURL_INLINE inline /* 'inline' keyword supported */
#elif defined(__GNUC__) && __GNUC__ >= 3
- /* GCC supports '__inline__' as an extension */
-# define inline __inline__
-#elif defined(_MSC_VER) && _MSC_VER >= 1400
- /* MSC supports '__inline' from VS 2005 (or even earlier) */
-# define inline __inline
+/* GCC supports '__inline__' as an extension */
+# define CURL_INLINE __inline__
+#elif defined(_MSC_VER)
+# define CURL_INLINE __inline
#else
- /* Probably 'inline' is not supported by compiler.
- Define to the empty string to be on the safe side. */
-# define inline /* empty */
+/* Probably 'inline' is not supported by compiler.
+ Define to the empty string to be on the safe side. */
+# define CURL_INLINE /* empty */
#endif
#endif /* HEADER_CURL_SETUP_H */
diff --git a/libs/libcurl/src/curl_setup_once.h b/libs/libcurl/src/curl_setup_once.h index 2c580fc444..efd025730a 100644 --- a/libs/libcurl/src/curl_setup_once.h +++ b/libs/libcurl/src/curl_setup_once.h @@ -24,7 +24,6 @@ *
***************************************************************************/
-
/*
* Inclusion of common header files.
*/
@@ -40,14 +39,6 @@ #include <sys/types.h>
#endif
-#ifdef NEED_MALLOC_H
-#include <malloc.h>
-#endif
-
-#ifdef NEED_MEMORY_H
-#include <memory.h>
-#endif
-
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -56,8 +47,11 @@ #include <sys/time.h>
#endif
-#ifdef _WIN32
+#ifdef HAVE_IO_H
#include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -111,8 +105,8 @@ #ifndef HAVE_STRUCT_TIMEVAL
struct timeval {
- long tv_sec;
- long tv_usec;
+ long tv_sec;
+ long tv_usec;
};
#endif
@@ -195,7 +189,7 @@ struct timeval { # define sclose(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
# define sclose(x) CloseSocket((x))
-#elif defined(HAVE_CLOSE_S)
+#elif defined(MSDOS) /* Watt-32 */
# define sclose(x) close_s((x))
#elif defined(USE_LWIPSOCK)
# define sclose(x) lwip_close((x))
@@ -233,8 +227,8 @@ struct timeval { #ifndef HAVE_BOOL_T
typedef enum {
- bool_false = 0,
- bool_true = 1
+ bool_false = 0,
+ bool_true = 1
} bool;
/*
@@ -397,7 +391,7 @@ typedef unsigned int bit; #ifdef __VMS
#define argv_item_t __char_ptr32
#elif defined(_UNICODE)
-#define argv_item_t wchar_t *
+#define argv_item_t wchar_t *
#else
#define argv_item_t char *
#endif
diff --git a/libs/libcurl/src/curl_sha256.h b/libs/libcurl/src/curl_sha256.h index 8e93245f39..2ab36fcd5e 100644 --- a/libs/libcurl/src/curl_sha256.h +++ b/libs/libcurl/src/curl_sha256.h @@ -26,7 +26,7 @@ ***************************************************************************/
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
- || defined(USE_LIBSSH2)
+ || defined(USE_LIBSSH2) || defined(USE_SSL)
#include <curl/curl.h>
#include "curl_hmac.h"
diff --git a/libs/libcurl/src/curl_sha512_256.c b/libs/libcurl/src/curl_sha512_256.c index 4333cfb146..75708ba914 100644 --- a/libs/libcurl/src/curl_sha512_256.c +++ b/libs/libcurl/src/curl_sha512_256.c @@ -283,28 +283,26 @@ Curl_sha512_256_finish(unsigned char *digest, #ifdef __GNUC__
# if defined(__has_attribute) && defined(__STDC_VERSION__)
# if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
-# define MHDX_INLINE inline __attribute__((always_inline))
+# define CURL_FORCEINLINE CURL_INLINE __attribute__((always_inline))
# endif
# endif
#endif
-#if !defined(MHDX_INLINE) && \
+#if !defined(CURL_FORCEINLINE) && \
defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
-# if _MSC_VER >= 1400
-# define MHDX_INLINE __forceinline
-# endif
+# define CURL_FORCEINLINE __forceinline
#endif
-#if !defined(MHDX_INLINE)
- /* Assume that 'inline' keyword works or the
+#if !defined(CURL_FORCEINLINE)
+ /* Assume that 'CURL_INLINE' keyword works or the
* macro was already defined correctly. */
-# define MHDX_INLINE inline
+# define CURL_FORCEINLINE CURL_INLINE
#endif
/* Bits manipulation macros and functions.
Can be moved to other headers to reuse. */
-#define MHDX_GET_64BIT_BE(ptr) \
+#define CURL_GET_64BIT_BE(ptr) \
( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
@@ -314,7 +312,7 @@ Curl_sha512_256_finish(unsigned char *digest, ((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
(curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
-#define MHDX_PUT_64BIT_BE(ptr,val) do { \
+#define CURL_PUT_64BIT_BE(ptr,val) do { \
((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
@@ -328,8 +326,8 @@ Curl_sha512_256_finish(unsigned char *digest, /* Defined as a function. The macro version may duplicate the binary code
* size as each argument is used twice, so if any calculation is used
* as an argument, the calculation could be done twice. */
-static MHDX_INLINE curl_uint64_t
-MHDx_rotr64(curl_uint64_t value, unsigned int bits)
+static CURL_FORCEINLINE curl_uint64_t
+Curl_rotr64(curl_uint64_t value, unsigned int bits)
{
bits %= 64;
if(0 == bits)
@@ -388,7 +386,7 @@ MHDx_rotr64(curl_uint64_t value, unsigned int bits) /**
* SHA-512/256 calculation context
*/
-struct mhdx_sha512_256ctx
+struct Curl_sha512_256ctx
{
/**
* Intermediate hash value. The variable is properly aligned. Smart
@@ -416,7 +414,7 @@ struct mhdx_sha512_256ctx /**
* Context type used for SHA-512/256 calculations
*/
-typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
+typedef struct Curl_sha512_256ctx Curl_sha512_256_ctx;
/**
@@ -426,9 +424,9 @@ typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx; * @return always CURLE_OK
*/
static CURLcode
-MHDx_sha512_256_init(void *context)
+Curl_sha512_256_init(void *context)
{
- struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
+ struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
@@ -462,7 +460,7 @@ MHDx_sha512_256_init(void *context) * @param data the data buffer with #CURL_SHA512_256_BLOCK_SIZE bytes block
*/
static void
-MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
+Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
const void *data)
{
/* Working variables,
@@ -488,13 +486,13 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], /* Four 'Sigma' macro functions.
See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
#define SIG0(x) \
- ( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
+ ( Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39) )
#define SIG1(x) \
- ( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
+ ( Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41) )
#define sig0(x) \
- ( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
+ ( Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7) )
#define sig1(x) \
- ( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
+ ( Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6) )
if(1) {
unsigned int t;
@@ -577,7 +575,7 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], Input data must be read in big-endian bytes order,
see FIPS PUB 180-4 section 3.1.2. */
#define SHA512_GET_W_FROM_DATA(buf,t) \
- MHDX_GET_64BIT_BE( \
+ CURL_GET_64BIT_BE( \
((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
/* During first 16 steps, before making any calculation on each step, the
@@ -628,12 +626,12 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], * @return always CURLE_OK
*/
static CURLcode
-MHDx_sha512_256_update(void *context,
+Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
unsigned int bytes_have; /**< Number of bytes in the context buffer */
- struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
+ struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
@@ -661,7 +659,7 @@ MHDx_sha512_256_update(void *context, bytes_left);
data += bytes_left;
length -= bytes_left;
- MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+ Curl_sha512_256_transform(ctx->H, ctx->buffer);
bytes_have = 0;
}
}
@@ -669,7 +667,7 @@ MHDx_sha512_256_update(void *context, while(CURL_SHA512_256_BLOCK_SIZE <= length) {
/* Process any full blocks of new data directly,
without copying to the buffer. */
- MHDx_sha512_256_transform(ctx->H, data);
+ Curl_sha512_256_transform(ctx->H, data);
data += CURL_SHA512_256_BLOCK_SIZE;
length -= CURL_SHA512_256_BLOCK_SIZE;
}
@@ -705,10 +703,10 @@ MHDx_sha512_256_update(void *context, * @return always CURLE_OK
*/
static CURLcode
-MHDx_sha512_256_finish(unsigned char *digest,
+Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
- struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
+ struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
curl_uint64_t num_bits; /**< Number of processed bits */
unsigned int bytes_have; /**< Number of bytes in the context buffer */
/* the void pointer here is required to mute Intel compiler warning */
@@ -742,7 +740,7 @@ MHDx_sha512_256_finish(unsigned char *digest, memset(((unsigned char *) ctx_buf) + bytes_have, 0,
CURL_SHA512_256_BLOCK_SIZE - bytes_have);
/* Process the full block. */
- MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+ Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Start the new block. */
bytes_have = 0;
}
@@ -754,37 +752,32 @@ MHDx_sha512_256_finish(unsigned char *digest, part of number of bits as big-endian values.
See FIPS PUB 180-4 section 5.1.2. */
/* Note: the target location is predefined and buffer is always aligned */
- MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD, \
ctx->count_bits_hi);
- MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD \
+ SHA512_256_BYTES_IN_WORD, \
num_bits);
/* Process the full final block. */
- MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+ Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Put in BE mode the leftmost part of the hash as the final digest.
See FIPS PUB 180-4 section 6.7. */
- MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
- MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
- MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
- MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
+ CURL_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
+ CURL_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
+ CURL_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
+ CURL_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
/* Erase potentially sensitive data. */
- memset(ctx, 0, sizeof(struct mhdx_sha512_256ctx));
+ memset(ctx, 0, sizeof(struct Curl_sha512_256ctx));
return CURLE_OK;
}
-/* Map to the local implementation */
-#define Curl_sha512_256_init MHDx_sha512_256_init
-#define Curl_sha512_256_update MHDx_sha512_256_update
-#define Curl_sha512_256_finish MHDx_sha512_256_finish
-
#endif /* Local SHA-512/256 code */
diff --git a/libs/libcurl/src/curl_sspi.h b/libs/libcurl/src/curl_sspi.h index 9c7a2d4c04..e5a843fbd2 100644 --- a/libs/libcurl/src/curl_sspi.h +++ b/libs/libcurl/src/curl_sspi.h @@ -81,27 +81,27 @@ extern PSecurityFunctionTable Curl_pSecFn; #endif
#ifndef SEC_I_SIGNATURE_NEEDED
-# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
+#define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
#endif
#ifndef CRYPT_E_REVOKED
-# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
+#define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_DLL
-# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
+#define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_CHECK
-# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
+#define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
#endif
#ifndef CRYPT_E_REVOCATION_OFFLINE
-# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
+#define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
#endif
#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
-# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
+#define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
#endif
#ifdef UNICODE
diff --git a/libs/libcurl/src/curl_trc.c b/libs/libcurl/src/curl_trc.c index 9075de25fd..2e3c42ed87 100644 --- a/libs/libcurl/src/curl_trc.c +++ b/libs/libcurl/src/curl_trc.c @@ -53,10 +53,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size)
{
@@ -239,6 +235,24 @@ void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...) }
#endif /* !CURL_DISABLE_SMTP */
+#ifdef USE_SSL
+struct curl_trc_feat Curl_trc_feat_ssls = {
+ "SSLS",
+ CURL_LOG_LVL_NONE,
+};
+
+void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
+{
+ DEBUGASSERT(!strchr(fmt, '\n'));
+ if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) {
+ va_list ap;
+ va_start(ap, fmt);
+ trc_infof(data, &Curl_trc_feat_ssls, fmt, ap);
+ va_end(ap);
+ }
+}
+#endif /* USE_SSL */
+
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
struct curl_trc_feat Curl_trc_feat_ws = {
"WS",
@@ -279,6 +293,9 @@ static struct trc_feat_def trc_feats[] = { #ifndef CURL_DISABLE_SMTP
{ &Curl_trc_feat_smtp, TRC_CT_PROTOCOL },
#endif
+#ifdef USE_SSL
+ { &Curl_trc_feat_ssls, TRC_CT_NETWORK },
+#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
{ &Curl_trc_feat_ws, TRC_CT_PROTOCOL },
#endif
@@ -319,7 +336,7 @@ static struct trc_cft_def trc_cfts[] = { #ifdef USE_HTTP3
{ &Curl_cft_http3, TRC_CT_PROTOCOL },
#endif
-#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+#if !defined(CURL_DISABLE_HTTP)
{ &Curl_cft_http_connect, TRC_CT_PROTOCOL },
#endif
};
@@ -328,13 +345,13 @@ static void trc_apply_level_by_name(const char * const token, int lvl) {
size_t i;
- for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) {
if(strcasecompare(token, trc_cfts[i].cft->name)) {
trc_cfts[i].cft->log_level = lvl;
break;
}
}
- for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) {
if(strcasecompare(token, trc_feats[i].feat->name)) {
trc_feats[i].feat->log_level = lvl;
break;
@@ -346,11 +363,11 @@ static void trc_apply_level_by_category(int category, int lvl) {
size_t i;
- for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) {
if(!category || (trc_cfts[i].category & category))
trc_cfts[i].cft->log_level = lvl;
}
- for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) {
if(!category || (trc_feats[i].category & category))
trc_feats[i].feat->log_level = lvl;
}
@@ -427,4 +444,53 @@ CURLcode Curl_trc_init(void) return CURLE_OK;
}
+void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+
+void Curl_trc_cf_infof(struct Curl_easy *data,
+ struct Curl_cfilter *cf,
+ const char *fmt, ...)
+{
+ (void)data; (void)cf; (void)fmt;
+}
+
+struct curl_trc_feat;
+
+void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+
+void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+
+#ifndef CURL_DISABLE_FTP
+void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+#endif
+#ifndef CURL_DISABLE_SMTP
+void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+#endif
+#if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP)
+void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+#endif
+
+void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data;
+ (void)fmt;
+}
+
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
diff --git a/libs/libcurl/src/curl_trc.h b/libs/libcurl/src/curl_trc.h index bcf598d8db..8156165776 100644 --- a/libs/libcurl/src/curl_trc.h +++ b/libs/libcurl/src/curl_trc.h @@ -70,7 +70,45 @@ void Curl_failf(struct Curl_easy *data, #define CURL_HAVE_C99
#endif
-#ifdef CURL_HAVE_C99
+/**
+ * Output an informational message when transfer's verbose logging is enabled.
+ */
+void Curl_infof(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+
+/**
+ * Output an informational message when both transfer's verbose logging
+ * and connection filters verbose logging are enabled.
+ */
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
+ const char *fmt, ...) CURL_PRINTF(3, 4);
+void Curl_trc_write(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+void Curl_trc_read(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+
+#ifndef CURL_DISABLE_FTP
+extern struct curl_trc_feat Curl_trc_feat_ftp;
+void Curl_trc_ftp(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+#endif
+#ifndef CURL_DISABLE_SMTP
+extern struct curl_trc_feat Curl_trc_feat_smtp;
+void Curl_trc_smtp(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+#endif
+#ifdef USE_SSL
+extern struct curl_trc_feat Curl_trc_feat_ssls;
+void Curl_trc_ssls(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+#endif
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+extern struct curl_trc_feat Curl_trc_feat_ws;
+void Curl_trc_ws(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+#endif
+
+#if defined(CURL_HAVE_C99) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
@@ -94,6 +132,11 @@ void Curl_failf(struct Curl_easy *data, do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) \
Curl_trc_smtp(data, __VA_ARGS__); } while(0)
#endif /* !CURL_DISABLE_SMTP */
+#ifdef USE_SSL
+#define CURL_TRC_SSLS(data, ...) \
+ do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) \
+ Curl_trc_ssls(data, __VA_ARGS__); } while(0)
+#endif /* USE_SSL */
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#define CURL_TRC_WS(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \
@@ -113,6 +156,9 @@ void Curl_failf(struct Curl_easy *data, #ifndef CURL_DISABLE_SMTP
#define CURL_TRC_SMTP Curl_trc_smtp
#endif
+#ifdef USE_SSL
+#define CURL_TRC_SSLS Curl_trc_ssls
+#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#define CURL_TRC_WS Curl_trc_ws
#endif
@@ -140,40 +186,6 @@ extern struct curl_trc_feat Curl_trc_feat_write; (Curl_trc_is_verbose(data) && \
(ft)->log_level >= CURL_LOG_LVL_INFO)
-/**
- * Output an informational message when transfer's verbose logging is enabled.
- */
-void Curl_infof(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-
-/**
- * Output an informational message when both transfer's verbose logging
- * and connection filters verbose logging are enabled.
- */
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
- const char *fmt, ...) CURL_PRINTF(3, 4);
-void Curl_trc_write(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-void Curl_trc_read(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-
-#ifndef CURL_DISABLE_FTP
-extern struct curl_trc_feat Curl_trc_feat_ftp;
-void Curl_trc_ftp(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-#endif
-#ifndef CURL_DISABLE_SMTP
-extern struct curl_trc_feat Curl_trc_feat_smtp;
-void Curl_trc_smtp(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-#endif
-#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
-extern struct curl_trc_feat Curl_trc_feat_ws;
-void Curl_trc_ws(struct Curl_easy *data,
- const char *fmt, ...) CURL_PRINTF(2, 3);
-#endif
-
-
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
@@ -181,49 +193,6 @@ void Curl_trc_ws(struct Curl_easy *data, #define Curl_trc_cf_is_verbose(x,y) (FALSE)
#define Curl_trc_ft_is_verbose(x,y) (FALSE)
-static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-
-static void Curl_trc_cf_infof(struct Curl_easy *data,
- struct Curl_cfilter *cf,
- const char *fmt, ...)
-{
- (void)data; (void)cf; (void)fmt;
-}
-
-struct curl_trc_feat;
-
-static void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-
-static void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-
-#ifndef CURL_DISABLE_FTP
-static void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-#endif
-#ifndef CURL_DISABLE_SMTP
-static void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-#endif
-#if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP)
-static void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
-{
- (void)data; (void)fmt;
-}
-#endif
-
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */
diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c index 5bf76332af..1e4a05969f 100644 --- a/libs/libcurl/src/dict.c +++ b/libs/libcurl/src/dict.c @@ -93,6 +93,7 @@ const struct Curl_handler Curl_handler_dict = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
CURLPROTO_DICT, /* family */
diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index 725361ace0..dfa7f27e53 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -410,12 +410,6 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, struct doh_probes *dohp;
struct connectdata *conn = data->conn;
size_t i;
-#ifdef USE_HTTPSRR
- /* for now, this is only used when ECH is enabled */
-# ifdef USE_ECH
- char *qname = NULL;
-# endif
-#endif
*waitp = FALSE;
(void)hostname;
(void)port;
@@ -462,34 +456,23 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, #endif
#ifdef USE_HTTPSRR
- /*
- * TODO: Figure out the conditions under which we want to make
- * a request for an HTTPS RR when we are not doing ECH. For now,
- * making this request breaks a bunch of DoH tests, e.g. test2100,
- * where the additional request does not match the pre-cooked data
- * files, so there is a bit of work attached to making the request
- * in a non-ECH use-case. For the present, we will only make the
- * request when ECH is enabled in the build and is being used for
- * the curl operation.
- */
-# ifdef USE_ECH
- if(data->set.tls_ech & CURLECH_ENABLE
- || data->set.tls_ech & CURLECH_HARD) {
- if(port == 443)
- qname = strdup(hostname);
- else
+ if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ /* Only use HTTPS RR for HTTP(S) transfers */
+ char *qname = NULL;
+ if(port != PORT_HTTPS) {
qname = aprintf("_%d._https.%s", port, hostname);
- if(!qname)
- goto error;
+ if(!qname)
+ goto error;
+ }
result = doh_run_probe(data, &dohp->probe[DOH_SLOT_HTTPS_RR],
- DNS_TYPE_HTTPS, qname, data->set.str[STRING_DOH],
+ DNS_TYPE_HTTPS,
+ qname ? qname : hostname, data->set.str[STRING_DOH],
data->multi, dohp->req_hds);
- Curl_safefree(qname);
+ free(qname);
if(result)
goto error;
dohp->pending++;
}
-# endif
#endif
*waitp = TRUE; /* this never returns synchronously */
return NULL;
@@ -961,11 +944,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, addr = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
-#ifdef __MINGW32__
- addr->sin_family = (short)addrtype;
-#else
- addr->sin_family = addrtype;
-#endif
+ addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
addr->sin_port = htons((unsigned short)port);
break;
@@ -974,11 +953,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, addr6 = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
-#ifdef __MINGW32__
- addr6->sin6_family = (short)addrtype;
-#else
- addr6->sin6_family = addrtype;
-#endif
+ addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
@@ -1089,62 +1064,6 @@ static CURLcode doh_decode_rdata_name(unsigned char **buf, size_t *remaining, return CURLE_OK;
}
-static CURLcode doh_decode_rdata_alpn(unsigned char *rrval, size_t len,
- char **alpns)
-{
- /*
- * spec here is as per draft-ietf-dnsop-svcb-https, section-7.1.1
- * encoding is catenated list of strings each preceded by a one
- * octet length
- * output is comma-sep list of the strings
- * implementations may or may not handle quoting of comma within
- * string values, so we might see a comma within the wire format
- * version of a string, in which case we will precede that by a
- * backslash - same goes for a backslash character, and of course
- * we need to use two backslashes in strings when we mean one;-)
- */
- int remaining = (int) len;
- char *oval;
- size_t i;
- unsigned char *cp = rrval;
- struct dynbuf dval;
-
- if(!alpns)
- return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
- remaining = (int)len;
- cp = rrval;
- while(remaining > 0) {
- size_t tlen = (size_t) *cp++;
-
- /* if not 1st time, add comma */
- if(remaining != (int)len && Curl_dyn_addn(&dval, ",", 1))
- goto err;
- remaining--;
- if(tlen > (size_t)remaining)
- goto err;
- /* add escape char if needed, clunky but easier to read */
- for(i = 0; i != tlen; i++) {
- if('\\' == *cp || ',' == *cp) {
- if(Curl_dyn_addn(&dval, "\\", 1))
- goto err;
- }
- if(Curl_dyn_addn(&dval, cp++, 1))
- goto err;
- }
- remaining -= (int)tlen;
- }
- /* this string is always null terminated */
- oval = Curl_dyn_ptr(&dval);
- if(!oval)
- goto err;
- *alpns = oval;
- return CURLE_OK;
-err:
- Curl_dyn_free(&dval);
- return CURLE_BAD_CONTENT_ENCODING;
-}
-
#ifdef DEBUGBUILD
static CURLcode doh_test_alpn_escapes(void)
{
@@ -1156,24 +1075,20 @@ static CURLcode doh_test_alpn_escapes(void) 0x68, 0x32 /* value "h2" */
};
size_t example_len = sizeof(example);
- char *aval = NULL;
- static const char *expected = "f\\\\oo\\,bar,h2";
+ unsigned char aval[MAX_HTTPSRR_ALPNS] = { 0 };
+ static const char expected[2] = { ALPN_h2, ALPN_none };
- if(doh_decode_rdata_alpn(example, example_len, &aval) != CURLE_OK)
+ if(Curl_httpsrr_decode_alpn(example, example_len, aval) != CURLE_OK)
return CURLE_BAD_CONTENT_ENCODING;
- if(strlen(aval) != strlen(expected))
- return CURLE_BAD_CONTENT_ENCODING;
- if(memcmp(aval, expected, strlen(aval)))
+ if(memcmp(aval, expected, sizeof(expected)))
return CURLE_BAD_CONTENT_ENCODING;
return CURLE_OK;
}
#endif
-static CURLcode doh_resp_decode_httpsrr(unsigned char *rrval, size_t len,
+static CURLcode doh_resp_decode_httpsrr(unsigned char *cp, size_t len,
struct Curl_https_rrinfo **hrr)
{
- size_t remaining = len;
- unsigned char *cp = rrval;
uint16_t pcode = 0, plen = 0;
struct Curl_https_rrinfo *lhrr = NULL;
char *dnsname = NULL;
@@ -1183,73 +1098,73 @@ static CURLcode doh_resp_decode_httpsrr(unsigned char *rrval, size_t len, if(doh_test_alpn_escapes() != CURLE_OK)
return CURLE_OUT_OF_MEMORY;
#endif
+ if(len <= 2)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
lhrr = calloc(1, sizeof(struct Curl_https_rrinfo));
if(!lhrr)
return CURLE_OUT_OF_MEMORY;
- lhrr->val = Curl_memdup(rrval, len);
- if(!lhrr->val)
- goto err;
- lhrr->len = len;
- if(remaining <= 2)
- goto err;
- lhrr->priority = (uint16_t)((cp[0] << 8) + cp[1]);
+ lhrr->priority = doh_get16bit(cp, 0);
cp += 2;
- remaining -= (uint16_t)2;
- if(doh_decode_rdata_name(&cp, &remaining, &dnsname) != CURLE_OK)
+ len -= 2;
+ if(doh_decode_rdata_name(&cp, &len, &dnsname) != CURLE_OK)
goto err;
lhrr->target = dnsname;
- while(remaining >= 4) {
- pcode = (uint16_t)((*cp << 8) + (*(cp + 1)));
- cp += 2;
- plen = (uint16_t)((*cp << 8) + (*(cp + 1)));
- cp += 2;
- remaining -= 4;
- if(pcode == HTTPS_RR_CODE_ALPN) {
- if(doh_decode_rdata_alpn(cp, plen, &lhrr->alpns) != CURLE_OK)
+ lhrr->port = -1; /* until set */
+ while(len >= 4) {
+ pcode = doh_get16bit(cp, 0);
+ plen = doh_get16bit(cp, 2);
+ cp += 4;
+ len -= 4;
+ switch(pcode) {
+ case HTTPS_RR_CODE_ALPN:
+ if(Curl_httpsrr_decode_alpn(cp, plen, lhrr->alpns) != CURLE_OK)
goto err;
- }
- if(pcode == HTTPS_RR_CODE_NO_DEF_ALPN)
+ break;
+ case HTTPS_RR_CODE_NO_DEF_ALPN:
lhrr->no_def_alpn = TRUE;
- else if(pcode == HTTPS_RR_CODE_IPV4) {
+ break;
+ case HTTPS_RR_CODE_IPV4:
if(!plen)
goto err;
lhrr->ipv4hints = Curl_memdup(cp, plen);
if(!lhrr->ipv4hints)
goto err;
lhrr->ipv4hints_len = (size_t)plen;
- }
- else if(pcode == HTTPS_RR_CODE_ECH) {
+ break;
+ case HTTPS_RR_CODE_ECH:
if(!plen)
goto err;
lhrr->echconfiglist = Curl_memdup(cp, plen);
if(!lhrr->echconfiglist)
goto err;
lhrr->echconfiglist_len = (size_t)plen;
- }
- else if(pcode == HTTPS_RR_CODE_IPV6) {
+ break;
+ case HTTPS_RR_CODE_IPV6:
if(!plen)
goto err;
lhrr->ipv6hints = Curl_memdup(cp, plen);
if(!lhrr->ipv6hints)
goto err;
lhrr->ipv6hints_len = (size_t)plen;
+ break;
+ case HTTPS_RR_CODE_PORT:
+ lhrr->port = doh_get16bit(cp, 0);
+ break;
+ default:
+ break;
}
- if(plen > 0 && plen <= remaining) {
+ if(plen > 0 && plen <= len) {
cp += plen;
- remaining -= plen;
+ len -= plen;
}
}
- DEBUGASSERT(!remaining);
+ DEBUGASSERT(!len);
*hrr = lhrr;
return CURLE_OK;
err:
- if(lhrr) {
- Curl_safefree(lhrr->target);
- Curl_safefree(lhrr->echconfiglist);
- Curl_safefree(lhrr->val);
- Curl_safefree(lhrr->alpns);
- Curl_safefree(lhrr);
- }
+ Curl_safefree(lhrr->target);
+ Curl_safefree(lhrr->echconfiglist);
+ Curl_safefree(lhrr);
return CURLE_OUT_OF_MEMORY;
}
@@ -1260,8 +1175,9 @@ static void doh_print_httpsrr(struct Curl_easy *data, DEBUGASSERT(hrr);
infof(data, "HTTPS RR: priority %d, target: %s",
hrr->priority, hrr->target);
- if(hrr->alpns)
- infof(data, "HTTPS RR: alpns %s", hrr->alpns);
+ if(hrr->alpns[0] != ALPN_none)
+ infof(data, "HTTPS RR: alpns %u %u %u %u",
+ hrr->alpns[0], hrr->alpns[1], hrr->alpns[2], hrr->alpns[3]);
else
infof(data, "HTTPS RR: no alpns");
if(hrr->no_def_alpn)
diff --git a/libs/libcurl/src/doh.h b/libs/libcurl/src/doh.h index cc0b3dd3ec..69c98d5883 100644 --- a/libs/libcurl/src/doh.h +++ b/libs/libcurl/src/doh.h @@ -28,6 +28,7 @@ #include "curl_addrinfo.h"
#ifdef USE_HTTPSRR
# include <stdint.h>
+# include "httpsrr.h"
#endif
#ifndef CURL_DISABLE_DOH
@@ -124,19 +125,6 @@ struct dohaddr { #ifdef USE_HTTPSRR
/*
- * These are the code points for DNS wire format SvcParams as
- * per draft-ietf-dnsop-svcb-https
- * Not all are supported now, and even those that are may need
- * more work in future to fully support the spec.
- */
-#define HTTPS_RR_CODE_ALPN 0x01
-#define HTTPS_RR_CODE_NO_DEF_ALPN 0x02
-#define HTTPS_RR_CODE_PORT 0x03
-#define HTTPS_RR_CODE_IPV4 0x04
-#define HTTPS_RR_CODE_ECH 0x05
-#define HTTPS_RR_CODE_IPV6 0x06
-
-/*
* These may need escaping when found within an ALPN string
* value.
*/
diff --git a/libs/libcurl/src/dynbuf.c b/libs/libcurl/src/dynbuf.c index f50fb055c1..2b65b76336 100644 --- a/libs/libcurl/src/dynbuf.c +++ b/libs/libcurl/src/dynbuf.c @@ -244,6 +244,18 @@ char *Curl_dyn_ptr(const struct dynbuf *s) return s->bufr;
}
+char *Curl_dyn_take(struct dynbuf *s, size_t *plen)
+{
+ char *ptr = s->bufr;
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ *plen = s->leng;
+ s->bufr = NULL;
+ s->leng = 0;
+ s->allc = 0;
+ return ptr;
+}
+
/*
* Returns an unsigned pointer to the buffer.
*/
diff --git a/libs/libcurl/src/dynbuf.h b/libs/libcurl/src/dynbuf.h index 2fd7d7e0ae..fc3247927a 100644 --- a/libs/libcurl/src/dynbuf.h +++ b/libs/libcurl/src/dynbuf.h @@ -39,6 +39,7 @@ #define Curl_dyn_uptr(a) curlx_dyn_uptr(a)
#define Curl_dyn_len(a) curlx_dyn_len(a)
#define Curl_dyn_reset(a) curlx_dyn_reset(a)
+#define Curl_dyn_take(a,b) curlx_dyn_take(a,b)
#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
#define curlx_dynbuf dynbuf /* for the struct name */
@@ -75,6 +76,10 @@ size_t Curl_dyn_len(const struct dynbuf *s); /* The implementation of this function exists in mprintf.c */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
+/* Take the buffer out of the dynbuf. Caller has ownership and
+ * dynbuf resets to initial state. */
+char *Curl_dyn_take(struct dynbuf *s, size_t *plen);
+
/* Dynamic buffer max sizes */
#define DYN_DOH_RESPONSE 3000
#define DYN_DOH_CNAME 256
diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 54269e34d9..55fe1adb7d 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -48,6 +48,7 @@ #include <curl/curl.h>
#include "transfer.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
@@ -761,12 +762,25 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) return CURLE_FAILED_INIT;
}
+ /* if the handle has a connection still attached (it is/was a connect-only
+ handle) then disconnect before performing */
+ if(data->conn) {
+ struct connectdata *c;
+ curl_socket_t s;
+ Curl_detach_connection(data);
+ s = Curl_getconnectinfo(data, &c);
+ if((s != CURL_SOCKET_BAD) && c) {
+ Curl_cpool_disconnect(data, c, TRUE);
+ }
+ DEBUGASSERT(!data->conn);
+ }
+
if(data->multi_easy)
multi = data->multi_easy;
else {
- /* this multi handle will only ever have a single easy handled attached
- to it, so make it use minimal hashes */
- multi = Curl_multi_handle(1, 3, 7);
+ /* this multi handle will only ever have a single easy handle attached to
+ it, so make it use minimal hash sizes */
+ multi = Curl_multi_handle(1, 3, 7, 3);
if(!multi)
return CURLE_OUT_OF_MEMORY;
}
@@ -1336,3 +1350,41 @@ CURLcode curl_easy_upkeep(CURL *d) /* Use the common function to keep connections alive. */
return Curl_cpool_upkeep(data);
}
+
+CURLcode curl_easy_ssls_import(CURL *d, const char *session_key,
+ const unsigned char *shmac, size_t shmac_len,
+ const unsigned char *sdata, size_t sdata_len)
+{
+#ifdef USE_SSLS_EXPORT
+ struct Curl_easy *data = d;
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return Curl_ssl_session_import(data, session_key,
+ shmac, shmac_len, sdata, sdata_len);
+#else
+ (void)d;
+ (void)session_key;
+ (void)shmac;
+ (void)shmac_len;
+ (void)sdata;
+ (void)sdata_len;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode curl_easy_ssls_export(CURL *d,
+ curl_ssls_export_cb *export_fn,
+ void *userptr)
+{
+#ifdef USE_SSLS_EXPORT
+ struct Curl_easy *data = d;
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return Curl_ssl_session_export(data, export_fn, userptr);
+#else
+ (void)d;
+ (void)export_fn;
+ (void)userptr;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
diff --git a/libs/libcurl/src/easy_lock.h b/libs/libcurl/src/easy_lock.h index 52f63dd874..3e3fc60d85 100644 --- a/libs/libcurl/src/easy_lock.h +++ b/libs/libcurl/src/easy_lock.h @@ -69,7 +69,7 @@ #endif
-static inline void curl_simple_lock_lock(curl_simple_lock *lock)
+static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock)
{
for(;;) {
if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
@@ -81,6 +81,8 @@ static inline void curl_simple_lock_lock(curl_simple_lock *lock) __builtin_ia32_pause();
#elif defined(__aarch64__)
__asm__ volatile("yield" ::: "memory");
+#elif defined(_WIN32)
+ Sleep(1);
#elif defined(HAVE_SCHED_YIELD)
sched_yield();
#endif
@@ -88,7 +90,7 @@ static inline void curl_simple_lock_lock(curl_simple_lock *lock) }
}
-static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
+static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock)
{
atomic_store_explicit(lock, false, memory_order_release);
}
diff --git a/libs/libcurl/src/easyoptions.c b/libs/libcurl/src/easyoptions.c index 66c0ef13c3..751ffa58ab 100644 --- a/libs/libcurl/src/easyoptions.c +++ b/libs/libcurl/src/easyoptions.c @@ -377,6 +377,6 @@ struct curl_easyoption Curl_easyopts[] = { */
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (326 + 1));
+ return (CURLOPT_LASTENTRY % 10000) != (326 + 1);
}
#endif
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c index 1c8b2b2c85..fe05ad067c 100644 --- a/libs/libcurl/src/file.c +++ b/libs/libcurl/src/file.c @@ -78,18 +78,12 @@ #include "curl_memory.h"
#include "memdebug.h"
-#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
+#if defined(_WIN32) || defined(MSDOS)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
#endif
-#ifdef OPEN_NEEDS_ARG3
-# define open_readonly(p,f) open((p),(f),(0))
-#else
-# define open_readonly(p,f) open((p),(f))
-#endif
-
/*
* Forward declarations.
*/
@@ -126,6 +120,7 @@ const struct Curl_handler Curl_handler_file = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
0, /* defport */
CURLPROTO_FILE, /* protocol */
CURLPROTO_FILE, /* family */
@@ -209,7 +204,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done) return CURLE_URL_MALFORMAT;
}
- fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
+ fd = open(actual_path, O_RDONLY|CURL_O_BINARY);
file->path = actual_path;
#else
if(memchr(real_path, 0, real_path_len)) {
@@ -233,16 +228,16 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done) extern int __unix_path_semantics;
if(strchr(real_path + 1, ':')) {
/* Amiga absolute path */
- fd = open_readonly(real_path + 1, O_RDONLY);
+ fd = open(real_path + 1, O_RDONLY);
file->path++;
}
else if(__unix_path_semantics) {
/* -lunix fallback */
- fd = open_readonly(real_path, O_RDONLY);
+ fd = open(real_path, O_RDONLY);
}
}
#else
- fd = open_readonly(real_path, O_RDONLY);
+ fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif
#endif
@@ -318,18 +313,18 @@ static CURLcode file_upload(struct Curl_easy *data) if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
-#ifdef O_BINARY
-#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
-#else
-#define MODE_DEFAULT O_WRONLY|O_CREAT
-#endif
-
+ mode = O_WRONLY|O_CREAT|CURL_O_BINARY;
if(data->state.resume_from)
- mode = MODE_DEFAULT|O_APPEND;
+ mode |= O_APPEND;
else
- mode = MODE_DEFAULT|O_TRUNC;
+ mode |= O_TRUNC;
+#if (defined(ANDROID) || defined(__ANDROID__)) && \
+ (defined(__i386__) || defined(__arm__))
+ fd = open(file->path, mode, (mode_t)data->set.new_file_perms);
+#else
fd = open(file->path, mode, data->set.new_file_perms);
+#endif
if(fd < 0) {
failf(data, "cannot open %s for writing", file->path);
return CURLE_WRITE_ERROR;
@@ -553,8 +548,13 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(data->state.resume_from) {
if(!S_ISDIR(statbuf.st_mode)) {
+#ifdef __AMIGA__
+ if(data->state.resume_from !=
+ lseek(fd, (off_t)data->state.resume_from, SEEK_SET))
+#else
if(data->state.resume_from !=
lseek(fd, data->state.resume_from, SEEK_SET))
+#endif
return CURLE_BAD_DOWNLOAD_RESUME;
}
else {
diff --git a/libs/libcurl/src/fopen.c b/libs/libcurl/src/fopen.c index 110345a067..de14f90f30 100644 --- a/libs/libcurl/src/fopen.c +++ b/libs/libcurl/src/fopen.c @@ -53,7 +53,7 @@ #ifdef _WIN32
#define PATHSEP "\\"
#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
-#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
+#elif defined(MSDOS) || defined(OS2)
#define PATHSEP "\\"
#define IS_SEP(x) ((x) == '\\')
#else
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index 20991676f1..9216aee564 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -250,6 +250,7 @@ const struct Curl_handler Curl_handler_ftp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
CURLPROTO_FTP, /* family */
@@ -282,6 +283,7 @@ const struct Curl_handler Curl_handler_ftps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
CURLPROTO_FTP, /* family */
@@ -2079,10 +2081,19 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, /* If we asked for a time of the file and we actually got one as well,
we "emulate" an HTTP-style header in our output. */
+#if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__))
+#pragma GCC diagnostic push
+/* 'time_t' is unsigned in MSDOS and AmigaOS. Silence:
+ warning: comparison of unsigned expression in '>= 0' is always true */
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
if(data->req.no_body &&
ftpc->file &&
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
+#if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__))
+#pragma GCC diagnostic pop
+#endif
char headerbuf[128];
int headerbuflen;
time_t filetime = data->info.filetime;
@@ -3154,7 +3165,7 @@ static CURLcode ftp_connect(struct Curl_easy *data, PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
- if(conn->handler->flags & PROTOPT_SSL) {
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* BLOCKING */
result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
@@ -4096,11 +4107,6 @@ static CURLcode ftp_disconnect(struct Curl_easy *data, return CURLE_OK;
}
-#ifdef _MSC_VER
-/* warning C4706: assignment within conditional expression */
-#pragma warning(disable:4706)
-#endif
-
/***********************************************************************
*
* ftp_parse_url_path()
@@ -4191,7 +4197,8 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) }
/* parse the URL path into separate path components */
- while((slashPos = strchr(curPos, '/'))) {
+ /* !checksrc! disable EQUALSNULL 1 */
+ while((slashPos = strchr(curPos, '/')) != NULL) {
size_t compLen = slashPos - curPos;
/* path starts with a slash: add that as a directory */
@@ -4244,7 +4251,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) else
n -= ftpc->file ? strlen(ftpc->file) : 0;
- if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
+ if((strlen(oldPath) == n) && rawPath && !strncmp(rawPath, oldPath, n)) {
infof(data, "Request has same path as previous transfer");
ftpc->cwddone = TRUE;
}
diff --git a/libs/libcurl/src/functypes.h b/libs/libcurl/src/functypes.h index 2ee699f7a5..bec5215b07 100644 --- a/libs/libcurl/src/functypes.h +++ b/libs/libcurl/src/functypes.h @@ -62,6 +62,7 @@ /* int send(int, const char *, int, int); */
#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2
#define SEND_TYPE_ARG2 char *
#define SEND_TYPE_ARG3 int
#define SEND_TYPE_RETV int
diff --git a/libs/libcurl/src/getinfo.c b/libs/libcurl/src/getinfo.c index a3f159e446..ff75ea13d8 100644 --- a/libs/libcurl/src/getinfo.c +++ b/libs/libcurl/src/getinfo.c @@ -69,6 +69,8 @@ CURLcode Curl_initinfo(struct Curl_easy *data) info->request_size = 0;
info->proxyauthavail = 0;
info->httpauthavail = 0;
+ info->proxyauthpicked = 0;
+ info->httpauthpicked = 0;
info->numconnects = 0;
free(info->contenttype);
@@ -238,8 +240,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, case CURLINFO_FILETIME:
if(data->info.filetime > LONG_MAX)
*param_longp = LONG_MAX;
+#if !defined(MSDOS) && !defined(__AMIGA__)
else if(data->info.filetime < LONG_MIN)
*param_longp = LONG_MIN;
+#endif
else
*param_longp = (long)data->info.filetime;
break;
@@ -270,6 +274,14 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, lptr.to_long = param_longp;
*lptr.to_ulong = data->info.proxyauthavail;
break;
+ case CURLINFO_HTTPAUTH_USED:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.httpauthpicked;
+ break;
+ case CURLINFO_PROXYAUTH_USED:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.proxyauthpicked;
+ break;
case CURLINFO_OS_ERRNO:
*param_longp = data->state.os_errno;
break;
@@ -377,6 +389,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info, case CURLINFO_APPCONNECT_TIME_T:
case CURLINFO_PRETRANSFER_TIME_T:
case CURLINFO_POSTTRANSFER_TIME_T:
+ case CURLINFO_QUEUE_TIME_T:
case CURLINFO_STARTTRANSFER_TIME_T:
case CURLINFO_REDIRECT_TIME_T:
case CURLINFO_SPEED_DOWNLOAD_T:
diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c index 220dc21807..3fc6fc0f56 100644 --- a/libs/libcurl/src/gopher.c +++ b/libs/libcurl/src/gopher.c @@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_gopher = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
CURLPROTO_GOPHER, /* family */
@@ -104,6 +105,7 @@ const struct Curl_handler Curl_handler_gophers = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHERS, /* protocol */
CURLPROTO_GOPHER, /* family */
diff --git a/libs/libcurl/src/hash.c b/libs/libcurl/src/hash.c index 64810bd1df..b531085793 100644 --- a/libs/libcurl/src/hash.c +++ b/libs/libcurl/src/hash.c @@ -42,6 +42,8 @@ hash_element_dtor(void *user, void *element) {
struct Curl_hash *h = (struct Curl_hash *) user;
struct Curl_hash_element *e = (struct Curl_hash_element *) element;
+ DEBUGASSERT(h);
+ DEBUGASSERT(e);
if(e->ptr) {
if(e->dtor)
diff --git a/libs/libcurl/src/hmac.c b/libs/libcurl/src/hmac.c index 4a8cffe798..f88b19dccd 100644 --- a/libs/libcurl/src/hmac.c +++ b/libs/libcurl/src/hmac.c @@ -26,8 +26,9 @@ #include "curl_setup.h"
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \
+ !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ defined(USE_SSL)
#include <curl/curl.h>
diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index 151fc7bf9d..7597ab814a 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -198,7 +198,7 @@ hostcache_entry_is_stale(void *datap, void *hc) if(dns->timestamp) {
/* age in seconds */
time_t age = prune->now - dns->timestamp;
- if(age >= prune->max_age_sec)
+ if(age >= (time_t)prune->max_age_sec)
return TRUE;
if(age > prune->oldest)
prune->oldest = age;
@@ -541,7 +541,9 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name) sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(port16);
sa6.sin6_flowinfo = 0;
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
sa6.sin6_scope_id = 0;
+#endif
(void)Curl_inet_pton(AF_INET6, "::1", ipv6);
memcpy(&sa6.sin6_addr, ipv6, sizeof(ipv6));
@@ -630,7 +632,7 @@ bool Curl_ipv6works(struct Curl_easy *data) ipv6_works = 1;
sclose(s);
}
- return (ipv6_works > 0);
+ return ipv6_works > 0;
}
}
#endif /* USE_IPV6 */
@@ -1077,18 +1079,10 @@ static void hostcache_unlink_entry(void *entry) Curl_freeaddrinfo(dns->addr);
#ifdef USE_HTTPSRR
if(dns->hinfo) {
- if(dns->hinfo->target)
- free(dns->hinfo->target);
- if(dns->hinfo->alpns)
- free(dns->hinfo->alpns);
- if(dns->hinfo->ipv4hints)
- free(dns->hinfo->ipv4hints);
- if(dns->hinfo->echconfiglist)
- free(dns->hinfo->echconfiglist);
- if(dns->hinfo->ipv6hints)
- free(dns->hinfo->ipv6hints);
- if(dns->hinfo->val)
- free(dns->hinfo->val);
+ free(dns->hinfo->target);
+ free(dns->hinfo->ipv4hints);
+ free(dns->hinfo->echconfiglist);
+ free(dns->hinfo->ipv6hints);
free(dns->hinfo);
}
#endif
diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index af0bde47f8..62ea20a3ed 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -29,6 +29,7 @@ #include "curl_addrinfo.h"
#include "timeval.h" /* for timediff_t */
#include "asyn.h"
+#include "httpsrr.h"
#include <setjmp.h>
@@ -53,6 +54,13 @@ struct hostent; struct Curl_easy;
struct connectdata;
+enum alpnid {
+ ALPN_none = 0,
+ ALPN_h1 = CURLALTSVC_H1,
+ ALPN_h2 = CURLALTSVC_H2,
+ ALPN_h3 = CURLALTSVC_H3
+};
+
/*
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
* Global DNS cache is general badness. Do not use. This will be removed in
@@ -62,36 +70,6 @@ struct connectdata; */
struct Curl_hash *Curl_global_host_cache_init(void);
-#ifdef USE_HTTPSRR
-
-#define CURL_MAXLEN_host_name 253
-
-struct Curl_https_rrinfo {
- size_t len; /* raw encoded length */
- unsigned char *val; /* raw encoded octets */
- /*
- * fields from HTTPS RR, with the mandatory fields
- * first (priority, target), then the others in the
- * order of the keytag numbers defined at
- * https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
- */
- uint16_t priority;
- char *target;
- char *alpns; /* keytag = 1 */
- bool no_def_alpn; /* keytag = 2 */
- /*
- * we do not support ports (keytag = 3) as we do not support
- * port-switching yet
- */
- unsigned char *ipv4hints; /* keytag = 4 */
- size_t ipv4hints_len;
- unsigned char *echconfiglist; /* keytag = 5 */
- size_t echconfiglist_len;
- unsigned char *ipv6hints; /* keytag = 6 */
- size_t ipv6hints_len;
-};
-#endif
-
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
#ifdef USE_HTTPSRR
diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c index 03c310ed09..cdaaa677e8 100644 --- a/libs/libcurl/src/hsts.c +++ b/libs/libcurl/src/hsts.c @@ -41,6 +41,7 @@ #include "rename.h"
#include "share.h"
#include "strdup.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -48,10 +49,8 @@ #include "memdebug.h"
#define MAX_HSTS_LINE 4095
-#define MAX_HSTS_HOSTLEN 256
-#define MAX_HSTS_HOSTLENSTR "256"
-#define MAX_HSTS_DATELEN 64
-#define MAX_HSTS_DATELENSTR "64"
+#define MAX_HSTS_HOSTLEN 2048
+#define MAX_HSTS_DATELEN 256
#define UNLIMITED "unlimited"
#if defined(DEBUGBUILD) || defined(UNITTESTS)
@@ -109,14 +108,13 @@ void Curl_hsts_cleanup(struct hsts **hp) static CURLcode hsts_create(struct hsts *h,
const char *hostname,
+ size_t hlen,
bool subdomains,
curl_off_t expires)
{
- size_t hlen;
DEBUGASSERT(h);
DEBUGASSERT(hostname);
- hlen = strlen(hostname);
if(hlen && (hostname[hlen - 1] == '.'))
/* strip off any trailing dot */
--hlen;
@@ -150,6 +148,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, bool subdomains = FALSE;
struct stsentry *sts;
time_t now = time(NULL);
+ size_t hlen = strlen(hostname);
if(Curl_host_is_ipnum(hostname))
/* "explicit IP address identification of all forms is excluded."
@@ -218,7 +217,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, if(!expires) {
/* remove the entry if present verbatim (without subdomain match) */
- sts = Curl_hsts(h, hostname, FALSE);
+ sts = Curl_hsts(h, hostname, hlen, FALSE);
if(sts) {
Curl_node_remove(&sts->node);
hsts_free(sts);
@@ -233,14 +232,14 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, expires += now;
/* check if it already exists */
- sts = Curl_hsts(h, hostname, FALSE);
+ sts = Curl_hsts(h, hostname, hlen, FALSE);
if(sts) {
/* just update these fields */
sts->expires = expires;
sts->includeSubDomains = subdomains;
}
else
- return hsts_create(h, hostname, subdomains, expires);
+ return hsts_create(h, hostname, hlen, subdomains, expires);
return CURLE_OK;
}
@@ -252,12 +251,11 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, * attempted.
*/
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
- bool subdomain)
+ size_t hlen, bool subdomain)
{
struct stsentry *bestsub = NULL;
if(h) {
time_t now = time(NULL);
- size_t hlen = strlen(hostname);
struct Curl_llist_node *e;
struct Curl_llist_node *n;
size_t blen = 0;
@@ -424,29 +422,40 @@ static CURLcode hsts_add(struct hsts *h, char *line) example.com "20191231 10:00:00"
.example.net "20191231 10:00:00"
*/
- char host[MAX_HSTS_HOSTLEN + 1];
- char date[MAX_HSTS_DATELEN + 1];
- int rc;
-
- rc = sscanf(line,
- "%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
- host, date);
- if(2 == rc) {
- time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) :
- TIME_T_MAX;
+ struct Curl_str host;
+ struct Curl_str date;
+
+ if(Curl_str_word(&line, &host, MAX_HSTS_HOSTLEN) ||
+ Curl_str_singlespace(&line) ||
+ Curl_str_quotedword(&line, &date, MAX_HSTS_DATELEN) ||
+ Curl_str_newline(&line))
+ ;
+ else {
CURLcode result = CURLE_OK;
- char *p = host;
bool subdomain = FALSE;
struct stsentry *e;
- if(p[0] == '.') {
- p++;
+ char dbuf[MAX_HSTS_DATELEN + 1];
+ time_t expires;
+
+ /* The date parser works on a null terminated string. The maximum length
+ is upheld by Curl_str_quotedword(). */
+ memcpy(dbuf, date.str, date.len);
+ dbuf[date.len] = 0;
+
+ expires = strcmp(dbuf, UNLIMITED) ? Curl_getdate_capped(dbuf) :
+ TIME_T_MAX;
+
+ if(host.str[0] == '.') {
+ host.str++;
+ host.len--;
subdomain = TRUE;
}
/* only add it if not already present */
- e = Curl_hsts(h, p, subdomain);
+ e = Curl_hsts(h, host.str, host.len, subdomain);
if(!e)
- result = hsts_create(h, p, subdomain, expires);
- else if(strcasecompare(p, e->host)) {
+ result = hsts_create(h, host.str, host.len, subdomain, expires);
+ else if((strlen(e->host) == host.len) &&
+ strncasecompare(host.str, e->host, host.len)) {
/* the same hostname, use the largest expire time */
if(expires > e->expires)
e->expires = expires;
@@ -488,7 +497,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) expires = Curl_getdate_capped(e.expire);
else
expires = TIME_T_MAX; /* the end of time */
- result = hsts_create(h, e.name,
+ result = hsts_create(h, e.name, strlen(e.name),
/* bitfield to bool conversion: */
e.includeSubDomains ? TRUE : FALSE,
expires);
diff --git a/libs/libcurl/src/hsts.h b/libs/libcurl/src/hsts.h index de08a1066a..486923c5fb 100644 --- a/libs/libcurl/src/hsts.h +++ b/libs/libcurl/src/hsts.h @@ -52,7 +52,7 @@ void Curl_hsts_cleanup(struct hsts **hp); CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
const char *sts);
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
- bool subdomain);
+ size_t hlen, bool subdomain);
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
const char *file);
CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index ed8a3598f1..1d6248a042 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -47,10 +47,6 @@ #include <sys/param.h>
#endif
-#ifdef USE_HYPER
-#include <hyper.h>
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -68,6 +64,7 @@ #include "http_negotiate.h"
#include "http_aws_sigv4.h"
#include "url.h"
+#include "urlapi-int.h"
#include "share.h"
#include "hostip.h"
#include "dynhds.h"
@@ -88,7 +85,6 @@ #include "altsvc.h"
#include "hsts.h"
#include "ws.h"
-#include "c-hyper.h"
#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
@@ -104,6 +100,30 @@ static bool http_should_fail(struct Curl_easy *data, int httpcode); static bool http_exp100_is_waiting(struct Curl_easy *data);
static CURLcode http_exp100_add_reader(struct Curl_easy *data);
static void http_exp100_send_anyway(struct Curl_easy *data);
+static bool http_exp100_is_selected(struct Curl_easy *data);
+static void http_exp100_got100(struct Curl_easy *data);
+static CURLcode http_firstwrite(struct Curl_easy *data);
+static CURLcode http_header(struct Curl_easy *data,
+ const char *hd, size_t hdlen);
+static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn);
+static CURLcode http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq);
+static CURLcode http_req_complete(struct Curl_easy *data,
+ struct dynbuf *r, int httpversion,
+ Curl_HttpReq httpreq);
+static CURLcode http_req_set_reader(struct Curl_easy *data,
+ Curl_HttpReq httpreq, int httpversion,
+ const char **tep);
+static CURLcode http_size(struct Curl_easy *data);
+static CURLcode http_statusline(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode http_target(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *req);
+static CURLcode http_useragent(struct Curl_easy *data);
+#ifdef HAVE_LIBZ
+static CURLcode http_transferencode(struct Curl_easy *data);
+#endif
+
/*
* HTTP handler interface.
@@ -126,6 +146,7 @@ const struct Curl_handler Curl_handler_http = { Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ Curl_http_follow, /* follow */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -155,6 +176,7 @@ const struct Curl_handler Curl_handler_https = { Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ Curl_http_follow, /* follow */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -473,7 +495,6 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, ongoing_auth ? " send, " : "");
/* We decided to abort the ongoing transfer */
streamclose(conn, "Mid-auth HTTP and much data left to send");
- /* FIXME: questionable manipulation here, can we do this differently? */
data->req.size = 0; /* do not download any more than 0 bytes */
}
return CURLE_OK;
@@ -510,8 +531,10 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
+ else
+ data->info.httpauthpicked = data->state.authhost.picked;
if(data->state.authhost.picked == CURLAUTH_NTLM &&
- conn->httpversion > 11) {
+ (data->req.httpversion_sent > 11)) {
infof(data, "Forcing HTTP/1.1 for NTLM");
connclose(conn, "Force HTTP/1.1 connection");
data->state.httpwant = CURL_HTTP_VERSION_1_1;
@@ -525,6 +548,9 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) authmask & ~CURLAUTH_BEARER);
if(!pickproxy)
data->state.authproblem = TRUE;
+ else
+ data->info.proxyauthpicked = data->state.authproxy.picked;
+
}
#endif
@@ -831,12 +857,12 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
- &conn->http_negotiate_state;
+ &conn->http_negotiate_state;
#endif
-#if defined(USE_SPNEGO) || \
- defined(USE_NTLM) || \
- !defined(CURL_DISABLE_DIGEST_AUTH) || \
- !defined(CURL_DISABLE_BASIC_AUTH) || \
+#if defined(USE_SPNEGO) || \
+ defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
!defined(CURL_DISABLE_BEARER_AUTH)
unsigned long *availp;
@@ -967,7 +993,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, authp->avail |= CURLAUTH_BEARER;
if(authp->picked == CURLAUTH_BEARER) {
/* We asked for Bearer authentication but got a 40X back
- anyway, which basically means our token is not valid. */
+ anyway, which basically means our token is not valid. */
authp->avail = CURLAUTH_NONE;
infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
@@ -1067,6 +1093,283 @@ static bool http_should_fail(struct Curl_easy *data, int httpcode) return data->state.authproblem;
}
+CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
+ followtype type)
+{
+ bool disallowport = FALSE;
+ bool reachedmax = FALSE;
+ char *follow_url = NULL;
+ CURLUcode uc;
+
+ DEBUGASSERT(type != FOLLOW_NONE);
+
+ if(type != FOLLOW_FAKE)
+ data->state.requests++; /* count all real follows */
+ if(type == FOLLOW_REDIR) {
+ if((data->set.maxredirs != -1) &&
+ (data->state.followlocation >= data->set.maxredirs)) {
+ reachedmax = TRUE;
+ type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
+ to URL */
+ }
+ else {
+ data->state.followlocation++; /* count redirect-followings, including
+ auth reloads */
+
+ if(data->set.http_auto_referer) {
+ CURLU *u;
+ char *referer = NULL;
+
+ /* We are asked to automatically set the previous URL as the referer
+ when we get the next URL. We pick the ->url field, which may or may
+ not be 100% correct */
+
+ if(data->state.referer_alloc) {
+ Curl_safefree(data->state.referer);
+ data->state.referer_alloc = FALSE;
+ }
+
+ /* Make a copy of the URL without credentials and fragment */
+ u = curl_url();
+ if(!u)
+ return CURLE_OUT_OF_MEMORY;
+
+ uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
+ if(!uc)
+ uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
+
+ curl_url_cleanup(u);
+
+ if(uc || !referer)
+ return CURLE_OUT_OF_MEMORY;
+
+ data->state.referer = referer;
+ data->state.referer_alloc = TRUE; /* yes, free this later */
+ }
+ }
+ }
+
+ if((type != FOLLOW_RETRY) &&
+ (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
+ Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
+ /* If this is not redirect due to a 401 or 407 response and an absolute
+ URL: do not allow a custom port number */
+ disallowport = TRUE;
+ }
+
+ DEBUGASSERT(data->state.uh);
+ uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
+ ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
+ ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
+ CURLU_ALLOW_SPACE |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
+ if(uc) {
+ if(type != FOLLOW_FAKE) {
+ failf(data, "The redirect target URL could not be parsed: %s",
+ curl_url_strerror(uc));
+ return Curl_uc_to_curlcode(uc);
+ }
+
+ /* the URL could not be parsed for some reason, but since this is FAKE
+ mode, just duplicate the field as-is */
+ follow_url = strdup(newurl);
+ if(!follow_url)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &follow_url, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+
+ /* Clear auth if this redirects to a different port number or protocol,
+ unless permitted */
+ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
+ char *portnum;
+ int port;
+ bool clear = FALSE;
+
+ if(data->set.use_port && data->state.allow_port)
+ /* a custom port is used */
+ port = (int)data->set.use_port;
+ else {
+ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
+ CURLU_DEFAULT_PORT);
+ if(uc) {
+ free(follow_url);
+ return Curl_uc_to_curlcode(uc);
+ }
+ port = atoi(portnum);
+ free(portnum);
+ }
+ if(port != data->info.conn_remote_port) {
+ infof(data, "Clear auth, redirects to port from %u to %u",
+ data->info.conn_remote_port, port);
+ clear = TRUE;
+ }
+ else {
+ char *scheme;
+ const struct Curl_handler *p;
+ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
+ if(uc) {
+ free(follow_url);
+ return Curl_uc_to_curlcode(uc);
+ }
+
+ p = Curl_get_scheme_handler(scheme);
+ if(p && (p->protocol != data->info.conn_protocol)) {
+ infof(data, "Clear auth, redirects scheme from %s to %s",
+ data->info.conn_scheme, scheme);
+ clear = TRUE;
+ }
+ free(scheme);
+ }
+ if(clear) {
+ Curl_safefree(data->state.aptr.user);
+ Curl_safefree(data->state.aptr.passwd);
+ }
+ }
+ }
+ DEBUGASSERT(follow_url);
+
+ if(type == FOLLOW_FAKE) {
+ /* we are only figuring out the new URL if we would have followed locations
+ but now we are done so we can get out! */
+ data->info.wouldredirect = follow_url;
+
+ if(reachedmax) {
+ failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
+ return CURLE_TOO_MANY_REDIRECTS;
+ }
+ return CURLE_OK;
+ }
+
+ if(disallowport)
+ data->state.allow_port = FALSE;
+
+ if(data->state.url_alloc)
+ Curl_safefree(data->state.url);
+
+ data->state.url = follow_url;
+ data->state.url_alloc = TRUE;
+ Curl_req_soft_reset(&data->req, data);
+ infof(data, "Issue another request to this URL: '%s'", data->state.url);
+
+ /*
+ * We get here when the HTTP code is 300-399 (and 401). We need to perform
+ * differently based on exactly what return code there was.
+ *
+ * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
+ * an HTTP (proxy-) authentication scheme other than Basic.
+ */
+ switch(data->info.httpcode) {
+ /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
+ Authorization: XXXX header in the HTTP request code snippet */
+ /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
+ Proxy-Authorization: XXXX header in the HTTP request code snippet */
+ /* 300 - Multiple Choices */
+ /* 306 - Not used */
+ /* 307 - Temporary Redirect */
+ default: /* for all above (and the unknown ones) */
+ /* Some codes are explicitly mentioned since I have checked RFC2616 and
+ * they seem to be OK to POST to.
+ */
+ break;
+ case 301: /* Moved Permanently */
+ /* (quote from RFC7231, section 6.4.2)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->state.httpreq == HTTPREQ_POST
+ || data->state.httpreq == HTTPREQ_POST_FORM
+ || data->state.httpreq == HTTPREQ_POST_MIME)
+ && !(data->set.keep_post & CURL_REDIR_POST_301)) {
+ infof(data, "Switch from POST to GET");
+ data->state.httpreq = HTTPREQ_GET;
+ Curl_creader_set_rewind(data, FALSE);
+ }
+ break;
+ case 302: /* Found */
+ /* (quote from RFC7231, section 6.4.3)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->state.httpreq == HTTPREQ_POST
+ || data->state.httpreq == HTTPREQ_POST_FORM
+ || data->state.httpreq == HTTPREQ_POST_MIME)
+ && !(data->set.keep_post & CURL_REDIR_POST_302)) {
+ infof(data, "Switch from POST to GET");
+ data->state.httpreq = HTTPREQ_GET;
+ Curl_creader_set_rewind(data, FALSE);
+ }
+ break;
+
+ case 303: /* See Other */
+ /* 'See Other' location is not the resource but a substitute for the
+ * resource. In this case we switch the method to GET/HEAD, unless the
+ * method is POST and the user specified to keep it as POST.
+ * https://github.com/curl/curl/issues/5237#issuecomment-614641049
+ */
+ if(data->state.httpreq != HTTPREQ_GET &&
+ ((data->state.httpreq != HTTPREQ_POST &&
+ data->state.httpreq != HTTPREQ_POST_FORM &&
+ data->state.httpreq != HTTPREQ_POST_MIME) ||
+ !(data->set.keep_post & CURL_REDIR_POST_303))) {
+ data->state.httpreq = HTTPREQ_GET;
+ infof(data, "Switch to %s",
+ data->req.no_body ? "HEAD" : "GET");
+ }
+ break;
+ case 304: /* Not Modified */
+ /* 304 means we did a conditional request and it was "Not modified".
+ * We should not get any Location: header in this response!
+ */
+ break;
+ case 305: /* Use Proxy */
+ /* (quote from RFC2616, section 10.3.6):
+ * "The requested resource MUST be accessed through the proxy given
+ * by the Location field. The Location field gives the URI of the
+ * proxy. The recipient is expected to repeat this single request
+ * via the proxy. 305 responses MUST only be generated by origin
+ * servers."
+ */
+ break;
+ }
+ Curl_pgrsTime(data, TIMER_REDIRECT);
+ Curl_pgrsResetTransferSizes(data);
+
+ return CURLE_OK;
+}
+
/*
* Curl_compareheader()
*
@@ -1169,7 +1472,6 @@ CURLcode Curl_http_done(struct Curl_easy *data, data->state.authproxy.multipass = FALSE;
Curl_dyn_reset(&data->state.headerb);
- Curl_hyper_done(data);
if(status)
return status;
@@ -1193,52 +1495,55 @@ CURLcode Curl_http_done(struct Curl_easy *data, return CURLE_OK;
}
-/*
- * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
- * to avoid it include:
- *
- * - if the user specifically requested HTTP 1.0
- * - if the server we are connected to only supports 1.0
- * - if any server previously contacted to handle this request only supports
- * 1.0.
- */
-bool Curl_use_http_1_1plus(const struct Curl_easy *data,
- const struct connectdata *conn)
+/* Determine if we may use HTTP 1.1 for this request. */
+static bool http_may_use_1_1(const struct Curl_easy *data)
{
- if((data->state.httpversion == 10) || (conn->httpversion == 10))
+ const struct connectdata *conn = data->conn;
+ /* We have seen a previous response for *this* transfer with 1.0,
+ * on another connection or the same one. */
+ if(data->state.httpversion == 10)
+ return FALSE;
+ /* We have seen a previous response on *this* connection with 1.0. */
+ if(conn->httpversion_seen == 10)
return FALSE;
+ /* We want 1.0 and have seen no previous response on *this* connection
+ with a higher version (maybe no response at all yet). */
if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
- (conn->httpversion <= 10))
+ (conn->httpversion_seen <= 10))
return FALSE;
- return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
- (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
+ /* We want something newer than 1.0 or have no preferences. */
+ return (data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
+ (data->state.httpwant >= CURL_HTTP_VERSION_1_1);
}
-#ifndef USE_HYPER
-static const char *get_http_string(const struct Curl_easy *data,
- const struct connectdata *conn)
+static unsigned char http_request_version(struct Curl_easy *data)
{
- if(Curl_conn_is_http3(data, conn, FIRSTSOCKET))
- return "3";
- if(Curl_conn_is_http2(data, conn, FIRSTSOCKET))
- return "2";
- if(Curl_use_http_1_1plus(data, conn))
- return "1.1";
-
- return "1.0";
+ unsigned char httpversion = Curl_conn_http_version(data);
+ if(!httpversion) {
+ /* No specific HTTP connection filter installed. */
+ httpversion = http_may_use_1_1(data) ? 11 : 10;
+ }
+ return httpversion;
+}
+
+static const char *get_http_string(int httpversion)
+{
+ switch(httpversion) {
+ case 30:
+ return "3";
+ case 20:
+ return "2";
+ case 11:
+ return "1.1";
+ default:
+ return "1.0";
+ }
}
-#endif
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
- bool is_connect,
-#ifndef USE_HYPER
- struct dynbuf *req
-#else
- void *req
-#endif
- )
+ bool is_connect, int httpversion,
+ struct dynbuf *req)
{
- struct connectdata *conn = data->conn;
char *ptr;
struct curl_slist *h[2];
struct curl_slist *headers;
@@ -1251,7 +1556,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, if(is_connect)
proxy = HEADER_CONNECT;
else
- proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ?
+ proxy = data->conn->bits.httpproxy && !data->conn->bits.tunnel_proxy ?
HEADER_PROXY : HEADER_SERVER;
switch(proxy) {
@@ -1303,9 +1608,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, /* copy the source */
semicolonp = strdup(headers->data);
if(!semicolonp) {
-#ifndef USE_HYPER
Curl_dyn_free(req);
-#endif
return CURLE_OUT_OF_MEMORY;
}
/* put a colon where the semicolon is */
@@ -1353,7 +1656,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, Connection: */
checkprefix("Connection:", compare))
;
- else if((conn->httpversion >= 20) &&
+ else if((httpversion >= 20) &&
checkprefix("Transfer-Encoding:", compare))
/* HTTP/2 does not support chunked requests */
;
@@ -1364,11 +1667,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, !Curl_auth_allowed_to_host(data))
;
else {
-#ifdef USE_HYPER
- result = Curl_hyper_header(data, req, compare);
-#else
result = Curl_dyn_addf(req, "%s\r\n", compare);
-#endif
}
if(semicolonp)
free(semicolonp);
@@ -1385,12 +1684,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, #ifndef CURL_DISABLE_PARSEDATE
CURLcode Curl_add_timecondition(struct Curl_easy *data,
-#ifndef USE_HYPER
- struct dynbuf *req
-#else
- void *req
-#endif
- )
+ struct dynbuf *req)
{
const struct tm *tm;
struct tm keeptime;
@@ -1453,12 +1747,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, tm->tm_min,
tm->tm_sec);
-#ifndef USE_HYPER
result = Curl_dyn_add(req, datestr);
-#else
- result = Curl_hyper_header(data, req, datestr);
-#endif
-
return result;
}
#else
@@ -1512,7 +1801,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, *reqp = httpreq;
}
-CURLcode Curl_http_useragent(struct Curl_easy *data)
+static CURLcode http_useragent(struct Curl_easy *data)
{
/* The User-Agent string might have been allocated in url.c already, because
it might have been used in the proxy connect, but if we have got a header
@@ -1526,7 +1815,7 @@ CURLcode Curl_http_useragent(struct Curl_easy *data) }
-CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
+static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn)
{
const char *ptr;
struct dynamically_allocated_data *aptr = &data->state.aptr;
@@ -1616,9 +1905,9 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) /*
* Append the request-target to the HTTP request
*/
-CURLcode Curl_http_target(struct Curl_easy *data,
- struct connectdata *conn,
- struct dynbuf *r)
+static CURLcode http_target(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
{
CURLcode result = CURLE_OK;
const char *path = data->state.up.path;
@@ -1684,7 +1973,7 @@ CURLcode Curl_http_target(struct Curl_easy *data, data->set.str[STRING_TARGET] : url);
free(url);
if(result)
- return (result);
+ return result;
if(strcasecompare("ftp", data->state.up.scheme)) {
if(data->set.proxy_transfer_mode) {
@@ -1898,9 +2187,9 @@ static CURLcode http_resume(struct Curl_easy *data, Curl_HttpReq httpreq) return CURLE_OK;
}
-CURLcode Curl_http_req_set_reader(struct Curl_easy *data,
- Curl_HttpReq httpreq,
- const char **tep)
+static CURLcode http_req_set_reader(struct Curl_easy *data,
+ Curl_HttpReq httpreq, int httpversion,
+ const char **tep)
{
CURLcode result = CURLE_OK;
const char *ptr;
@@ -1919,12 +2208,10 @@ CURLcode Curl_http_req_set_reader(struct Curl_easy *data, data->req.upload_chunky =
Curl_compareheader(ptr,
STRCONST("Transfer-Encoding:"), STRCONST("chunked"));
- if(data->req.upload_chunky &&
- Curl_use_http_1_1plus(data, data->conn) &&
- (data->conn->httpversion >= 20)) {
- infof(data, "suppressing chunked transfer encoding on connection "
- "using HTTP version 2 or higher");
- data->req.upload_chunky = FALSE;
+ if(data->req.upload_chunky && (httpversion >= 20)) {
+ infof(data, "suppressing chunked transfer encoding on connection "
+ "using HTTP version 2 or higher");
+ data->req.upload_chunky = FALSE;
}
}
else {
@@ -1932,10 +2219,10 @@ CURLcode Curl_http_req_set_reader(struct Curl_easy *data, if(req_clen < 0) {
/* indeterminate request content length */
- if(Curl_use_http_1_1plus(data, data->conn)) {
+ if(httpversion > 10) {
/* On HTTP/1.1, enable chunked, on HTTP/2 and later we do not
* need it */
- data->req.upload_chunky = (data->conn->httpversion < 20);
+ data->req.upload_chunky = (httpversion < 20);
}
else {
failf(data, "Chunky upload is not supported by HTTP 1.0");
@@ -1954,7 +2241,7 @@ CURLcode Curl_http_req_set_reader(struct Curl_easy *data, }
static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
- bool *announced_exp100)
+ int httpversion, bool *announced_exp100)
{
CURLcode result;
char *ptr;
@@ -1973,9 +2260,7 @@ static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r, *announced_exp100 =
Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
}
- else if(!data->state.disableexpect &&
- Curl_use_http_1_1plus(data, data->conn) &&
- (data->conn->httpversion < 20)) {
+ else if(!data->state.disableexpect && (httpversion == 11)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
@@ -1990,21 +2275,20 @@ static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r, return CURLE_OK;
}
-CURLcode Curl_http_req_complete(struct Curl_easy *data,
- struct dynbuf *r, Curl_HttpReq httpreq)
+static CURLcode http_req_complete(struct Curl_easy *data,
+ struct dynbuf *r, int httpversion,
+ Curl_HttpReq httpreq)
{
CURLcode result = CURLE_OK;
curl_off_t req_clen;
bool announced_exp100 = FALSE;
DEBUGASSERT(data->conn);
-#ifndef USE_HYPER
if(data->req.upload_chunky) {
result = Curl_httpchunk_add_reader(data);
if(result)
return result;
}
-#endif
/* Get the request body length that has been set up */
req_clen = Curl_creader_total_length(data);
@@ -2053,7 +2337,7 @@ CURLcode Curl_http_req_complete(struct Curl_easy *data, goto out;
}
}
- result = addexpect(data, r, &announced_exp100);
+ result = addexpect(data, r, httpversion, &announced_exp100);
if(result)
goto out;
break;
@@ -2079,9 +2363,9 @@ out: #if !defined(CURL_DISABLE_COOKIES)
-CURLcode Curl_http_cookies(struct Curl_easy *data,
- struct connectdata *conn,
- struct dynbuf *r)
+static CURLcode http_cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
{
CURLcode result = CURLE_OK;
char *addcookies = NULL;
@@ -2155,10 +2439,12 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, }
return result;
}
+#else
+#define http_cookies(a,b,c) CURLE_OK
#endif
-CURLcode Curl_http_range(struct Curl_easy *data,
- Curl_HttpReq httpreq)
+static CURLcode http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq)
{
if(data->state.use_range) {
/*
@@ -2190,7 +2476,7 @@ CURLcode Curl_http_range(struct Curl_easy *data, }
else if(data->state.resume_from) {
/* This is because "resume" was selected */
- /* TODO: not sure if we want to send this header during authentication
+ /* Not sure if we want to send this header during authentication
* negotiation, but test1084 checks for it. In which case we have a
* "null" client reader installed that gives an unexpected length. */
curl_off_t total_len = data->req.authneg ?
@@ -2214,7 +2500,7 @@ CURLcode Curl_http_range(struct Curl_easy *data, return CURLE_OK;
}
-CURLcode Curl_http_firstwrite(struct Curl_easy *data)
+static CURLcode http_firstwrite(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
@@ -2277,7 +2563,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data) }
#ifdef HAVE_LIBZ
-CURLcode Curl_transferencode(struct Curl_easy *data)
+static CURLcode http_transferencode(struct Curl_easy *data)
{
if(!Curl_checkheaders(data, STRCONST("TE")) &&
data->set.http_transfer_encoding) {
@@ -2309,7 +2595,6 @@ CURLcode Curl_transferencode(struct Curl_easy *data) }
#endif
-#ifndef USE_HYPER
/*
* Curl_http() gets called from the generic multi_do() function when an HTTP
* request is to be performed. This creates and sends a properly constructed
@@ -2326,6 +2611,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) struct dynbuf req;
char *altused = NULL;
const char *p_accept; /* Accept: string */
+ unsigned char httpversion;
/* Always consider the DO phase done after this function call, even if there
may be parts of the request that are not yet sent, since we can deal with
@@ -2334,29 +2620,29 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) switch(conn->alpn) {
case CURL_HTTP_VERSION_3:
- DEBUGASSERT(Curl_conn_is_http3(data, conn, FIRSTSOCKET));
+ DEBUGASSERT(Curl_conn_http_version(data) == 30);
break;
case CURL_HTTP_VERSION_2:
#ifndef CURL_DISABLE_PROXY
- if(!Curl_conn_is_http2(data, conn, FIRSTSOCKET) &&
+ if((Curl_conn_http_version(data) != 20) &&
conn->bits.proxy && !conn->bits.tunnel_proxy
) {
- result = Curl_http2_switch(data, conn, FIRSTSOCKET);
+ result = Curl_http2_switch(data);
if(result)
goto fail;
}
else
#endif
- DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
+ DEBUGASSERT(Curl_conn_http_version(data) == 20);
break;
case CURL_HTTP_VERSION_1_1:
/* continue with HTTP/1.x when explicitly requested */
break;
default:
/* Check if user wants to use HTTP/2 with clear TCP */
- if(Curl_http2_may_switch(data, conn, FIRSTSOCKET)) {
+ if(Curl_http2_may_switch(data)) {
DEBUGF(infof(data, "HTTP/2 over clean TCP"));
- result = Curl_http2_switch(data, conn, FIRSTSOCKET);
+ result = Curl_http2_switch(data);
if(result)
goto fail;
}
@@ -2370,11 +2656,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(result)
goto fail;
- result = Curl_http_host(data, conn);
+ result = http_host(data, conn);
if(result)
goto fail;
- result = Curl_http_useragent(data);
+ result = http_useragent(data);
if(result)
goto fail;
@@ -2415,24 +2701,25 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) #ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
- result = Curl_transferencode(data);
+ result = http_transferencode(data);
if(result)
goto fail;
#endif
- result = Curl_http_req_set_reader(data, httpreq, &te);
+ httpversion = http_request_version(data);
+ httpstring = get_http_string(httpversion);
+
+ result = http_req_set_reader(data, httpreq, httpversion, &te);
if(result)
goto fail;
p_accept = Curl_checkheaders(data,
STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
- result = Curl_http_range(data, httpreq);
+ result = http_range(data, httpreq);
if(result)
goto fail;
- httpstring = get_http_string(data, conn);
-
/* initialize a dynamic send-buffer */
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
@@ -2444,7 +2731,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* GET/HEAD/POST/PUT */
result = Curl_dyn_addf(&req, "%s ", request);
if(!result)
- result = Curl_http_target(data, conn, &req);
+ result = http_target(data, conn, &req);
if(result) {
Curl_dyn_free(&req);
goto fail;
@@ -2526,8 +2813,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto fail;
}
- if(!(conn->handler->flags&PROTOPT_SSL) &&
- conn->httpversion < 20 &&
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET) && (httpversion < 20) &&
(data->state.httpwant == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it is not done
over SSL */
@@ -2538,7 +2824,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) }
}
- result = Curl_http_cookies(data, conn, &req);
+ result = http_cookies(data, conn, &req);
#ifndef CURL_DISABLE_WEBSOCKETS
if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
result = Curl_ws_request(data, &req);
@@ -2546,19 +2832,19 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(!result)
result = Curl_add_timecondition(data, &req);
if(!result)
- result = Curl_add_custom_headers(data, FALSE, &req);
+ result = Curl_add_custom_headers(data, FALSE, httpversion, &req);
if(!result) {
/* req_send takes ownership of the 'req' memory on success */
- result = Curl_http_req_complete(data, &req, httpreq);
+ result = http_req_complete(data, &req, httpversion, httpreq);
if(!result)
- result = Curl_req_send(data, &req);
+ result = Curl_req_send(data, &req, httpversion);
}
Curl_dyn_free(&req);
if(result)
goto fail;
- if((conn->httpversion >= 20) && data->req.upload_chunky)
+ if((httpversion >= 20) && data->req.upload_chunky)
/* upload_chunky was set above to set up the request in a chunky fashion,
but is disabled here again to avoid that the chunked encoded version is
actually used when sending the request body over h2 */
@@ -2569,8 +2855,6 @@ fail: return result;
}
-#endif /* USE_HYPER */
-
typedef enum {
STATUS_UNKNOWN, /* not enough data to tell yet */
STATUS_DONE, /* a status line was read */
@@ -2657,10 +2941,10 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, Curl_compareheader(hd, STRCONST(n), STRCONST(v)))
/*
- * Curl_http_header() parses a single response header.
+ * http_header() parses a single response header.
*/
-CURLcode Curl_http_header(struct Curl_easy *data,
- const char *hd, size_t hdlen)
+static CURLcode http_header(struct Curl_easy *data,
+ const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
CURLcode result;
@@ -2672,7 +2956,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, case 'A':
#ifndef CURL_DISABLE_ALTSVC
v = (data->asi &&
- ((data->conn->handler->flags & PROTOPT_SSL) ||
+ (Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ||
#ifdef DEBUGBUILD
/* allow debug builds to circumvent the HTTPS restriction */
getenv("CURL_ALTSVC_HTTP")
@@ -2682,8 +2966,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, )) ? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
if(v) {
/* the ALPN of the current request */
- enum alpnid id = (conn->httpversion == 30) ? ALPN_h3 :
- (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+ enum alpnid id = (k->httpversion == 30) ? ALPN_h3 :
+ (k->httpversion == 20) ? ALPN_h2 : ALPN_h1;
return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
curlx_uitous((unsigned int)conn->remote_port));
}
@@ -2755,7 +3039,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, streamclose(conn, "Connection: close used");
return CURLE_OK;
}
- if((conn->httpversion == 10) &&
+ if((k->httpversion == 10) &&
HD_IS_AND_SAYS(hd, hdlen, "Connection:", "keep-alive")) {
/*
* An HTTP/1.0 reply with the 'Connection: keep-alive' line
@@ -2845,7 +3129,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY
v = HD_VAL(hd, hdlen, "Proxy-Connection:");
if(v) {
- if((conn->httpversion == 10) && conn->bits.httpproxy &&
+ if((k->httpversion == 10) && conn->bits.httpproxy &&
HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "keep-alive")) {
/*
* When an HTTP/1.0 reply comes when using a proxy, the
@@ -2856,7 +3140,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, connkeep(conn, "Proxy-Connection keep-alive"); /* do not close */
infof(data, "HTTP/1.0 proxy connection set to keep alive");
}
- else if((conn->httpversion == 11) && conn->bits.httpproxy &&
+ else if((k->httpversion == 11) && conn->bits.httpproxy &&
HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "close")) {
/*
* We get an HTTP/1.1 response from a proxy and it says it will
@@ -2903,11 +3187,19 @@ CURLcode Curl_http_header(struct Curl_easy *data, (void)curlx_strtoofft(v, NULL, 10, &retry_after);
if(!retry_after) {
time_t date = Curl_getdate_capped(v);
- if(-1 != date)
+ time_t current = time(NULL);
+ if((time_t)-1 != date && date > current) {
/* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
+ retry_after = date - current;
+ }
}
- data->info.retry_after = retry_after; /* store it */
+ if(retry_after < 0)
+ retry_after = 0;
+ /* limit to 6 hours max. this is not documented so that it can be changed
+ in the future if necessary. */
+ if(retry_after > 21600)
+ retry_after = 21600;
+ data->info.retry_after = retry_after;
return CURLE_OK;
}
break;
@@ -2938,7 +3230,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, #ifndef CURL_DISABLE_HSTS
/* If enabled, the header is incoming and this is over HTTPS */
v = (data->hsts &&
- ((conn->handler->flags & PROTOPT_SSL) ||
+ (Curl_conn_is_ssl(conn, FIRSTSOCKET) ||
#ifdef DEBUGBUILD
/* allow debug builds to circumvent the HTTPS restriction */
getenv("CURL_HSTS_HTTP")
@@ -3022,8 +3314,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, * Called after the first HTTP response line (the status line) has been
* received and parsed.
*/
-CURLcode Curl_http_statusline(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode http_statusline(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SingleRequest *k = &data->req;
@@ -3037,11 +3329,11 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, case 30:
#endif
/* no major version switch mid-connection */
- if(conn->httpversion &&
- (k->httpversion/10 != conn->httpversion/10)) {
+ if(k->httpversion_sent &&
+ (k->httpversion/10 != k->httpversion_sent/10)) {
failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)",
- conn->httpversion/10, k->httpversion/10);
- return CURLE_UNSUPPORTED_PROTOCOL;
+ k->httpversion_sent/10, k->httpversion/10);
+ return CURLE_WEIRD_SERVER_REPLY;
}
break;
default:
@@ -3052,7 +3344,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, data->info.httpcode = k->httpcode;
data->info.httpversion = k->httpversion;
- conn->httpversion = (unsigned char)k->httpversion;
+ conn->httpversion_seen = (unsigned char)k->httpversion;
if(!data->state.httpversion || data->state.httpversion > k->httpversion)
/* store the lowest server version we encounter */
@@ -3116,7 +3408,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, figured out here after all headers have been received but before the final
call to the user's header callback, so that a valid content length can be
retrieved by the user in the final call. */
-CURLcode Curl_http_size(struct Curl_easy *data)
+static CURLcode http_size(struct Curl_easy *data)
{
struct SingleRequest *k = &data->req;
if(data->req.ignore_cl || k->chunk) {
@@ -3232,7 +3524,7 @@ static CURLcode http_on_response(struct Curl_easy *data, if(k->upgr101 == UPGR101_RECEIVED) {
/* supposedly upgraded to http2 now */
- if(conn->httpversion != 20)
+ if(data->req.httpversion != 20)
infof(data, "Lying server, not serving HTTP/2");
}
@@ -3264,12 +3556,11 @@ static CURLcode http_on_response(struct Curl_easy *data, * that tells us that the server is OK with this and ready
* to receive the data.
*/
- Curl_http_exp100_got100(data);
+ http_exp100_got100(data);
break;
case 101:
/* Switching Protocols only allowed from HTTP/1.1 */
-
- if(conn->httpversion != 11) {
+ if(k->httpversion_sent != 11) {
/* invalid for other HTTP versions */
failf(data, "unexpected 101 response code");
result = CURLE_WEIRD_SERVER_REPLY;
@@ -3283,6 +3574,7 @@ static CURLcode http_on_response(struct Curl_easy *data, /* We expect more response from HTTP/2 later */
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
+ k->httpversion_sent = 20; /* It's a HTTP/2 request now */
/* Any remaining `buf` bytes are already HTTP/2 and passed to
* be processed. */
result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
@@ -3304,10 +3596,9 @@ static CURLcode http_on_response(struct Curl_easy *data, }
#endif
else {
- /* We silently accept this as the final response.
- * TODO: this looks, uhm, wrong. What are we switching to if we
- * did not ask for an Upgrade? Maybe the application provided an
- * `Upgrade: xxx` header? */
+ /* We silently accept this as the final response. What are we
+ * switching to if we did not ask for an Upgrade? Maybe the
+ * application provided an `Upgrade: xxx` header? */
k->header = FALSE;
}
break;
@@ -3331,7 +3622,7 @@ static CURLcode http_on_response(struct Curl_easy *data, }
if((k->size == -1) && !k->chunk && !conn->bits.close &&
- (conn->httpversion == 11) &&
+ (k->httpversion == 11) &&
!(conn->handler->protocol & CURLPROTO_RTSP) &&
data->state.httpreq != HTTPREQ_HEAD) {
/* On HTTP 1.1, when connection is not to get closed, but no
@@ -3423,7 +3714,7 @@ static CURLcode http_on_response(struct Curl_easy *data, * connection for closure after we have read the entire response.
*/
if(!Curl_req_done_sending(data)) {
- if((k->httpcode == 417) && Curl_http_exp100_is_selected(data)) {
+ if((k->httpcode == 417) && http_exp100_is_selected(data)) {
/* 417 Expectation Failed - try again without the Expect
header */
if(!k->writebytecount && http_exp100_is_waiting(data)) {
@@ -3480,19 +3771,17 @@ static CURLcode http_on_response(struct Curl_easy *data, like to call http2_handle_stream_close to properly close a
stream. In order to do this, we keep reading until we
close the stream. */
- if(0 == k->maxdownload
- && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
- && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
+ if((0 == k->maxdownload) && (k->httpversion_sent < 20))
k->download_done = TRUE;
/* final response without error, prepare to receive the body */
- result = Curl_http_firstwrite(data);
+ result = http_firstwrite(data);
if(!result)
/* This is the last response that we get for the current request.
* Check on the body size and determine if the response is complete.
*/
- result = Curl_http_size(data);
+ result = http_size(data);
out:
if(last_hd) {
@@ -3567,7 +3856,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, p++;
if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
if(ISBLANK(p[2])) {
- k->httpversion = 10 + (p[1] - '0');
+ k->httpversion = (unsigned char)(10 + (p[1] - '0'));
p += 3;
if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
@@ -3587,7 +3876,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, case '3':
if(!ISBLANK(p[1]))
break;
- k->httpversion = (*p - '0') * 10;
+ k->httpversion = (unsigned char)((*p - '0') * 10);
p += 2;
if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
@@ -3645,7 +3934,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, }
if(fine_statusline) {
- result = Curl_http_statusline(data, data->conn);
+ result = http_statusline(data, data->conn);
if(result)
return result;
writetype |= CLIENTWRITE_STATUS;
@@ -3660,7 +3949,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, if(result)
return result;
- result = Curl_http_header(data, hd, hdlen);
+ result = http_header(data, hd, hdlen);
if(result)
return result;
@@ -3717,10 +4006,11 @@ static CURLcode http_parse_headers(struct Curl_easy *data, Curl_dyn_len(&data->state.headerb));
if(st == STATUS_BAD) {
- /* this is not the beginning of a protocol first header line */
+ /* this is not the beginning of a protocol first header line.
+ * Cannot be 0.9 if version was detected or connection was reused. */
k->header = FALSE;
streamclose(conn, "bad HTTP: No end-of-message indicator");
- if(conn->httpversion >= 10) {
+ if((k->httpversion >= 10) || conn->bits.reuse) {
failf(data, "Invalid status line");
return CURLE_WEIRD_SERVER_REPLY;
}
@@ -3755,8 +4045,9 @@ static CURLcode http_parse_headers(struct Curl_easy *data, Curl_dyn_len(&data->state.headerb));
if(st == STATUS_BAD) {
streamclose(conn, "bad HTTP: No end-of-message indicator");
- /* this is not the beginning of a protocol first header line */
- if(conn->httpversion >= 10) {
+ /* this is not the beginning of a protocol first header line.
+ * Cannot be 0.9 if version was detected or connection was reused. */
+ if((k->httpversion >= 10) || conn->bits.reuse) {
failf(data, "Invalid status line");
return CURLE_WEIRD_SERVER_REPLY;
}
@@ -4115,7 +4406,9 @@ struct name_const { size_t namelen;
};
+/* keep them sorted by length! */
static struct name_const H2_NON_FIELD[] = {
+ { STRCONST("TE") },
{ STRCONST("Host") },
{ STRCONST("Upgrade") },
{ STRCONST("Connection") },
@@ -4160,7 +4453,7 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers, infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
}
else {
- scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL) ?
+ scheme = Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ?
"https" : "http";
}
}
@@ -4359,7 +4652,7 @@ static CURLcode http_exp100_add_reader(struct Curl_easy *data) return result;
}
-void Curl_http_exp100_got100(struct Curl_easy *data)
+static void http_exp100_got100(struct Curl_easy *data)
{
struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
if(r)
@@ -4371,7 +4664,7 @@ static bool http_exp100_is_waiting(struct Curl_easy *data) struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
if(r) {
struct cr_exp100_ctx *ctx = r->ctx;
- return (ctx->state == EXP100_AWAITING_CONTINUE);
+ return ctx->state == EXP100_AWAITING_CONTINUE;
}
return FALSE;
}
@@ -4383,7 +4676,7 @@ static void http_exp100_send_anyway(struct Curl_easy *data) http_exp100_continue(data, r);
}
-bool Curl_http_exp100_is_selected(struct Curl_easy *data)
+static bool http_exp100_is_selected(struct Curl_easy *data)
{
struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
return !!r;
diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index c1b02dd992..06cb9ae71e 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -42,6 +42,18 @@ typedef enum { HTTPREQ_HEAD
} Curl_HttpReq;
+
+/* When redirecting transfers. */
+typedef enum {
+ FOLLOW_NONE, /* not used within the function, just a placeholder to
+ allow initing to this */
+ FOLLOW_FAKE, /* only records stuff, not actually following */
+ FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
+ redirect following */
+ FOLLOW_REDIR /* a full true redirect */
+} followtype;
+
+
#ifndef CURL_DISABLE_HTTP
#if defined(USE_HTTP3)
@@ -74,50 +86,14 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, const char *thisheader,
const size_t thislen);
-CURLcode Curl_add_timecondition(struct Curl_easy *data,
-#ifndef USE_HYPER
- struct dynbuf *req
-#else
- void *headers
-#endif
- );
-CURLcode Curl_add_custom_headers(struct Curl_easy *data,
- bool is_connect,
-#ifndef USE_HYPER
- struct dynbuf *req
-#else
- void *headers
-#endif
- );
+CURLcode Curl_add_timecondition(struct Curl_easy *data, struct dynbuf *req);
+CURLcode Curl_add_custom_headers(struct Curl_easy *data, bool is_connect,
+ int httpversion, struct dynbuf *req);
+CURLcode Curl_dynhds_add_custom(struct Curl_easy *data, bool is_connect,
+ struct dynhds *hds);
void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
const char **method, Curl_HttpReq *);
-CURLcode Curl_http_useragent(struct Curl_easy *data);
-CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
-CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
- struct dynbuf *req);
-CURLcode Curl_http_statusline(struct Curl_easy *data,
- struct connectdata *conn);
-CURLcode Curl_http_header(struct Curl_easy *data,
- const char *hd, size_t hdlen);
-CURLcode Curl_transferencode(struct Curl_easy *data);
-CURLcode Curl_http_req_set_reader(struct Curl_easy *data,
- Curl_HttpReq httpreq,
- const char **tep);
-CURLcode Curl_http_req_complete(struct Curl_easy *data,
- struct dynbuf *r, Curl_HttpReq httpreq);
-bool Curl_use_http_1_1plus(const struct Curl_easy *data,
- const struct connectdata *conn);
-#ifndef CURL_DISABLE_COOKIES
-CURLcode Curl_http_cookies(struct Curl_easy *data,
- struct connectdata *conn,
- struct dynbuf *r);
-#else
-#define Curl_http_cookies(a,b,c) CURLE_OK
-#endif
-CURLcode Curl_http_range(struct Curl_easy *data,
- Curl_HttpReq httpreq);
-CURLcode Curl_http_firstwrite(struct Curl_easy *data);
/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http_setup_conn(struct Curl_easy *data,
@@ -139,6 +115,10 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth);
CURLcode Curl_http_auth_act(struct Curl_easy *data);
+/* follow a redirect or not */
+CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
+ followtype type);
+
/* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed
to not having one selected. The other CURLAUTH_* defines are present in the
@@ -175,8 +155,6 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data); version. This count includes CONNECT response headers. */
#define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
-bool Curl_http_exp100_is_selected(struct Curl_easy *data);
-void Curl_http_exp100_got100(struct Curl_easy *data);
#endif /* CURL_DISABLE_HTTP */
@@ -184,8 +162,6 @@ void Curl_http_exp100_got100(struct Curl_easy *data); * HTTP unique setup
***************************************************************************/
-CURLcode Curl_http_size(struct Curl_easy *data);
-
CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
const char *buf, size_t blen,
size_t *pconsumed);
diff --git a/libs/libcurl/src/http1.c b/libs/libcurl/src/http1.c index ac472a4733..8a1278112c 100644 --- a/libs/libcurl/src/http1.c +++ b/libs/libcurl/src/http1.c @@ -167,8 +167,6 @@ static CURLcode start_req(struct h1_req_parser *parser, if(!target_len || !hv_len)
goto out;
- /* TODO: we do not check HTTP_VERSION for conformity, should
- + do that when STRICT option is supplied. */
(void)hv;
/* The TARGET can be (rfc 9112, ch. 3.2):
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index c5f10c678b..7b88aa7a83 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -198,7 +198,6 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, * All about the H2 internals of a stream
*/
struct h2_stream_ctx {
- struct bufq recvbuf; /* response buffer */
struct bufq sendbuf; /* request buffer */
struct h1_req_parser h1; /* parsing the request */
struct dynhds resp_trailers; /* response trailer fields */
@@ -240,7 +239,6 @@ static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx) H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
- stream->resp_hds_len = 0;
stream->bodystarted = FALSE;
stream->status_code = -1;
stream->closed = FALSE;
@@ -2057,23 +2055,10 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, }
if(nread > 0) {
- size_t data_consumed = (size_t)nread;
/* Now that we transferred this to the upper layer, we report
* the actual amount of DATA consumed to the H2 session, so
* that it adjusts stream flow control */
- if(stream->resp_hds_len >= data_consumed) {
- stream->resp_hds_len -= data_consumed; /* no DATA */
- }
- else {
- if(stream->resp_hds_len) {
- data_consumed -= stream->resp_hds_len;
- stream->resp_hds_len = 0;
- }
- if(data_consumed) {
- nghttp2_session_consume(ctx->h2, stream->id, data_consumed);
- }
- }
-
+ nghttp2_session_consume(ctx->h2, stream->id, (size_t)nread);
if(stream->closed) {
CURL_TRC_CF(data, cf, "[%d] DRAIN closed stream", stream->id);
drain_stream(cf, data, stream);
@@ -2337,7 +2322,7 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(should_close_session(ctx)) {
/* nghttp2 thinks this session is done. If the stream has not been
* closed, this is an error state for out transfer */
- if(stream->closed) {
+ if(stream && stream->closed) {
nwritten = http2_handle_stream_close(cf, data, stream, err);
}
else {
@@ -2496,9 +2481,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf, /* Send out our SETTINGS and ACKs and such. If that blocks, we
* have it buffered and can count this filter as being connected */
result = h2_progress_egress(cf, data);
- if(result == CURLE_AGAIN)
- result = CURLE_OK;
- else if(result)
+ if(result && (result != CURLE_AGAIN))
goto out;
*done = TRUE;
@@ -2638,9 +2621,6 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf, case CF_CTRL_FLUSH:
result = cf_h2_flush(cf, data);
break;
- case CF_CTRL_DATA_DETACH:
- http2_data_done(cf, data);
- break;
case CF_CTRL_DATA_DONE:
http2_data_done(cf, data);
break;
@@ -2655,10 +2635,8 @@ static bool cf_h2_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct cf_h2_ctx *ctx = cf->ctx;
- struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
- if(ctx && (!Curl_bufq_is_empty(&ctx->inbufq)
- || (stream && !Curl_bufq_is_empty(&stream->sendbuf))))
+ if(ctx && !Curl_bufq_is_empty(&ctx->inbufq))
return TRUE;
return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
@@ -2728,6 +2706,9 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf, }
break;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 20;
+ return CURLE_OK;
default:
break;
}
@@ -2738,7 +2719,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_nghttp2 = {
"HTTP/2",
- CF_TYPE_MULTIPLEX,
+ CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
CURL_LOG_LVL_NONE,
cf_h2_destroy,
cf_h2_connect,
@@ -2812,35 +2793,12 @@ out: return result;
}
-static bool cf_is_http2(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
-{
- (void)data;
- for(; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_nghttp2)
- return TRUE;
- if(cf->cft->flags & CF_TYPE_IP_CONNECT)
- return FALSE;
- }
- return FALSE;
-}
-
-bool Curl_conn_is_http2(const struct Curl_easy *data,
- const struct connectdata *conn,
- int sockindex)
-{
- return conn ? cf_is_http2(conn->cfilter[sockindex], data) : FALSE;
-}
-
-bool Curl_http2_may_switch(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+bool Curl_http2_may_switch(struct Curl_easy *data)
{
- (void)sockindex;
- if(!Curl_conn_is_http2(data, conn, sockindex) &&
+ if(Curl_conn_http_version(data) < 20 &&
data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ if(data->conn->bits.httpproxy && !data->conn->bits.tunnel_proxy) {
/* We do not support HTTP/2 proxies yet. Also it is debatable
whether or not this setting should apply to HTTP/2 proxies. */
infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
@@ -2852,21 +2810,19 @@ bool Curl_http2_may_switch(struct Curl_easy *data, return FALSE;
}
-CURLcode Curl_http2_switch(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+CURLcode Curl_http2_switch(struct Curl_easy *data)
{
struct Curl_cfilter *cf;
CURLcode result;
- DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
+ DEBUGASSERT(Curl_conn_http_version(data) < 20);
- result = http2_cfilter_add(&cf, data, conn, sockindex, FALSE);
+ result = http2_cfilter_add(&cf, data, data->conn, FIRSTSOCKET, FALSE);
if(result)
return result;
CURL_TRC_CF(data, cf, "switching connection to HTTP/2");
- conn->httpversion = 20; /* we know we are on HTTP/2 now */
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ data->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
Curl_multi_connchanged(data->multi);
if(cf->next) {
@@ -2881,14 +2837,13 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data) struct Curl_cfilter *cf_h2;
CURLcode result;
- DEBUGASSERT(!cf_is_http2(cf, data));
+ DEBUGASSERT(Curl_conn_http_version(data) < 20);
result = http2_cfilter_insert_after(cf, data, FALSE);
if(result)
return result;
cf_h2 = cf->next;
- cf->conn->httpversion = 20; /* we know we are on HTTP/2 now */
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
Curl_multi_connchanged(data->multi);
@@ -2907,7 +2862,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data, struct cf_h2_ctx *ctx;
CURLcode result;
- DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
+ DEBUGASSERT(Curl_conn_http_version(data) < 20);
DEBUGASSERT(data->req.upgr101 == UPGR101_RECEIVED);
result = http2_cfilter_add(&cf, data, conn, sockindex, TRUE);
@@ -2940,7 +2895,6 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data, " after upgrade: len=%zu", nread);
}
- conn->httpversion = 20; /* we know we are on HTTP/2 now */
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
Curl_multi_connchanged(data->multi);
@@ -2955,9 +2909,9 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data, CURLE_HTTP2_STREAM error! */
bool Curl_h2_http_1_1_error(struct Curl_easy *data)
{
- if(Curl_conn_is_http2(data, data->conn, FIRSTSOCKET)) {
+ if(Curl_conn_http_version(data) == 20) {
int err = Curl_conn_get_stream_error(data, data->conn, FIRSTSOCKET);
- return (err == NGHTTP2_HTTP_1_1_REQUIRED);
+ return err == NGHTTP2_HTTP_1_1_REQUIRED;
}
return FALSE;
}
diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h index b67a7e170d..f7da3c43e3 100644 --- a/libs/libcurl/src/http2.h +++ b/libs/libcurl/src/http2.h @@ -44,15 +44,9 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
bool Curl_h2_http_1_1_error(struct Curl_easy *data);
-bool Curl_conn_is_http2(const struct Curl_easy *data,
- const struct connectdata *conn,
- int sockindex);
-bool Curl_http2_may_switch(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex);
+bool Curl_http2_may_switch(struct Curl_easy *data);
-CURLcode Curl_http2_switch(struct Curl_easy *data,
- struct connectdata *conn, int sockindex);
+CURLcode Curl_http2_switch(struct Curl_easy *data);
CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data);
@@ -69,12 +63,10 @@ extern struct Curl_cftype Curl_cft_nghttp2; #else /* USE_NGHTTP2 */
-#define Curl_cf_is_http2(a,b) FALSE
-#define Curl_conn_is_http2(a,b,c) FALSE
-#define Curl_http2_may_switch(a,b,c) FALSE
+#define Curl_http2_may_switch(a) FALSE
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_switch(a,b,c) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_switch(a) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_upgrade(a,b,c,d,e) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_h2_http_1_1_error(x) 0
#endif
diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c index 007c355642..3c2f67de8b 100644 --- a/libs/libcurl/src/http_aws_sigv4.c +++ b/libs/libcurl/src/http_aws_sigv4.c @@ -35,6 +35,7 @@ #include "parsedate.h"
#include "sendf.h"
#include "escape.h"
+#include "strparse.h"
#include <time.h>
@@ -118,8 +119,6 @@ static void trim_headers(struct curl_slist *head) /* maximum length for the aws sivg4 parts */
#define MAX_SIGV4_LEN 64
-#define MAX_SIGV4_LEN_TXT "64"
-
#define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date"))
/* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
@@ -160,7 +159,8 @@ static int compare_header_names(const char *a, const char *b) static CURLcode make_headers(struct Curl_easy *data,
const char *hostname,
char *timestamp,
- char *provider1,
+ const char *provider1,
+ size_t plen, /* length of provider1 */
char **date_header,
char *content_sha256_header,
struct dynbuf *canonical_headers,
@@ -174,16 +174,16 @@ static CURLcode make_headers(struct Curl_easy *data, struct curl_slist *l;
bool again = TRUE;
- /* provider1 mid */
- Curl_strntolower(provider1, provider1, strlen(provider1));
- provider1[0] = Curl_raw_toupper(provider1[0]);
-
- msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%s-Date", provider1);
+ msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%.*s-Date",
+ (int)plen, provider1);
+ /* provider1 ucfirst */
+ Curl_strntolower(&date_hdr_key[2], provider1, plen);
+ date_hdr_key[2] = Curl_raw_toupper(provider1[0]);
- /* provider1 lowercase */
- Curl_strntolower(provider1, provider1, 1); /* first byte only */
msnprintf(date_full_hdr, DATE_FULL_HDR_LEN,
- "x-%s-date:%s", provider1, timestamp);
+ "x-%.*s-date:%s", (int)plen, provider1, timestamp);
+ /* provider1 lowercase */
+ Curl_strntolower(&date_full_hdr[2], provider1, plen);
if(!Curl_checkheaders(data, STRCONST("Host"))) {
char *fullhost;
@@ -336,6 +336,7 @@ fail: /* try to parse a payload hash from the content-sha256 header */
static char *parse_content_sha_hdr(struct Curl_easy *data,
const char *provider1,
+ size_t plen,
size_t *value_len)
{
char key[CONTENT_SHA256_KEY_LEN];
@@ -343,7 +344,8 @@ static char *parse_content_sha_hdr(struct Curl_easy *data, char *value;
size_t len;
- key_len = msnprintf(key, sizeof(key), "x-%s-content-sha256", provider1);
+ key_len = msnprintf(key, sizeof(key), "x-%.*s-content-sha256",
+ (int)plen, provider1);
value = Curl_checkheaders(data, key, key_len);
if(!value)
@@ -389,6 +391,7 @@ static CURLcode calc_payload_hash(struct Curl_easy *data, static CURLcode calc_s3_payload_hash(struct Curl_easy *data,
Curl_HttpReq httpreq, char *provider1,
+ size_t plen,
unsigned char *sha_hash,
char *sha_hex, char *header)
{
@@ -415,7 +418,7 @@ static CURLcode calc_s3_payload_hash(struct Curl_easy *data, /* format the required content-sha256 header */
msnprintf(header, CONTENT_SHA256_HDR_LEN,
- "x-%s-content-sha256: %s", provider1, sha_hex);
+ "x-%.*s-content-sha256: %s", (int)plen, provider1, sha_hex);
ret = CURLE_OK;
fail:
@@ -432,6 +435,8 @@ static int compare_func(const void *a, const void *b) const struct pair *aa = a;
const struct pair *bb = b;
/* If one element is empty, the other is always sorted higher */
+ if(aa->len == 0 && bb->len == 0)
+ return 0;
if(aa->len == 0)
return -1;
if(bb->len == 0)
@@ -571,12 +576,11 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) CURLcode result = CURLE_OUT_OF_MEMORY;
struct connectdata *conn = data->conn;
size_t len;
- const char *arg;
- char provider0[MAX_SIGV4_LEN + 1]="";
- char provider1[MAX_SIGV4_LEN + 1]="";
- char region[MAX_SIGV4_LEN + 1]="";
- char service[MAX_SIGV4_LEN + 1]="";
- bool sign_as_s3 = FALSE;
+ char *line;
+ struct Curl_str provider0;
+ struct Curl_str provider1;
+ struct Curl_str region = { NULL, 0};
+ struct Curl_str service = { NULL, 0};
const char *hostname = conn->host.name;
time_t clock;
struct tm tm;
@@ -625,27 +629,31 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) * AWS is the default because most of non-amazon providers
* are still using aws:amz as a prefix.
*/
- arg = data->set.str[STRING_AWS_SIGV4] ?
- data->set.str[STRING_AWS_SIGV4] : "aws:amz";
+ line = data->set.str[STRING_AWS_SIGV4] ?
+ data->set.str[STRING_AWS_SIGV4] : (char *)"aws:amz";
- /* provider1[:provider2[:region[:service]]]
+ /* provider0[:provider1[:region[:service]]]
No string can be longer than N bytes of non-whitespace
*/
- (void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
- ":%" MAX_SIGV4_LEN_TXT "[^:]"
- ":%" MAX_SIGV4_LEN_TXT "[^:]"
- ":%" MAX_SIGV4_LEN_TXT "s",
- provider0, provider1, region, service);
- if(!provider0[0]) {
+ if(Curl_str_until(&line, &provider0, MAX_SIGV4_LEN, ':')) {
failf(data, "first aws-sigv4 provider cannot be empty");
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
- else if(!provider1[0])
- strcpy(provider1, provider0);
+ if(Curl_str_single(&line, ':') ||
+ Curl_str_until(&line, &provider1, MAX_SIGV4_LEN, ':')) {
+ provider1.str = provider0.str;
+ provider1.len = provider0.len;
+ }
+ else if(Curl_str_single(&line, ':') ||
+ Curl_str_until(&line, ®ion, MAX_SIGV4_LEN, ':') ||
+ Curl_str_single(&line, ':') ||
+ Curl_str_until(&line, &service, MAX_SIGV4_LEN, ':')) {
+ /* nothing to do */
+ }
- if(!service[0]) {
+ if(!service.len) {
char *hostdot = strchr(hostname, '.');
if(!hostdot) {
failf(data, "aws-sigv4: service missing in parameters and hostname");
@@ -658,12 +666,13 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) result = CURLE_URL_MALFORMAT;
goto fail;
}
- memcpy(service, hostname, len);
- service[len] = '\0';
+ service.str = (char *)hostname;
+ service.len = len;
- infof(data, "aws_sigv4: picked service %s from host", service);
+ infof(data, "aws_sigv4: picked service %.*s from host",
+ (int)service.len, service.str);
- if(!region[0]) {
+ if(!region.len) {
const char *reg = hostdot + 1;
const char *hostreg = strchr(reg, '.');
if(!hostreg) {
@@ -677,25 +686,29 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) result = CURLE_URL_MALFORMAT;
goto fail;
}
- memcpy(region, reg, len);
- region[len] = '\0';
- infof(data, "aws_sigv4: picked region %s from host", region);
+ region.str = (char *)reg;
+ region.len = len;
+ infof(data, "aws_sigv4: picked region %.*s from host",
+ (int)region.len, region.str);
}
}
Curl_http_method(data, conn, &method, &httpreq);
- /* AWS S3 requires a x-amz-content-sha256 header, and supports special
- * values like UNSIGNED-PAYLOAD */
- sign_as_s3 = (strcasecompare(provider0, "aws") &&
- strcasecompare(service, "s3"));
-
- payload_hash = parse_content_sha_hdr(data, provider1, &payload_hash_len);
+ payload_hash = parse_content_sha_hdr(data, provider1.str, provider1.len,
+ &payload_hash_len);
if(!payload_hash) {
+ /* AWS S3 requires a x-amz-content-sha256 header, and supports special
+ * values like UNSIGNED-PAYLOAD */
+ bool sign_as_s3 = ((provider0.len == 3) &&
+ strncasecompare(provider0.str, "aws", 3)) &&
+ ((service.len == 2) && strncasecompare(service.str, "s3", 2));
+
if(sign_as_s3)
- result = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
- sha_hex, content_sha256_hdr);
+ result = calc_s3_payload_hash(data, httpreq,
+ provider1.str, provider1.len,
+ sha_hash, sha_hex, content_sha256_hdr);
else
result = calc_payload_hash(data, sha_hash, sha_hex);
if(result)
@@ -726,7 +739,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) goto fail;
}
- result = make_headers(data, hostname, timestamp, provider1,
+ result = make_headers(data, hostname, timestamp,
+ provider1.str, provider1.len,
&date_header, content_sha256_hdr,
&canonical_headers, &signed_headers);
if(result)
@@ -771,14 +785,18 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) DEBUGF(infof(data, "Canonical request: %s", canonical_request));
- /* provider 0 lowercase */
- Curl_strntolower(provider0, provider0, strlen(provider0));
- request_type = aprintf("%s4_request", provider0);
+ request_type = aprintf("%.*s4_request", (int)provider0.len, provider0.str);
if(!request_type)
goto fail;
- credential_scope = aprintf("%s/%s/%s/%s",
- date, region, service, request_type);
+ /* provider0 is lowercased *after* aprintf() so that the buffer can be
+ written to */
+ Curl_strntolower(request_type, request_type, provider0.len);
+
+ credential_scope = aprintf("%s/%.*s/%.*s/%s",
+ date, (int)region.len, region.str,
+ (int)service.len, service.str,
+ request_type);
if(!credential_scope)
goto fail;
@@ -788,42 +806,41 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) sha256_to_hex(sha_hex, sha_hash);
- /* provider 0 uppercase */
- Curl_strntoupper(provider0, provider0, strlen(provider0));
-
/*
* Google allows using RSA key instead of HMAC, so this code might change
* in the future. For now we only support HMAC.
*/
- str_to_sign = aprintf("%s4-HMAC-SHA256\n" /* Algorithm */
+ str_to_sign = aprintf("%.*s4-HMAC-SHA256\n" /* Algorithm */
"%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */
- provider0,
+ (int)provider0.len, provider0.str,
timestamp,
credential_scope,
sha_hex);
- if(!str_to_sign) {
+ if(!str_to_sign)
goto fail;
- }
- /* provider 0 uppercase */
- secret = aprintf("%s4%s", provider0,
+ /* make provider0 part done uppercase */
+ Curl_strntoupper(str_to_sign, provider0.str, provider0.len);
+
+ secret = aprintf("%.*s4%s", (int)provider0.len, provider0.str,
data->state.aptr.passwd ?
data->state.aptr.passwd : "");
if(!secret)
goto fail;
+ /* make provider0 part done uppercase */
+ Curl_strntoupper(secret, provider0.str, provider0.len);
HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
- HMAC_SHA256(sign0, sizeof(sign0), region, strlen(region), sign1);
- HMAC_SHA256(sign1, sizeof(sign1), service, strlen(service), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), region.str, region.len, sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), service.str, service.len, sign0);
HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
sha256_to_hex(sha_hex, sign0);
- /* provider 0 uppercase */
- auth_headers = aprintf("Authorization: %s4-HMAC-SHA256 "
+ auth_headers = aprintf("Authorization: %.*s4-HMAC-SHA256 "
"Credential=%s/%s, "
"SignedHeaders=%s, "
"Signature=%s\r\n"
@@ -834,7 +851,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) */
"%s"
"%s", /* optional sha256 header includes \r\n */
- provider0,
+ (int)provider0.len, provider0.str,
user,
credential_scope,
Curl_dyn_ptr(&signed_headers),
@@ -844,6 +861,9 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) if(!auth_headers) {
goto fail;
}
+ /* provider 0 uppercase */
+ Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1],
+ provider0.str, provider0.len);
Curl_safefree(data->state.aptr.userpwd);
data->state.aptr.userpwd = auth_headers;
diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c index d8b44abdd1..a7a98533b3 100644 --- a/libs/libcurl/src/http_negotiate.c +++ b/libs/libcurl/src/http_negotiate.c @@ -27,6 +27,7 @@ #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
#include "urldata.h"
+#include "cfilters.h"
#include "sendf.h"
#include "http_negotiate.h"
#include "vauth/vauth.h"
@@ -109,7 +110,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, #endif
/* Check if the connection is using SSL and get the channel binding data */
#if defined(USE_SSL) && defined(HAVE_GSSAPI)
- if(conn->handler->flags & PROTOPT_SSL) {
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
result = Curl_ssl_get_channel_binding(
data, FIRSTSOCKET, &neg_ctx->channel_binding_data);
diff --git a/libs/libcurl/src/http_ntlm.c b/libs/libcurl/src/http_ntlm.c index 03788062ff..0dee7594c2 100644 --- a/libs/libcurl/src/http_ntlm.c +++ b/libs/libcurl/src/http_ntlm.c @@ -252,6 +252,12 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) break;
case NTLMSTATE_LAST:
+ /* since this is a little artificial in that this is used without any
+ outgoing auth headers being set, we need to set the bit by force */
+ if(proxy)
+ data->info.proxyauthpicked = CURLAUTH_NTLM;
+ else
+ data->info.httpauthpicked = CURLAUTH_NTLM;
Curl_safefree(*allocuserpwd);
authp->done = TRUE;
break;
diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c index 684bd738b6..892ac56449 100644 --- a/libs/libcurl/src/http_proxy.c +++ b/libs/libcurl/src/http_proxy.c @@ -29,9 +29,6 @@ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
#include <curl/curl.h>
-#ifdef USE_HYPER
-#include <hyper.h>
-#endif
#include "sendf.h"
#include "http.h"
#include "url.h"
@@ -59,7 +56,7 @@ static bool hd_name_eq(const char *n1, size_t n1len, }
static CURLcode dynhds_add_custom(struct Curl_easy *data,
- bool is_connect,
+ bool is_connect, int httpversion,
struct dynhds *hds)
{
struct connectdata *conn = data->conn;
@@ -172,9 +169,9 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data, Connection: */
hd_name_eq(name, namelen, STRCONST("Connection:")))
;
- else if((conn->httpversion >= 20) &&
+ else if((httpversion >= 20) &&
hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:")))
- /* HTTP/2 does not support chunked requests */
+ /* HTTP/2 and HTTP/3 do not support chunked requests */
;
else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) ||
hd_name_eq(name, namelen, STRCONST("Cookie:"))) &&
@@ -224,11 +221,18 @@ CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, return CURLE_OK;
}
+struct cf_proxy_ctx {
+ /* the protocol specific sub-filter we install during connect */
+ struct Curl_cfilter *cf_protocol;
+ int httpversion; /* HTTP version used to CONNECT */
+};
+
CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
struct Curl_cfilter *cf,
struct Curl_easy *data,
int http_version_major)
{
+ struct cf_proxy_ctx *ctx = cf->ctx;
const char *hostname = NULL;
char *authority = NULL;
int port;
@@ -289,7 +293,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, goto out;
}
- result = dynhds_add_custom(data, TRUE, &req->headers);
+ result = dynhds_add_custom(data, TRUE, ctx->httpversion, &req->headers);
out:
if(result && req) {
@@ -301,12 +305,6 @@ out: return result;
}
-
-struct cf_proxy_ctx {
- /* the protocol specific sub-filter we install during connect */
- struct Curl_cfilter *cf_protocol;
-};
-
static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
@@ -328,6 +326,7 @@ connect_sub: *done = FALSE;
if(!ctx->cf_protocol) {
struct Curl_cfilter *cf_protocol = NULL;
+ int httpversion = 0;
int alpn = Curl_conn_cf_is_ssl(cf->next) ?
cf->conn->proxy_alpn : CURL_HTTP_VERSION_1_1;
@@ -343,6 +342,7 @@ connect_sub: if(result)
goto out;
cf_protocol = cf->next;
+ httpversion = (alpn == CURL_HTTP_VERSION_1_0) ? 10 : 11;
break;
#ifdef USE_NGHTTP2
case CURL_HTTP_VERSION_2:
@@ -352,6 +352,7 @@ connect_sub: if(result)
goto out;
cf_protocol = cf->next;
+ httpversion = 20;
break;
#endif
default:
@@ -361,6 +362,7 @@ connect_sub: }
ctx->cf_protocol = cf_protocol;
+ ctx->httpversion = httpversion;
/* after we installed the filter "below" us, we call connect
* on out sub-chain again.
*/
diff --git a/libs/libcurl/src/httpsrr.c b/libs/libcurl/src/httpsrr.c new file mode 100644 index 0000000000..7c50536cc5 --- /dev/null +++ b/libs/libcurl/src/httpsrr.c @@ -0,0 +1,167 @@ +/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_HTTPSRR
+
+#include "urldata.h"
+#include "curl_addrinfo.h"
+#include "httpsrr.h"
+#include "connect.h"
+#include "sendf.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
+ unsigned char *alpns)
+{
+ /*
+ * spec here is as per RFC 9460, section-7.1.1
+ * encoding is a concatenated list of strings each preceded by a one
+ * octet length
+ * output is comma-sep list of the strings
+ * implementations may or may not handle quoting of comma within
+ * string values, so we might see a comma within the wire format
+ * version of a string, in which case we will precede that by a
+ * backslash - same goes for a backslash character, and of course
+ * we need to use two backslashes in strings when we mean one;-)
+ */
+ struct dynbuf dval;
+ int idnum = 0;
+
+ Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
+ while(len > 0) {
+ size_t tlen = (size_t) *cp++;
+ size_t i;
+ enum alpnid id;
+ len--;
+ if(tlen > len)
+ goto err;
+ /* add escape char if needed, clunky but easier to read */
+ for(i = 0; i != tlen; i++) {
+ if('\\' == *cp || ',' == *cp) {
+ if(Curl_dyn_addn(&dval, "\\", 1))
+ goto err;
+ }
+ if(Curl_dyn_addn(&dval, cp++, 1))
+ goto err;
+ }
+ len -= tlen;
+
+ /* we only store ALPN ids we know about */
+ id = Curl_alpn2alpnid(Curl_dyn_ptr(&dval), Curl_dyn_len(&dval));
+ if(id != ALPN_none) {
+ if(idnum == MAX_HTTPSRR_ALPNS)
+ break;
+ alpns[idnum++] = (unsigned char)id;
+ }
+ Curl_dyn_reset(&dval);
+ }
+ Curl_dyn_free(&dval);
+ if(idnum < MAX_HTTPSRR_ALPNS)
+ alpns[idnum] = ALPN_none; /* terminate the list */
+ return CURLE_OK;
+err:
+ Curl_dyn_free(&dval);
+ return CURLE_BAD_CONTENT_ENCODING;
+}
+
+#ifdef USE_ARES
+
+static void httpsrr_opt(struct Curl_easy *data,
+ const ares_dns_rr_t *rr,
+ ares_dns_rr_key_t key, size_t idx)
+{
+ size_t len = 0;
+ const unsigned char *val = NULL;
+ unsigned short code;
+ struct thread_data *res = data->state.async.tdata;
+ struct Curl_https_rrinfo *hi = &res->hinfo;
+ code = ares_dns_rr_get_opt(rr, key, idx, &val, &len);
+
+ switch(code) {
+ case HTTPS_RR_CODE_ALPN: /* str_list */
+ Curl_httpsrr_decode_alpn(val, len, hi->alpns);
+ infof(data, "HTTPS RR ALPN: %u %u %u %u",
+ hi->alpns[0], hi->alpns[1], hi->alpns[2], hi->alpns[3]);
+ break;
+ case HTTPS_RR_CODE_NO_DEF_ALPN:
+ infof(data, "HTTPS RR no-def-alpn");
+ break;
+ case HTTPS_RR_CODE_IPV4: /* addr4 list */
+ infof(data, "HTTPS RR IPv4");
+ break;
+ case HTTPS_RR_CODE_ECH:
+ infof(data, "HTTPS RR ECH");
+ break;
+ case HTTPS_RR_CODE_IPV6: /* addr6 list */
+ infof(data, "HTTPS RR IPv6");
+ break;
+ case HTTPS_RR_CODE_PORT:
+ infof(data, "HTTPS RR port");
+ break;
+ default:
+ infof(data, "HTTPS RR unknown code");
+ break;
+ }
+}
+
+void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
+ size_t timeouts,
+ const ares_dns_record_t *dnsrec)
+{
+ struct Curl_easy *data = arg;
+ size_t i;
+#ifdef CURLRES_ARES
+ struct thread_data *res = data->state.async.tdata;
+
+ res->num_pending--;
+#endif
+ (void)timeouts;
+ if((ARES_SUCCESS != status) || !dnsrec)
+ return;
+
+ for(i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
+ size_t opt;
+ const ares_dns_rr_t *rr =
+ ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
+ if(ares_dns_rr_get_type(rr) != ARES_REC_TYPE_HTTPS)
+ continue;
+ /* When SvcPriority is 0, the SVCB record is in AliasMode. Otherwise, it
+ is in ServiceMode */
+ infof(data, "HTTPS RR priority: %u",
+ ares_dns_rr_get_u16(rr, ARES_RR_HTTPS_PRIORITY));
+ for(opt = 0; opt < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS);
+ opt++)
+ httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt);
+ }
+}
+
+#endif /* USE_ARES */
+
+#endif /* USE_HTTPSRR */
diff --git a/libs/libcurl/src/httpsrr.h b/libs/libcurl/src/httpsrr.h new file mode 100644 index 0000000000..a734c9ed6d --- /dev/null +++ b/libs/libcurl/src/httpsrr.h @@ -0,0 +1,76 @@ +#ifndef HEADER_CURL_HTTPSRR_H
+#define HEADER_CURL_HTTPSRR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_ARES
+#include <ares.h>
+#endif
+
+#ifdef USE_HTTPSRR
+
+#define CURL_MAXLEN_host_name 253
+#define MAX_HTTPSRR_ALPNS 4
+
+struct Curl_https_rrinfo {
+ /*
+ * Fields from HTTPS RR. The only mandatory fields are priority and target.
+ * See https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
+ */
+ char *target;
+ unsigned char *ipv4hints; /* keytag = 4 */
+ size_t ipv4hints_len;
+ unsigned char *echconfiglist; /* keytag = 5 */
+ size_t echconfiglist_len;
+ unsigned char *ipv6hints; /* keytag = 6 */
+ size_t ipv6hints_len;
+ unsigned char alpns[MAX_HTTPSRR_ALPNS]; /* keytag = 1 */
+ /* store parsed alpnid entries in the array, end with ALPN_none */
+ int port; /* -1 means not set */
+ uint16_t priority;
+ bool no_def_alpn; /* keytag = 2 */
+};
+#endif
+
+/*
+ * Code points for DNS wire format SvcParams as per RFC 9460
+ */
+#define HTTPS_RR_CODE_ALPN 0x01
+#define HTTPS_RR_CODE_NO_DEF_ALPN 0x02
+#define HTTPS_RR_CODE_PORT 0x03
+#define HTTPS_RR_CODE_IPV4 0x04
+#define HTTPS_RR_CODE_ECH 0x05
+#define HTTPS_RR_CODE_IPV6 0x06
+
+CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
+ unsigned char *alpns);
+
+#if defined(USE_ARES) && defined(USE_HTTPSRR)
+void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
+ size_t timeouts,
+ const ares_dns_record_t *dnsrec);
+#endif
+#endif /* HEADER_CURL_HTTPSRR_H */
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index c36a1a1974..2ba0a10f25 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -134,6 +134,7 @@ const struct Curl_handler Curl_handler_imap = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
CURLPROTO_IMAP, /* family */
@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
CURLPROTO_IMAP, /* family */
@@ -191,19 +193,6 @@ static const struct SASLproto saslimap = { };
-#ifdef USE_SSL
-static void imap_to_imaps(struct connectdata *conn)
-{
- /* Change the connection handler */
- conn->handler = &Curl_handler_imaps;
-
- /* Set the connection's upgraded to TLS flag */
- conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define imap_to_imaps(x) Curl_nop_stmt
-#endif
-
/***********************************************************************
*
* imap_matchresp()
@@ -472,6 +461,7 @@ static CURLcode imap_perform_starttls(struct Curl_easy *data) static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
struct connectdata *conn)
{
+#ifdef USE_SSL
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
CURLcode result;
@@ -481,21 +471,27 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
+ /* Change the connection handler */
+ conn->handler = &Curl_handler_imaps;
+ conn->bits.tls_upgraded = TRUE;
}
+ DEBUGASSERT(!imapc->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
- if(!result) {
+ DEBUGF(infof(data, "imap_perform_upgrade_tls, connect -> %d, %d",
+ result, ssldone));
+ if(!result && ssldone) {
imapc->ssldone = ssldone;
- if(imapc->state != IMAP_UPGRADETLS)
- imap_state(data, IMAP_UPGRADETLS);
-
- if(imapc->ssldone) {
- imap_to_imaps(conn);
- result = imap_perform_capability(data, conn);
- }
+ /* perform CAPA now, changes imapc->state out of IMAP_UPGRADETLS */
+ result = imap_perform_capability(data, conn);
}
out:
return result;
+#else
+ (void)data;
+ (void)conn;
+ return CURLE_NOT_BUILT_IN;
+#endif
}
/***********************************************************************
@@ -996,7 +992,7 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data, result = imap_perform_authentication(data, conn);
}
else
- result = imap_perform_upgrade_tls(data, conn);
+ imap_state(data, IMAP_UPGRADETLS);
return result;
}
@@ -1305,8 +1301,12 @@ static CURLcode imap_statemachine(struct Curl_easy *data, (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
- if(imapc->state == IMAP_UPGRADETLS)
- return imap_perform_upgrade_tls(data, conn);
+upgrade_tls:
+ if(imapc->state == IMAP_UPGRADETLS) {
+ result = imap_perform_upgrade_tls(data, conn);
+ if(result || (imapc->state == IMAP_UPGRADETLS))
+ return result;
+ }
/* Flush any data that needs to be sent */
if(pp->sendleft)
@@ -1337,6 +1337,10 @@ static CURLcode imap_statemachine(struct Curl_easy *data, case IMAP_STARTTLS:
result = imap_state_starttls_resp(data, imapcode, imapc->state);
+ /* During UPGRADETLS, leave the read loop as we need to connect
+ * (e.g. TLS handshake) before we continue sending/receiving. */
+ if(!result && (imapc->state == IMAP_UPGRADETLS))
+ goto upgrade_tls;
break;
case IMAP_AUTHENTICATE:
@@ -1390,14 +1394,6 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
- if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
- bool ssldone = FALSE;
- result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
- imapc->ssldone = ssldone;
- if(result || !ssldone)
- return result;
- }
-
result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
*done = (imapc->state == IMAP_STOP);
diff --git a/libs/libcurl/src/inet_ntop.c b/libs/libcurl/src/inet_ntop.c index ff318d1a25..b2991f82de 100644 --- a/libs/libcurl/src/inet_ntop.c +++ b/libs/libcurl/src/inet_ntop.c @@ -75,7 +75,7 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) len = strlen(tmp);
if(len == 0 || len >= size) {
errno = ENOSPC;
- return (NULL);
+ return NULL;
}
strcpy(dst, tmp);
return dst;
@@ -154,7 +154,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
errno = ENOSPC;
- return (NULL);
+ return NULL;
}
tp += strlen(tp);
break;
@@ -172,7 +172,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) */
if((size_t)(tp - tmp) > size) {
errno = ENOSPC;
- return (NULL);
+ return NULL;
}
strcpy(dst, tmp);
return dst;
diff --git a/libs/libcurl/src/inet_ntop.h b/libs/libcurl/src/inet_ntop.h index e2c3b4b5ac..63c0a97424 100644 --- a/libs/libcurl/src/inet_ntop.h +++ b/libs/libcurl/src/inet_ntop.h @@ -29,12 +29,25 @@ char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#ifdef HAVE_INET_NTOP
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef _WIN32
+#if defined(_MSC_VER) && (_MSC_VER <= 1900)
+#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af, (void *)addr, buf, size)
+#else
+#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af, addr, buf, size)
+#endif
+#elif defined(__AMIGA__)
#define Curl_inet_ntop(af,addr,buf,size) \
- inet_ntop(af, addr, buf, size)
+ (char *)inet_ntop(af, (void *)addr, (unsigned char *)buf, \
+ (curl_socklen_t)(size))
#else
#define Curl_inet_ntop(af,addr,buf,size) \
inet_ntop(af, addr, buf, (curl_socklen_t)(size))
diff --git a/libs/libcurl/src/inet_pton.c b/libs/libcurl/src/inet_pton.c index cf0027648a..1a0259864a 100644 --- a/libs/libcurl/src/inet_pton.c +++ b/libs/libcurl/src/inet_pton.c @@ -76,12 +76,12 @@ Curl_inet_pton(int af, const char *src, void *dst) {
switch(af) {
case AF_INET:
- return (inet_pton4(src, (unsigned char *)dst));
+ return inet_pton4(src, (unsigned char *)dst);
case AF_INET6:
- return (inet_pton6(src, (unsigned char *)dst));
+ return inet_pton6(src, (unsigned char *)dst);
default:
errno = EAFNOSUPPORT;
- return (-1);
+ return -1;
}
/* NOTREACHED */
}
@@ -116,29 +116,29 @@ inet_pton4(const char *src, unsigned char *dst) (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
- return (0);
+ return 0;
if(val > 255)
- return (0);
+ return 0;
*tp = (unsigned char)val;
if(!saw_digit) {
if(++octets > 4)
- return (0);
+ return 0;
saw_digit = 1;
}
}
else if(ch == '.' && saw_digit) {
if(octets == 4)
- return (0);
+ return 0;
*++tp = 0;
saw_digit = 0;
}
else
- return (0);
+ return 0;
}
if(octets < 4)
- return (0);
+ return 0;
memcpy(dst, tmp, INADDRSZ);
- return (1);
+ return 1;
}
/* int
@@ -170,7 +170,7 @@ inet_pton6(const char *src, unsigned char *dst) /* Leading :: requires some special handling. */
if(*src == ':')
if(*++src != ':')
- return (0);
+ return 0;
curtok = src;
saw_xdigit = 0;
val = 0;
@@ -185,19 +185,19 @@ inet_pton6(const char *src, unsigned char *dst) val <<= 4;
val |= (pch - xdigits);
if(++saw_xdigit > 4)
- return (0);
+ return 0;
continue;
}
if(ch == ':') {
curtok = src;
if(!saw_xdigit) {
if(colonp)
- return (0);
+ return 0;
colonp = tp;
continue;
}
if(tp + INT16SZ > endp)
- return (0);
+ return 0;
*tp++ = (unsigned char) ((val >> 8) & 0xff);
*tp++ = (unsigned char) (val & 0xff);
saw_xdigit = 0;
@@ -210,11 +210,11 @@ inet_pton6(const char *src, unsigned char *dst) saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
- return (0);
+ return 0;
}
if(saw_xdigit) {
if(tp + INT16SZ > endp)
- return (0);
+ return 0;
*tp++ = (unsigned char) ((val >> 8) & 0xff);
*tp++ = (unsigned char) (val & 0xff);
}
@@ -227,7 +227,7 @@ inet_pton6(const char *src, unsigned char *dst) ssize_t i;
if(tp == endp)
- return (0);
+ return 0;
for(i = 1; i <= n; i++) {
*(endp - i) = *(colonp + n - i);
*(colonp + n - i) = 0;
@@ -235,9 +235,9 @@ inet_pton6(const char *src, unsigned char *dst) tp = endp;
}
if(tp != endp)
- return (0);
+ return 0;
memcpy(dst, tmp, IN6ADDRSZ);
- return (1);
+ return 1;
}
#endif /* HAVE_INET_PTON */
diff --git a/libs/libcurl/src/inet_pton.h b/libs/libcurl/src/inet_pton.h index c3dc5d0415..449ec47cf7 100644 --- a/libs/libcurl/src/inet_pton.h +++ b/libs/libcurl/src/inet_pton.h @@ -29,10 +29,20 @@ int Curl_inet_pton(int, const char *, void *);
#ifdef HAVE_INET_PTON
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
+#if defined(__AMIGA__)
+#define Curl_inet_pton(x,y,z) inet_pton(x,(unsigned char *)y,z)
+#else
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#endif
+#endif
#endif /* HEADER_CURL_INET_PTON_H */
diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c index bb1ea644a8..ee86de0d9f 100644 --- a/libs/libcurl/src/krb5.c +++ b/libs/libcurl/src/krb5.c @@ -63,6 +63,11 @@ #include "curl_memory.h"
#include "memdebug.h"
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
const char *cmd)
{
@@ -924,4 +929,8 @@ Curl_sec_end(struct connectdata *conn) conn->mech = NULL;
}
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c index 4e73c241d8..a463bfb47e 100644 --- a/libs/libcurl/src/ldap.c +++ b/libs/libcurl/src/ldap.c @@ -26,6 +26,11 @@ #if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP)
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
/*
* Notice that USE_OPENLDAP is only a source code selection switch. When
* libcurl is built with USE_OPENLDAP defined the libcurl source code that
@@ -52,7 +57,7 @@ #ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
# ifdef _MSC_VER
# pragma warning(push)
-# pragma warning(disable: 4201)
+# pragma warning(disable:4201)
# endif
# include <subauth.h> /* for [P]UNICODE_STRING */
# ifdef _MSC_VER
@@ -78,6 +83,7 @@ #include "urldata.h"
#include <curl/curl.h>
+#include "cfilters.h"
#include "sendf.h"
#include "escape.h"
#include "progress.h"
@@ -148,7 +154,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp); #define ldap_err2string ldap_err2stringA
#endif
-#if defined(USE_WIN32_LDAP) && defined(_MSC_VER) && (_MSC_VER <= 1600)
+#if defined(USE_WIN32_LDAP) && defined(_MSC_VER) && (_MSC_VER <= 1700)
/* Workaround for warning:
'type cast' : conversion from 'int' to 'void *' of greater size */
#undef LDAP_OPT_ON
@@ -181,6 +187,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -210,6 +217,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -346,7 +354,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) }
/* Get the URL scheme (either ldap or ldaps) */
- if(conn->given->flags & PROTOPT_SSL)
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET))
ldap_ssl = 1;
infof(data, "LDAP local: trying to establish %s connection",
ldap_ssl ? "encrypted" : "cleartext");
@@ -381,55 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) #else
int ldap_option;
char *ldap_ca = conn->ssl_config.CAfile;
-#if defined(CURL_HAS_NOVELL_LDAPSDK)
- rc = ldapssl_client_init(NULL, NULL);
- if(rc != LDAP_SUCCESS) {
- failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
- result = CURLE_SSL_CERTPROBLEM;
- goto quit;
- }
- if(conn->ssl_config.verifypeer) {
- /* Novell SDK supports DER or BASE64 files. */
- int cert_type = LDAPSSL_CERT_FILETYPE_B64;
- if((data->set.ssl.cert_type) &&
- (strcasecompare(data->set.ssl.cert_type, "DER")))
- cert_type = LDAPSSL_CERT_FILETYPE_DER;
- if(!ldap_ca) {
- failf(data, "LDAP local: ERROR %s CA cert not set",
- (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
- result = CURLE_SSL_CERTPROBLEM;
- goto quit;
- }
- infof(data, "LDAP local: using %s CA cert '%s'",
- (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
- ldap_ca);
- rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
- if(rc != LDAP_SUCCESS) {
- failf(data, "LDAP local: ERROR setting %s CA cert: %s",
- (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
- ldap_err2string(rc));
- result = CURLE_SSL_CERTPROBLEM;
- goto quit;
- }
- ldap_option = LDAPSSL_VERIFY_SERVER;
- }
- else
- ldap_option = LDAPSSL_VERIFY_NONE;
- rc = ldapssl_set_verify_mode(ldap_option);
- if(rc != LDAP_SUCCESS) {
- failf(data, "LDAP local: ERROR setting cert verify mode: %s",
- ldap_err2string(rc));
- result = CURLE_SSL_CERTPROBLEM;
- goto quit;
- }
- server = ldapssl_init(host, conn->primary.remote_port, 1);
- if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%u",
- conn->host.dispname, conn->primary.remote_port);
- result = CURLE_COULDNT_CONNECT;
- goto quit;
- }
-#elif defined(LDAP_OPT_X_TLS)
+#ifdef LDAP_OPT_X_TLS
if(conn->ssl_config.verifypeer) {
/* OpenLDAP SDK supports BASE64 files. */
if((data->set.ssl.cert_type) &&
@@ -750,10 +710,6 @@ quit: ldap_free_urldesc(ludp);
if(server)
ldap_unbind_s(server);
-#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
- if(ldap_ssl)
- ldapssl_client_deinit();
-#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
FREE_ON_WINLDAP(host);
@@ -800,7 +756,7 @@ static int str2scope(const char *p) return LDAP_SCOPE_SUBTREE;
if(strcasecompare(p, "subtree"))
return LDAP_SCOPE_SUBTREE;
- return (-1);
+ return -1;
}
/*
@@ -1082,7 +1038,7 @@ static int _ldap_url_parse(struct Curl_easy *data, ludp = NULL;
}
*ludpp = ludp;
- return (rc);
+ return rc;
}
static void _ldap_free_urldesc(LDAPURLDesc *ludp)
@@ -1113,4 +1069,9 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp) free(ludp);
}
#endif /* !HAVE_LDAP_URL_PARSE */
+
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/libs/libcurl/src/libcurl.def b/libs/libcurl/src/libcurl.def index 4f8f9229d2..33789fd185 100644 --- a/libs/libcurl/src/libcurl.def +++ b/libs/libcurl/src/libcurl.def @@ -15,6 +15,8 @@ curl_easy_recv curl_easy_reset
curl_easy_send
curl_easy_setopt
+curl_easy_ssls_export
+curl_easy_ssls_import
curl_easy_strerror
curl_easy_unescape
curl_easy_upkeep
diff --git a/libs/libcurl/src/llist.c b/libs/libcurl/src/llist.c index 3d57779338..61348b1809 100644 --- a/libs/libcurl/src/llist.c +++ b/libs/libcurl/src/llist.c @@ -134,40 +134,38 @@ Curl_llist_append(struct Curl_llist *list, const void *p, Curl_llist_insert_next(list, list->_tail, p, ne);
}
-/*
- * @unittest: 1300
- */
-void
-Curl_node_uremove(struct Curl_llist_node *e, void *user)
+void *Curl_node_take_elem(struct Curl_llist_node *e)
{
void *ptr;
struct Curl_llist *list;
if(!e)
- return;
+ return NULL;
list = e->_list;
DEBUGASSERT(list);
DEBUGASSERT(list->_init == LLISTINIT);
DEBUGASSERT(list->_size);
DEBUGASSERT(e->_init == NODEINIT);
- if(e == list->_head) {
- list->_head = e->_next;
+ if(list) {
+ if(e == list->_head) {
+ list->_head = e->_next;
- if(!list->_head)
- list->_tail = NULL;
- else
- e->_next->_prev = NULL;
- }
- else {
- if(e->_prev)
- e->_prev->_next = e->_next;
+ if(!list->_head)
+ list->_tail = NULL;
+ else
+ e->_next->_prev = NULL;
+ }
+ else {
+ if(e->_prev)
+ e->_prev->_next = e->_next;
- if(!e->_next)
- list->_tail = e->_prev;
- else
- e->_next->_prev = e->_prev;
+ if(!e->_next)
+ list->_tail = e->_prev;
+ else
+ e->_next->_prev = e->_prev;
+ }
+ --list->_size;
}
-
ptr = e->_ptr;
e->_list = NULL;
@@ -178,11 +176,27 @@ Curl_node_uremove(struct Curl_llist_node *e, void *user) e->_init = NODEREM; /* specific pattern on remove - not zero */
#endif
- --list->_size;
+ return ptr;
+}
- /* call the dtor() last for when it actually frees the 'e' memory itself */
- if(list->_dtor)
- list->_dtor(user, ptr);
+/*
+ * @unittest: 1300
+ */
+void
+Curl_node_uremove(struct Curl_llist_node *e, void *user)
+{
+ struct Curl_llist *list;
+ void *ptr;
+ if(!e)
+ return;
+
+ list = e->_list;
+ DEBUGASSERT(list);
+ if(list) {
+ ptr = Curl_node_take_elem(e);
+ if(list->_dtor)
+ list->_dtor(user, ptr);
+ }
}
void Curl_node_remove(struct Curl_llist_node *e)
diff --git a/libs/libcurl/src/llist.h b/libs/libcurl/src/llist.h index 3f44090341..776f9cae87 100644 --- a/libs/libcurl/src/llist.h +++ b/libs/libcurl/src/llist.h @@ -75,6 +75,10 @@ size_t Curl_llist_count(struct Curl_llist *list); /* Curl_node_elem() returns the custom data from a Curl_llist_node */
void *Curl_node_elem(struct Curl_llist_node *n);
+/* Remove the node from the list and return the custom data
+ * from a Curl_llist_node. Will NOT incoke a registered `dtor`. */
+void *Curl_node_take_elem(struct Curl_llist_node *);
+
/* Curl_node_next() returns the next element in a list from a given
Curl_llist_node */
struct Curl_llist_node *Curl_node_next(struct Curl_llist_node *n);
diff --git a/libs/libcurl/src/macos.c b/libs/libcurl/src/macos.c index f9396e0360..02024329bf 100644 --- a/libs/libcurl/src/macos.c +++ b/libs/libcurl/src/macos.c @@ -37,7 +37,7 @@ CURLcode Curl_macos_init(void) /*
* The automagic conversion from IPv4 literals to IPv6 literals only
* works if the SCDynamicStoreCopyProxies system function gets called
- * first. As Curl currently does not support system-wide HTTP proxies, we
+ * first. As curl currently does not support system-wide HTTP proxies, we
* therefore do not use any value this function might return.
*
* This function is only available on macOS and is not needed for
diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c index d31658c537..78cd579aee 100644 --- a/libs/libcurl/src/memdebug.c +++ b/libs/libcurl/src/memdebug.c @@ -153,7 +153,7 @@ ALLOC_FUNC void *curl_dbg_malloc(size_t wantedsize, source, line, wantedsize,
mem ? (void *)mem->mem : (void *)0);
- return (mem ? mem->mem : NULL);
+ return mem ? mem->mem : NULL;
}
ALLOC_FUNC void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
@@ -181,7 +181,7 @@ ALLOC_FUNC void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size, source, line, wanted_elements, wanted_size,
mem ? (void *)mem->mem : (void *)0);
- return (mem ? mem->mem : NULL);
+ return mem ? mem->mem : NULL;
}
ALLOC_FUNC char *curl_dbg_strdup(const char *str,
diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index e9aba3488a..66dd0f2ed2 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -1561,6 +1561,14 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part, }
}
+ /* If subparts have already been used as a top-level MIMEPOST,
+ they might not be positioned at start. Rewind them now, as
+ a future check while rewinding the parent may cause this
+ content to be skipped. */
+ if(mime_subparts_seek(subparts, (curl_off_t) 0, SEEK_SET) !=
+ CURL_SEEKFUNC_OK)
+ return CURLE_SEND_FAIL_REWIND;
+
subparts->parent = part;
/* Subparts are processed internally: no read callback. */
part->seekfunc = mime_subparts_seek;
@@ -1590,8 +1598,8 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) (void) size; /* Always 1. */
- /* TODO: this loop is broken. If `nitems` is <= 4, some encoders will
- * return STOP_FILLING without adding any data and this loops infinitely. */
+ /* If `nitems` is <= 4, some encoders will return STOP_FILLING without
+ * adding any data and this loops infinitely. */
do {
hasread = FALSE;
ret = readback_part(part, buffer, nitems, &hasread);
@@ -2171,7 +2179,7 @@ static bool cr_mime_is_paused(struct Curl_easy *data, {
struct cr_mime_ctx *ctx = reader->ctx;
(void)data;
- return (ctx->part && ctx->part->lastreadstatus == CURL_READFUNC_PAUSE);
+ return ctx->part && ctx->part->lastreadstatus == CURL_READFUNC_PAUSE;
}
static const struct Curl_crtype cr_mime = {
diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c index 5722c6d838..572ba1980d 100644 --- a/libs/libcurl/src/mprintf.c +++ b/libs/libcurl/src/mprintf.c @@ -37,14 +37,12 @@ #ifdef HAVE_LONGLONG
# define LONG_LONG_TYPE long long
# define HAVE_LONG_LONG_TYPE
+#elif defined(_MSC_VER)
+# define LONG_LONG_TYPE __int64
+# define HAVE_LONG_LONG_TYPE
#else
-# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
-# define LONG_LONG_TYPE __int64
-# define HAVE_LONG_LONG_TYPE
-# else
-# undef LONG_LONG_TYPE
-# undef HAVE_LONG_LONG_TYPE
-# endif
+# undef LONG_LONG_TYPE
+# undef HAVE_LONG_LONG_TYPE
#endif
/*
@@ -680,12 +678,12 @@ static int formatf( struct outsegment output[MAX_SEGMENTS];
struct va_input input[MAX_PARAMETERS];
- char work[BUFFSIZE];
+ char work[BUFFSIZE + 2];
/* 'workend' points to the final buffer byte position, but with an extra
byte as margin to avoid the (FALSE?) warning Coverity gives us
otherwise */
- char *workend = &work[sizeof(work) - 2];
+ char *workend = &work[BUFFSIZE - 2];
/* Parse the format string */
if(parsefmt(format, output, input, &ocount, &icount, ap_save))
@@ -968,8 +966,8 @@ number: if(width >= 0) {
size_t dlen;
- if(width >= (int)sizeof(work))
- width = sizeof(work)-1;
+ if(width >= BUFFSIZE)
+ width = BUFFSIZE - 1;
/* RECURSIVE USAGE */
dlen = (size_t)curl_msnprintf(fptr, left, "%d", width);
fptr += dlen;
@@ -978,17 +976,19 @@ number: if(prec >= 0) {
/* for each digit in the integer part, we can have one less
precision */
- size_t maxprec = sizeof(work) - 2;
+ int maxprec = BUFFSIZE - 1;
double val = iptr->val.dnum;
+ if(prec > maxprec)
+ prec = maxprec - 1;
if(width > 0 && prec <= width)
- maxprec -= (size_t)width;
+ maxprec -= width;
while(val >= 10.0) {
val /= 10;
maxprec--;
}
- if(prec > (int)maxprec)
- prec = (int)maxprec-1;
+ if(prec > maxprec)
+ prec = maxprec - 1;
if(prec < 0)
prec = 0;
/* RECURSIVE USAGE */
@@ -1014,14 +1014,19 @@ number: /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
#ifdef HAVE_SNPRINTF
- (snprintf)(work, sizeof(work), formatbuf, iptr->val.dnum);
+ (snprintf)(work, BUFFSIZE, formatbuf, iptr->val.dnum); /* NOLINT */
+#ifdef _WIN32
+ /* Old versions of the Windows CRT do not terminate the snprintf output
+ buffer if it reaches the max size so we do that here. */
+ work[BUFFSIZE - 1] = 0;
+#endif
#else
(sprintf)(work, formatbuf, iptr->val.dnum);
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
- DEBUGASSERT(strlen(work) <= sizeof(work));
+ DEBUGASSERT(strlen(work) < BUFFSIZE);
for(fptr = work; *fptr; fptr++)
OUTCHAR(*fptr);
break;
diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c index 05fd45feb9..fa064ebedc 100644 --- a/libs/libcurl/src/mqtt.c +++ b/libs/libcurl/src/mqtt.c @@ -92,6 +92,7 @@ const struct Curl_handler Curl_handler_mqtt = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_MQTT, /* defport */
CURLPROTO_MQTT, /* protocol */
CURLPROTO_MQTT, /* family */
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index b79a577d9e..fa130b23fe 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -46,6 +46,7 @@ #include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -59,7 +60,7 @@ /*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
- CURL handle takes 45-50 K memory, therefore this 3K are not significant.
+ curl handle takes 6K memory, therefore this 3K are not significant.
*/
#ifndef CURL_SOCKET_HASH_TABLE_SIZE
#define CURL_SOCKET_HASH_TABLE_SIZE 911
@@ -73,6 +74,10 @@ #define CURL_DNS_HASH_SIZE 71
#endif
+#ifndef CURL_TLS_SESSION_SIZE
+#define CURL_TLS_SESSION_SIZE 25
+#endif
+
#define CURL_MULTI_HANDLE 0x000bab1e
#ifdef DEBUGBUILD
@@ -395,9 +400,10 @@ static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg) Curl_llist_append(&multi->msglist, msg, &msg->list);
}
-struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
+struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
size_t chashsize, /* connection hash */
- size_t dnssize) /* dns hash */
+ size_t dnssize, /* dns hash */
+ size_t sesssize) /* TLS session cache */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -414,7 +420,10 @@ struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */ Curl_hash_str, Curl_str_key_compare, ph_freeentry);
if(Curl_cpool_init(&multi->cpool, Curl_on_disconnect,
- multi, NULL, chashsize))
+ multi, NULL, chashsize))
+ goto error;
+
+ if(Curl_ssl_scache_create(sesssize, 2, &multi->ssl_scache))
goto error;
Curl_llist_init(&multi->msglist, NULL);
@@ -447,6 +456,7 @@ error: Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_cpool_destroy(&multi->cpool);
+ Curl_ssl_scache_destroy(multi->ssl_scache);
free(multi);
return NULL;
}
@@ -455,7 +465,8 @@ CURLM *curl_multi_init(void) {
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
CURL_CONNECTION_HASH_SIZE,
- CURL_DNS_HASH_SIZE);
+ CURL_DNS_HASH_SIZE,
+ CURL_TLS_SESSION_SIZE);
}
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -787,7 +798,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
- if(!GOOD_EASY_HANDLE(data) || !multi->num_easy)
+ if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
/* Prevent users from trying to remove same easy handle more than once */
@@ -798,6 +809,11 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) if(data->multi != multi)
return CURLM_BAD_EASY_HANDLE;
+ if(!multi->num_easy) {
+ DEBUGASSERT(0);
+ return CURLM_INTERNAL_ERROR;
+ }
+
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
@@ -917,7 +933,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) /* Return TRUE if the application asked for multiplexing */
bool Curl_multiplex_wanted(const struct Curl_multi *multi)
{
- return (multi && (multi->multiplexing));
+ return multi && multi->multiplexing;
}
/*
@@ -930,7 +946,6 @@ void Curl_detach_connection(struct Curl_easy *data) {
struct connectdata *conn = data->conn;
if(conn) {
- Curl_conn_ev_data_detach(conn, data);
Curl_node_remove(&data->conn_queue);
}
data->conn = NULL;
@@ -951,7 +966,6 @@ void Curl_attach_connection(struct Curl_easy *data, Curl_llist_append(&conn->easyq, data, &data->conn_queue);
if(conn->handler && conn->handler->attach)
conn->handler->attach(data, conn);
- Curl_conn_ev_data_attach(conn, data);
}
static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
@@ -1152,6 +1166,7 @@ CURLMcode curl_multi_fdset(CURLM *m, int this_max_fd = -1;
struct Curl_llist_node *e;
struct Curl_multi *multi = m;
+ unsigned int i;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1162,7 +1177,6 @@ CURLMcode curl_multi_fdset(CURLM *m, for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
struct Curl_easy *data = Curl_node_elem(e);
- unsigned int i;
multi_getsock(data, &data->last_poll);
@@ -1170,15 +1184,24 @@ CURLMcode curl_multi_fdset(CURLM *m, if(!FDSET_SOCK(data->last_poll.sockets[i]))
/* pretend it does not exist */
continue;
+#if defined(__DJGPP__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warith-conversion"
+#endif
if(data->last_poll.actions[i] & CURL_POLL_IN)
FD_SET(data->last_poll.sockets[i], read_fd_set);
if(data->last_poll.actions[i] & CURL_POLL_OUT)
FD_SET(data->last_poll.sockets[i], write_fd_set);
+#if defined(__DJGPP__)
+#pragma GCC diagnostic pop
+#endif
if((int)data->last_poll.sockets[i] > this_max_fd)
this_max_fd = (int)data->last_poll.sockets[i];
}
}
+ Curl_cpool_setfds(&multi->cpool, read_fd_set, write_fd_set, &this_max_fd);
+
*max_fd = this_max_fd;
return CURLM_OK;
@@ -1189,12 +1212,13 @@ CURLMcode curl_multi_waitfds(CURLM *m, unsigned int size,
unsigned int *fd_count)
{
- struct curl_waitfds cwfds;
+ struct Curl_waitfds cwfds;
CURLMcode result = CURLM_OK;
struct Curl_llist_node *e;
struct Curl_multi *multi = m;
+ unsigned int need = 0;
- if(!ufds)
+ if(!ufds && (size || !fd_count))
return CURLM_BAD_FUNCTION_ARGUMENT;
if(!GOOD_MULTI_HANDLE(multi))
@@ -1207,20 +1231,17 @@ CURLMcode curl_multi_waitfds(CURLM *m, for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
struct Curl_easy *data = Curl_node_elem(e);
multi_getsock(data, &data->last_poll);
- if(Curl_waitfds_add_ps(&cwfds, &data->last_poll)) {
- result = CURLM_OUT_OF_MEMORY;
- goto out;
- }
+ need += Curl_waitfds_add_ps(&cwfds, &data->last_poll);
}
- if(Curl_cpool_add_waitfds(&multi->cpool, &cwfds)) {
+ need += Curl_cpool_add_waitfds(&multi->cpool, &cwfds);
+
+ if(need != cwfds.n && ufds) {
result = CURLM_OUT_OF_MEMORY;
- goto out;
}
-out:
if(fd_count)
- *fd_count = cwfds.n;
+ *fd_count = need;
return result;
}
@@ -1517,15 +1538,6 @@ CURLMcode curl_multi_wakeup(CURLM *m) Curl_multi struct that are constant */
struct Curl_multi *multi = m;
-#if defined(ENABLE_WAKEUP) && !defined(USE_WINSOCK)
-#ifdef USE_EVENTFD
- const void *buf;
- const uint64_t val = 1;
-#else
- char buf[1];
-#endif
-#endif
-
/* GOOD_MULTI_HANDLE can be safely called */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1539,15 +1551,14 @@ CURLMcode curl_multi_wakeup(CURLM *m) making it safe to access from another thread after the init part
and before cleanup */
if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
+ while(1) {
#ifdef USE_EVENTFD
- buf = &val;
- /* eventfd has a stringent rule of requiring the 8-byte buffer when
- calling write(2) on it, which makes the sizeof(buf) below fine since
- this is only used on 64-bit systems and then the pointer is 64-bit */
+ /* eventfd has a stringent rule of requiring the 8-byte buffer when
+ calling write(2) on it */
+ const uint64_t buf[1] = { 1 };
#else
- buf[0] = 1;
+ const char buf[1] = { 1 };
#endif
- while(1) {
/* swrite() is not thread-safe in general, because concurrent calls
can have their messages interleaved, but in this case the content
of the messages does not matter, which makes it ok to call.
@@ -1834,289 +1845,13 @@ static void multi_posttransfer(struct Curl_easy *data) * This function DOES NOT FREE the given url.
*/
static CURLcode multi_follow(struct Curl_easy *data,
- char *newurl, /* the Location: string */
+ const struct Curl_handler *handler,
+ const char *newurl, /* the Location: string */
followtype type) /* see transfer.h */
{
-#ifdef CURL_DISABLE_HTTP
- (void)data;
- (void)newurl;
- (void)type;
- /* Location: following will not happen when HTTP is disabled */
+ if(handler && handler->follow)
+ return handler->follow(data, newurl, type);
return CURLE_TOO_MANY_REDIRECTS;
-#else
-
- /* Location: redirect */
- bool disallowport = FALSE;
- bool reachedmax = FALSE;
- CURLUcode uc;
-
- DEBUGASSERT(type != FOLLOW_NONE);
-
- if(type != FOLLOW_FAKE)
- data->state.requests++; /* count all real follows */
- if(type == FOLLOW_REDIR) {
- if((data->set.maxredirs != -1) &&
- (data->state.followlocation >= data->set.maxredirs)) {
- reachedmax = TRUE;
- type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
- to URL */
- }
- else {
- data->state.followlocation++; /* count redirect-followings, including
- auth reloads */
-
- if(data->set.http_auto_referer) {
- CURLU *u;
- char *referer = NULL;
-
- /* We are asked to automatically set the previous URL as the referer
- when we get the next URL. We pick the ->url field, which may or may
- not be 100% correct */
-
- if(data->state.referer_alloc) {
- Curl_safefree(data->state.referer);
- data->state.referer_alloc = FALSE;
- }
-
- /* Make a copy of the URL without credentials and fragment */
- u = curl_url();
- if(!u)
- return CURLE_OUT_OF_MEMORY;
-
- uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
- if(!uc)
- uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
-
- curl_url_cleanup(u);
-
- if(uc || !referer)
- return CURLE_OUT_OF_MEMORY;
-
- data->state.referer = referer;
- data->state.referer_alloc = TRUE; /* yes, free this later */
- }
- }
- }
-
- if((type != FOLLOW_RETRY) &&
- (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
- /* If this is not redirect due to a 401 or 407 response and an absolute
- URL: do not allow a custom port number */
- disallowport = TRUE;
- }
-
- DEBUGASSERT(data->state.uh);
- uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
- ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
- ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
- CURLU_ALLOW_SPACE |
- (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
- if(uc) {
- if(type != FOLLOW_FAKE) {
- failf(data, "The redirect target URL could not be parsed: %s",
- curl_url_strerror(uc));
- return Curl_uc_to_curlcode(uc);
- }
-
- /* the URL could not be parsed for some reason, but since this is FAKE
- mode, just duplicate the field as-is */
- newurl = strdup(newurl);
- if(!newurl)
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
- if(uc)
- return Curl_uc_to_curlcode(uc);
-
- /* Clear auth if this redirects to a different port number or protocol,
- unless permitted */
- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
- char *portnum;
- int port;
- bool clear = FALSE;
-
- if(data->set.use_port && data->state.allow_port)
- /* a custom port is used */
- port = (int)data->set.use_port;
- else {
- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
- CURLU_DEFAULT_PORT);
- if(uc) {
- free(newurl);
- return Curl_uc_to_curlcode(uc);
- }
- port = atoi(portnum);
- free(portnum);
- }
- if(port != data->info.conn_remote_port) {
- infof(data, "Clear auth, redirects to port from %u to %u",
- data->info.conn_remote_port, port);
- clear = TRUE;
- }
- else {
- char *scheme;
- const struct Curl_handler *p;
- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
- if(uc) {
- free(newurl);
- return Curl_uc_to_curlcode(uc);
- }
-
- p = Curl_get_scheme_handler(scheme);
- if(p && (p->protocol != data->info.conn_protocol)) {
- infof(data, "Clear auth, redirects scheme from %s to %s",
- data->info.conn_scheme, scheme);
- clear = TRUE;
- }
- free(scheme);
- }
- if(clear) {
- Curl_safefree(data->state.aptr.user);
- Curl_safefree(data->state.aptr.passwd);
- }
- }
- }
-
- if(type == FOLLOW_FAKE) {
- /* we are only figuring out the new URL if we would have followed locations
- but now we are done so we can get out! */
- data->info.wouldredirect = newurl;
-
- if(reachedmax) {
- failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
- return CURLE_TOO_MANY_REDIRECTS;
- }
- return CURLE_OK;
- }
-
- if(disallowport)
- data->state.allow_port = FALSE;
-
- if(data->state.url_alloc)
- Curl_safefree(data->state.url);
-
- data->state.url = newurl;
- data->state.url_alloc = TRUE;
- Curl_req_soft_reset(&data->req, data);
- infof(data, "Issue another request to this URL: '%s'", data->state.url);
-
- /*
- * We get here when the HTTP code is 300-399 (and 401). We need to perform
- * differently based on exactly what return code there was.
- *
- * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
- * an HTTP (proxy-) authentication scheme other than Basic.
- */
- switch(data->info.httpcode) {
- /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
- Authorization: XXXX header in the HTTP request code snippet */
- /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
- Proxy-Authorization: XXXX header in the HTTP request code snippet */
- /* 300 - Multiple Choices */
- /* 306 - Not used */
- /* 307 - Temporary Redirect */
- default: /* for all above (and the unknown ones) */
- /* Some codes are explicitly mentioned since I have checked RFC2616 and
- * they seem to be OK to POST to.
- */
- break;
- case 301: /* Moved Permanently */
- /* (quote from RFC7231, section 6.4.2)
- *
- * Note: For historical reasons, a user agent MAY change the request
- * method from POST to GET for the subsequent request. If this
- * behavior is undesired, the 307 (Temporary Redirect) status code
- * can be used instead.
- *
- * ----
- *
- * Many webservers expect this, so these servers often answers to a POST
- * request with an error page. To be sure that libcurl gets the page that
- * most user agents would get, libcurl has to force GET.
- *
- * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
- * can be overridden with CURLOPT_POSTREDIR.
- */
- if((data->state.httpreq == HTTPREQ_POST
- || data->state.httpreq == HTTPREQ_POST_FORM
- || data->state.httpreq == HTTPREQ_POST_MIME)
- && !(data->set.keep_post & CURL_REDIR_POST_301)) {
- infof(data, "Switch from POST to GET");
- data->state.httpreq = HTTPREQ_GET;
- Curl_creader_set_rewind(data, FALSE);
- }
- break;
- case 302: /* Found */
- /* (quote from RFC7231, section 6.4.3)
- *
- * Note: For historical reasons, a user agent MAY change the request
- * method from POST to GET for the subsequent request. If this
- * behavior is undesired, the 307 (Temporary Redirect) status code
- * can be used instead.
- *
- * ----
- *
- * Many webservers expect this, so these servers often answers to a POST
- * request with an error page. To be sure that libcurl gets the page that
- * most user agents would get, libcurl has to force GET.
- *
- * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
- * can be overridden with CURLOPT_POSTREDIR.
- */
- if((data->state.httpreq == HTTPREQ_POST
- || data->state.httpreq == HTTPREQ_POST_FORM
- || data->state.httpreq == HTTPREQ_POST_MIME)
- && !(data->set.keep_post & CURL_REDIR_POST_302)) {
- infof(data, "Switch from POST to GET");
- data->state.httpreq = HTTPREQ_GET;
- Curl_creader_set_rewind(data, FALSE);
- }
- break;
-
- case 303: /* See Other */
- /* 'See Other' location is not the resource but a substitute for the
- * resource. In this case we switch the method to GET/HEAD, unless the
- * method is POST and the user specified to keep it as POST.
- * https://github.com/curl/curl/issues/5237#issuecomment-614641049
- */
- if(data->state.httpreq != HTTPREQ_GET &&
- ((data->state.httpreq != HTTPREQ_POST &&
- data->state.httpreq != HTTPREQ_POST_FORM &&
- data->state.httpreq != HTTPREQ_POST_MIME) ||
- !(data->set.keep_post & CURL_REDIR_POST_303))) {
- data->state.httpreq = HTTPREQ_GET;
- infof(data, "Switch to %s",
- data->req.no_body ? "HEAD" : "GET");
- }
- break;
- case 304: /* Not Modified */
- /* 304 means we did a conditional request and it was "Not modified".
- * We should not get any Location: header in this response!
- */
- break;
- case 305: /* Use Proxy */
- /* (quote from RFC2616, section 10.3.6):
- * "The requested resource MUST be accessed through the proxy given
- * by the Location field. The Location field gives the URI of the
- * proxy. The recipient is expected to repeat this single request
- * via the proxy. 305 responses MUST only be generated by origin
- * servers."
- */
- break;
- }
- Curl_pgrsTime(data, TIMER_REDIRECT);
- Curl_pgrsResetTransferSizes(data);
-
- return CURLE_OK;
-#endif /* CURL_DISABLE_HTTP */
}
static CURLMcode state_performing(struct Curl_easy *data,
@@ -2215,6 +1950,7 @@ static CURLMcode state_performing(struct Curl_easy *data, multi_done(data, result, TRUE);
}
else if(data->req.done && !Curl_cwriter_is_paused(data)) {
+ const struct Curl_handler *handler = data->conn->handler;
/* call this even if the readwrite function returned error */
multi_posttransfer(data);
@@ -2235,7 +1971,7 @@ static CURLMcode state_performing(struct Curl_easy *data, follow = FOLLOW_RETRY;
(void)multi_done(data, CURLE_OK, FALSE);
/* multi_done() might return CURLE_GOT_NOTHING */
- result = multi_follow(data, newurl, follow);
+ result = multi_follow(data, handler, newurl, follow);
if(!result) {
multistate(data, MSTATE_SETUP);
rc = CURLM_CALL_MULTI_PERFORM;
@@ -2250,7 +1986,7 @@ static CURLMcode state_performing(struct Curl_easy *data, free(newurl);
newurl = data->req.location;
data->req.location = NULL;
- result = multi_follow(data, newurl, FOLLOW_FAKE);
+ result = multi_follow(data, handler, newurl, FOLLOW_FAKE);
if(result) {
*stream_errorp = TRUE;
result = multi_done(data, result, TRUE);
@@ -2302,7 +2038,7 @@ static CURLMcode state_do(struct Curl_easy *data, }
}
- if(data->set.connect_only == 1) {
+ if(data->set.connect_only && !data->set.connect_only_ws) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
@@ -2359,6 +2095,7 @@ static CURLMcode state_do(struct Curl_easy *data, * unexpectedly died. If possible, send the connection back to the
* CONNECT phase so we can try again.
*/
+ const struct Curl_handler *handler = data->conn->handler;
char *newurl = NULL;
followtype follow = FOLLOW_NONE;
CURLcode drc;
@@ -2378,7 +2115,7 @@ static CURLMcode state_do(struct Curl_easy *data, if(newurl) {
if(!drc || (drc == CURLE_SEND_ERROR)) {
follow = FOLLOW_RETRY;
- drc = multi_follow(data, newurl, follow);
+ drc = multi_follow(data, handler, newurl, follow);
if(!drc) {
multistate(data, MSTATE_SETUP);
rc = CURLM_CALL_MULTI_PERFORM;
@@ -3021,9 +2758,11 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles) sigpipe_apply(multi->cpool.idata, &pipe_st);
Curl_cpool_multi_perform(multi);
-
sigpipe_restore(&pipe_st);
+ if(multi_ischanged(m, TRUE))
+ process_pending_handles(m);
+
/*
* Simply remove all expired timers from the splay since handles are dealt
* with unconditionally by this function and curl_multi_timeout() requires
@@ -3124,6 +2863,7 @@ CURLMcode curl_multi_cleanup(CURLM *m) Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_psl_destroy(&multi->psl);
+ Curl_ssl_scache_destroy(multi->ssl_scache);
#ifdef USE_WINSOCK
WSACloseEvent(multi->wsa_event);
@@ -3619,6 +3359,9 @@ out: }
sigpipe_restore(&mrc.pipe_st);
+ if(multi_ischanged(multi, TRUE))
+ process_pending_handles(multi);
+
if(running_handles)
*running_handles = (int)multi->num_alive;
@@ -3676,9 +3419,6 @@ CURLMcode curl_multi_setopt(CURLM *m, break;
case CURLMOPT_MAX_TOTAL_CONNECTIONS:
multi->max_total_connections = va_arg(param, long);
- /* for now, let this also decide the max number of connections
- * in shutdown handling */
- multi->max_shutdown_connections = va_arg(param, long);
break;
/* options formerly used for pipelining */
case CURLMOPT_MAX_PIPELINE_LENGTH:
@@ -4126,7 +3866,7 @@ void Curl_set_in_callback(struct Curl_easy *data, bool value) bool Curl_is_in_callback(struct Curl_easy *data)
{
- return (data && data->multi && data->multi->in_callback);
+ return data && data->multi && data->multi->in_callback;
}
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h index a14f346819..410bf3f53f 100644 --- a/libs/libcurl/src/multihandle.h +++ b/libs/libcurl/src/multihandle.h @@ -106,8 +106,8 @@ struct Curl_multi { curl_push_callback push_cb;
void *push_userp;
- /* Hostname cache */
- struct Curl_hash hostcache;
+ struct Curl_hash hostcache; /* Hostname cache */
+ struct Curl_ssl_scache *ssl_scache; /* TLS session pool */
#ifdef USE_LIBPSL
/* PSL cache. */
@@ -148,8 +148,6 @@ struct Curl_multi { long max_total_connections; /* if >0, a fixed limit of the maximum number
of connections in total */
- long max_shutdown_connections; /* if >0, a fixed limit of the maximum number
- of connections in shutdown handling */
/* timer callback and user data pointer for the *socket() API */
curl_multi_timer_callback timer_cb;
diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h index c5cdc24b37..acabdee604 100644 --- a/libs/libcurl/src/multiif.h +++ b/libs/libcurl/src/multiif.h @@ -47,7 +47,8 @@ void Curl_multi_connchanged(struct Curl_multi *multi); socket, connection and dns hashes */
struct Curl_multi *Curl_multi_handle(size_t hashsize,
size_t chashsize,
- size_t dnssize);
+ size_t dnssize,
+ size_t sesssize);
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
diff --git a/libs/libcurl/src/netrc.c b/libs/libcurl/src/netrc.c index fed826a12d..1586f76fd1 100644 --- a/libs/libcurl/src/netrc.c +++ b/libs/libcurl/src/netrc.c @@ -26,7 +26,9 @@ #ifndef CURL_DISABLE_NETRC
#ifdef HAVE_PWD_H
+#undef __NO_NET_API /* required for AmigaOS to declare getpwuid() */
#include <pwd.h>
+#define __NO_NET_API
#endif
#include <curl/curl.h>
@@ -57,23 +59,26 @@ enum found_state { #define FOUND_LOGIN 1
#define FOUND_PASSWORD 2
-#define NETRC_FILE_MISSING 1
-#define NETRC_FAILED -1
-#define NETRC_SUCCESS 0
-
#define MAX_NETRC_LINE 16384
#define MAX_NETRC_FILE (128*1024)
#define MAX_NETRC_TOKEN 4096
-static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
+/* convert a dynbuf call CURLcode error to a NETRCcode error */
+#define curl2netrc(result) \
+ (((result) == CURLE_OUT_OF_MEMORY) ? \
+ NETRC_OUT_OF_MEMORY : NETRC_SYNTAX_ERROR)
+
+static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf)
{
- CURLcode result = CURLE_OK;
+ NETRCcode ret = NETRC_FILE_MISSING; /* if it cannot open the file */
FILE *file = fopen(filename, FOPEN_READTEXT);
struct dynbuf linebuf;
Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
if(file) {
+ ret = NETRC_OK;
while(Curl_get_line(&linebuf, file)) {
+ CURLcode result;
const char *line = Curl_dyn_ptr(&linebuf);
/* skip comments on load */
while(ISBLANK(*line))
@@ -81,27 +86,29 @@ static CURLcode file2memory(const char *filename, struct dynbuf *filebuf) if(*line == '#')
continue;
result = Curl_dyn_add(filebuf, line);
- if(result)
+ if(result) {
+ ret = curl2netrc(result);
goto done;
+ }
}
}
done:
Curl_dyn_free(&linebuf);
if(file)
fclose(file);
- return result;
+ return ret;
}
/*
* Returns zero on success.
*/
-static int parsenetrc(struct store_netrc *store,
- const char *host,
- char **loginp, /* might point to a username */
- char **passwordp,
- const char *netrcfile)
+static NETRCcode parsenetrc(struct store_netrc *store,
+ const char *host,
+ char **loginp, /* might point to a username */
+ char **passwordp,
+ const char *netrcfile)
{
- int retcode = NETRC_FILE_MISSING;
+ NETRCcode retcode = NETRC_NO_MATCH;
char *login = *loginp;
char *password = NULL;
bool specific_login = !!login; /* points to something */
@@ -118,8 +125,9 @@ static int parsenetrc(struct store_netrc *store, Curl_dyn_init(&token, MAX_NETRC_TOKEN);
if(!store->loaded) {
- if(file2memory(netrcfile, filebuf))
- return NETRC_FAILED;
+ NETRCcode ret = file2memory(netrcfile, filebuf);
+ if(ret)
+ return ret;
store->loaded = TRUE;
}
@@ -149,12 +157,18 @@ static int parsenetrc(struct store_netrc *store, tok_end = tok;
if(!quoted) {
size_t len = 0;
+ CURLcode result;
while(!ISSPACE(*tok_end)) {
tok_end++;
len++;
}
- if(!len || Curl_dyn_addn(&token, tok, len)) {
- retcode = NETRC_FAILED;
+ if(!len) {
+ retcode = NETRC_SYNTAX_ERROR;
+ goto out;
+ }
+ result = Curl_dyn_addn(&token, tok, len);
+ if(result) {
+ retcode = curl2netrc(result);
goto out;
}
}
@@ -163,6 +177,7 @@ static int parsenetrc(struct store_netrc *store, bool endquote = FALSE;
tok_end++; /* pass the leading quote */
while(*tok_end) {
+ CURLcode result;
char s = *tok_end;
if(escape) {
escape = FALSE;
@@ -188,15 +203,16 @@ static int parsenetrc(struct store_netrc *store, endquote = TRUE;
break;
}
- if(Curl_dyn_addn(&token, &s, 1)) {
- retcode = NETRC_FAILED;
+ result = Curl_dyn_addn(&token, &s, 1);
+ if(result) {
+ retcode = curl2netrc(result);
goto out;
}
tok_end++;
}
if(escape || !endquote) {
/* bad syntax, get out */
- retcode = NETRC_FAILED;
+ retcode = NETRC_SYNTAX_ERROR;
goto out;
}
}
@@ -224,7 +240,7 @@ static int parsenetrc(struct store_netrc *store, }
else if(strcasecompare("default", tok)) {
state = HOSTVALID;
- retcode = NETRC_SUCCESS; /* we did find our host */
+ retcode = NETRC_OK; /* we did find our host */
}
break;
case MACDEF:
@@ -235,7 +251,7 @@ static int parsenetrc(struct store_netrc *store, if(strcasecompare(host, tok)) {
/* and yes, this is our host! */
state = HOSTVALID;
- retcode = NETRC_SUCCESS; /* we did find our host */
+ retcode = NETRC_OK; /* we did find our host */
}
else
/* not our host */
@@ -251,7 +267,7 @@ static int parsenetrc(struct store_netrc *store, free(login);
login = strdup(tok);
if(!login) {
- retcode = NETRC_FAILED; /* allocation failed */
+ retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */
goto out;
}
}
@@ -262,10 +278,11 @@ static int parsenetrc(struct store_netrc *store, free(password);
password = strdup(tok);
if(!password) {
- retcode = NETRC_FAILED; /* allocation failed */
+ retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */
goto out;
}
- found |= FOUND_PASSWORD;
+ if(!specific_login || our_login)
+ found |= FOUND_PASSWORD;
keyword = NONE;
}
else if(strcasecompare("login", tok))
@@ -274,6 +291,10 @@ static int parsenetrc(struct store_netrc *store, keyword = PASSWORD;
else if(strcasecompare("machine", tok)) {
/* a new machine here */
+ if(found & FOUND_PASSWORD) {
+ done = TRUE;
+ break;
+ }
state = HOSTFOUND;
keyword = NONE;
found = 0;
@@ -283,7 +304,7 @@ static int parsenetrc(struct store_netrc *store, }
else if(strcasecompare("default", tok)) {
state = HOSTVALID;
- retcode = NETRC_SUCCESS; /* we did find our host */
+ retcode = NETRC_OK; /* we did find our host */
Curl_safefree(password);
if(!specific_login)
Curl_safefree(login);
@@ -309,11 +330,16 @@ static int parsenetrc(struct store_netrc *store, out:
Curl_dyn_free(&token);
- if(!retcode && !password && our_login) {
- /* success without a password, set a blank one */
- password = strdup("");
- if(!password)
- retcode = 1; /* out of memory */
+ if(!retcode) {
+ if(!password && our_login) {
+ /* success without a password, set a blank one */
+ password = strdup("");
+ if(!password)
+ retcode = NETRC_OUT_OF_MEMORY; /* out of memory */
+ }
+ else if(!login && !password)
+ /* a default with no credentials */
+ retcode = NETRC_NO_MATCH;
}
if(!retcode) {
/* success */
@@ -331,17 +357,34 @@ out: return retcode;
}
+const char *Curl_netrc_strerror(NETRCcode ret)
+{
+ switch(ret) {
+ default:
+ return ""; /* not a legit error */
+ case NETRC_FILE_MISSING:
+ return "no such file";
+ case NETRC_NO_MATCH:
+ return "no matching entry";
+ case NETRC_OUT_OF_MEMORY:
+ return "out of memory";
+ case NETRC_SYNTAX_ERROR:
+ return "syntax error";
+ }
+ /* never reached */
+}
+
/*
* @unittest: 1304
*
* *loginp and *passwordp MUST be allocated if they are not NULL when passed
* in.
*/
-int Curl_parsenetrc(struct store_netrc *store, const char *host,
- char **loginp, char **passwordp,
- char *netrcfile)
+NETRCcode Curl_parsenetrc(struct store_netrc *store, const char *host,
+ char **loginp, char **passwordp,
+ char *netrcfile)
{
- int retcode = 1;
+ NETRCcode retcode = NETRC_OK;
char *filealloc = NULL;
if(!netrcfile) {
@@ -379,13 +422,13 @@ int Curl_parsenetrc(struct store_netrc *store, const char *host, }
if(!home)
- return retcode; /* no home directory found (or possibly out of
- memory) */
+ return NETRC_FILE_MISSING; /* no home directory found (or possibly out
+ of memory) */
filealloc = aprintf("%s%s.netrc", home, DIR_CHAR);
if(!filealloc) {
free(homea);
- return -1;
+ return NETRC_OUT_OF_MEMORY;
}
retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
free(filealloc);
@@ -395,7 +438,7 @@ int Curl_parsenetrc(struct store_netrc *store, const char *host, filealloc = aprintf("%s%s_netrc", home, DIR_CHAR);
if(!filealloc) {
free(homea);
- return -1;
+ return NETRC_OUT_OF_MEMORY;
}
retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
free(filealloc);
diff --git a/libs/libcurl/src/netrc.h b/libs/libcurl/src/netrc.h index 6d9f3eddf3..de87097d88 100644 --- a/libs/libcurl/src/netrc.h +++ b/libs/libcurl/src/netrc.h @@ -34,12 +34,21 @@ struct store_netrc { BIT(loaded);
};
+typedef enum {
+ NETRC_OK,
+ NETRC_NO_MATCH, /* no matching entry in the file */
+ NETRC_SYNTAX_ERROR, /* in the netrc file */
+ NETRC_FILE_MISSING, /* the netrc file does not exist */
+ NETRC_OUT_OF_MEMORY, /* while parsing netrc */
+ NETRC_LAST /* never used */
+} NETRCcode;
+
+const char *Curl_netrc_strerror(NETRCcode ret);
void Curl_netrc_init(struct store_netrc *s);
void Curl_netrc_cleanup(struct store_netrc *s);
-/* returns -1 on failure, 0 if the host is found, 1 is the host is not found */
-int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
- char **passwordp, char *filename);
+NETRCcode Curl_parsenetrc(struct store_netrc *s, const char *host,
+ char **loginp, char **passwordp, char *filename);
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine
* section in the netrc.
diff --git a/libs/libcurl/src/nonblock.c b/libs/libcurl/src/nonblock.c index c4d745f543..f33ae8eee7 100644 --- a/libs/libcurl/src/nonblock.c +++ b/libs/libcurl/src/nonblock.c @@ -63,6 +63,12 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ flags &= ~O_NONBLOCK;
return sfcntl(sockfd, F_SETFL, flags);
+#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
+
+ /* Amiga */
+ long flags = nonblock ? 1L : 0L;
+ return IoctlSocket(sockfd, FIONBIO, (char *)&flags);
+
#elif defined(HAVE_IOCTL_FIONBIO)
/* older Unix versions */
@@ -75,12 +81,6 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ unsigned long flags = nonblock ? 1UL : 0UL;
return ioctlsocket(sockfd, (long)FIONBIO, &flags);
-#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
-
- /* Amiga */
- long flags = nonblock ? 1L : 0L;
- return IoctlSocket(sockfd, FIONBIO, (char *)&flags);
-
#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
/* Orbis OS */
diff --git a/libs/libcurl/src/noproxy.c b/libs/libcurl/src/noproxy.c index 8580235b56..ab2a210b7b 100644 --- a/libs/libcurl/src/noproxy.c +++ b/libs/libcurl/src/noproxy.c @@ -71,7 +71,7 @@ UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */ return FALSE;
return TRUE;
}
- return (address == check);
+ return address == check;
}
UNITTEST bool Curl_cidr6_match(const char *ipv6,
diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c index 8bbf9711bf..8c4caf1c0b 100644 --- a/libs/libcurl/src/openldap.c +++ b/libs/libcurl/src/openldap.c @@ -134,6 +134,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -163,6 +164,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -571,7 +573,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
#ifdef USE_SSL
- if(conn->handler->flags & PROTOPT_SSL)
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET))
return oldap_ssl_connect(data, OLDAP_SSL);
if(data->set.use_ssl) {
diff --git a/libs/libcurl/src/optiontable.pl b/libs/libcurl/src/optiontable.pl index ec229b2392..07e66769d6 100644 --- a/libs/libcurl/src/optiontable.pl +++ b/libs/libcurl/src/optiontable.pl @@ -145,7 +145,7 @@ print <<FOOT */
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != ($lastnum + 1));
+ return (CURLOPT_LASTENTRY % 10000) != ($lastnum + 1);
}
#endif
FOOT
diff --git a/libs/libcurl/src/parsedate.c b/libs/libcurl/src/parsedate.c index 6438abebea..7cbb139c9b 100644 --- a/libs/libcurl/src/parsedate.c +++ b/libs/libcurl/src/parsedate.c @@ -558,7 +558,7 @@ static int parsedate(const char *date, time_t *output) if(tzoff == -1)
tzoff = 0;
- if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) {
+ if((tzoff > 0) && (t > (time_t)(TIME_T_MAX - tzoff))) {
*output = TIME_T_MAX;
return PARSEDATE_LATER; /* time_t overflow */
}
@@ -586,7 +586,7 @@ time_t curl_getdate(const char *p, const time_t *now) (void)now; /* legacy argument from the past that we ignore */
if(rc == PARSEDATE_OK) {
- if(parsed == -1)
+ if(parsed == (time_t)-1)
/* avoid returning -1 for a working scenario */
parsed++;
return parsed;
@@ -606,7 +606,7 @@ time_t Curl_getdate_capped(const char *p) switch(rc) {
case PARSEDATE_OK:
- if(parsed == -1)
+ if(parsed == (time_t)-1)
/* avoid returning -1 for a working scenario */
parsed++;
return parsed;
diff --git a/libs/libcurl/src/pingpong.c b/libs/libcurl/src/pingpong.c index 6f1e4c3092..a7c458e0dd 100644 --- a/libs/libcurl/src/pingpong.c +++ b/libs/libcurl/src/pingpong.c @@ -448,7 +448,7 @@ CURLcode Curl_pp_disconnect(struct pingpong *pp) bool Curl_pp_moredata(struct pingpong *pp)
{
- return (!pp->sendleft && Curl_dyn_len(&pp->recvbuf) > pp->nfinal);
+ return !pp->sendleft && Curl_dyn_len(&pp->recvbuf) > pp->nfinal;
}
#endif
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index ca88747ce6..8aa1bafc22 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -83,10 +83,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
/* Local API functions */
static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode pop3_do(struct Curl_easy *data, bool *done);
@@ -138,6 +134,7 @@ const struct Curl_handler Curl_handler_pop3 = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_POP3, /* defport */
CURLPROTO_POP3, /* protocol */
CURLPROTO_POP3, /* family */
@@ -168,6 +165,7 @@ const struct Curl_handler Curl_handler_pop3s = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_POP3S, /* defport */
CURLPROTO_POP3S, /* protocol */
CURLPROTO_POP3, /* family */
@@ -190,19 +188,6 @@ static const struct SASLproto saslpop3 = { SASL_FLAG_BASE64 /* Configuration flags */
};
-#ifdef USE_SSL
-static void pop3_to_pop3s(struct connectdata *conn)
-{
- /* Change the connection handler */
- conn->handler = &Curl_handler_pop3s;
-
- /* Set the connection's upgraded to TLS flag */
- conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define pop3_to_pop3s(x) Curl_nop_stmt
-#endif
-
struct pop3_cmd {
const char *name;
unsigned short nlen;
@@ -237,7 +222,7 @@ static const struct pop3_cmd pop3cmds[] = { static bool pop3_is_multiline(const char *cmdline)
{
size_t i;
- for(i = 0; i < ARRAYSIZE(pop3cmds); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(pop3cmds); ++i) {
if(strncasecompare(pop3cmds[i].name, cmdline, pop3cmds[i].nlen)) {
if(!cmdline[pop3cmds[i].nlen])
return pop3cmds[i].multiline;
@@ -423,6 +408,7 @@ static CURLcode pop3_perform_starttls(struct Curl_easy *data, static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
struct connectdata *conn)
{
+#ifdef USE_SSL
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
CURLcode result;
@@ -432,22 +418,27 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data, result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
+ /* Change the connection handler */
+ conn->handler = &Curl_handler_pop3s;
+ conn->bits.tls_upgraded = TRUE;
}
+ DEBUGASSERT(!pop3c->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-
- if(!result) {
+ DEBUGF(infof(data, "pop3_perform_upgrade_tls, connect -> %d, %d",
+ result, ssldone));
+ if(!result && ssldone) {
pop3c->ssldone = ssldone;
- if(pop3c->state != POP3_UPGRADETLS)
- pop3_state(data, POP3_UPGRADETLS);
-
- if(pop3c->ssldone) {
- pop3_to_pop3s(conn);
- result = pop3_perform_capa(data, conn);
- }
+ /* perform CAPA now, changes pop3c->state out of POP3_UPGRADETLS */
+ result = pop3_perform_capa(data, conn);
}
out:
return result;
+#else
+ (void)data;
+ (void)conn;
+ return CURLE_NOT_BUILT_IN;
+#endif
}
/***********************************************************************
@@ -859,7 +850,7 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, result = pop3_perform_authentication(data, conn);
}
else
- result = pop3_perform_upgrade_tls(data, conn);
+ pop3_state(data, POP3_UPGRADETLS);
return result;
}
@@ -1037,8 +1028,12 @@ static CURLcode pop3_statemachine(struct Curl_easy *data, (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
- if(pop3c->state == POP3_UPGRADETLS)
- return pop3_perform_upgrade_tls(data, conn);
+upgrade_tls:
+ if(pop3c->state == POP3_UPGRADETLS) {
+ result = pop3_perform_upgrade_tls(data, conn);
+ if(result || (pop3c->state == POP3_UPGRADETLS))
+ return result;
+ }
/* Flush any data that needs to be sent */
if(pp->sendleft)
@@ -1065,6 +1060,10 @@ static CURLcode pop3_statemachine(struct Curl_easy *data, case POP3_STARTTLS:
result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
+ /* During UPGRADETLS, leave the read loop as we need to connect
+ * (e.g. TLS handshake) before we continue sending/receiving. */
+ if(!result && (pop3c->state == POP3_UPGRADETLS))
+ goto upgrade_tls;
break;
case POP3_AUTH:
@@ -1110,14 +1109,6 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
- if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
- bool ssldone = FALSE;
- result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
- pop3c->ssldone = ssldone;
- if(result || !pop3c->ssldone)
- return result;
- }
-
result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
*done = (pop3c->state == POP3_STOP);
diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c index dd0cfc1d00..8556cd2221 100644 --- a/libs/libcurl/src/progress.c +++ b/libs/libcurl/src/progress.c @@ -170,6 +170,8 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, case TIMER_STARTOP:
/* This is set at the start of a transfer */
data->progress.t_startop = timestamp;
+ data->progress.t_startqueue = timestamp;
+ data->progress.t_postqueue = 0;
break;
case TIMER_STARTSINGLE:
/* This is set at the start of each single transfer */
@@ -177,12 +179,9 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, data->progress.is_t_startransfer_set = FALSE;
break;
case TIMER_POSTQUEUE:
- /* Set when the transfer starts (after potentially having been brought
- back from the waiting queue). It needs to count from t_startop and not
- t_startsingle since the latter is reset when a connection is brought
- back from the pending queue. */
- data->progress.t_postqueue =
- Curl_timediff_us(timestamp, data->progress.t_startop);
+ /* Queue time is accumulative from all involved redirects */
+ data->progress.t_postqueue +=
+ Curl_timediff_us(timestamp, data->progress.t_startqueue);
break;
case TIMER_STARTACCEPT:
data->progress.t_acceptdata = timestamp;
@@ -220,6 +219,7 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, case TIMER_REDIRECT:
data->progress.t_redirect = Curl_timediff_us(timestamp,
data->progress.start);
+ data->progress.t_startqueue = timestamp;
break;
}
if(delta) {
@@ -312,7 +312,7 @@ timediff_t Curl_pgrsLimitWaitTime(struct pgrs_dir *d, if(actual < minimum) {
/* if it downloaded the data faster than the limit, make it wait the
difference */
- return (minimum - actual);
+ return minimum - actual;
}
return 0;
diff --git a/libs/libcurl/src/request.c b/libs/libcurl/src/request.c index 66130d3f1d..a4fa833e93 100644 --- a/libs/libcurl/src/request.c +++ b/libs/libcurl/src/request.c @@ -66,7 +66,8 @@ CURLcode Curl_req_soft_reset(struct SingleRequest *req, req->headerbytecount = 0;
req->allheadercount = 0;
req->deductheadercount = 0;
-
+ req->httpversion_sent = 0;
+ req->httpversion = 0;
result = Curl_client_start(data);
if(result)
return result;
@@ -162,9 +163,6 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data) req->no_body = data->set.opt_no_body;
req->authneg = FALSE;
req->shutdown = FALSE;
-#ifdef USE_HYPER
- req->bodywritten = FALSE;
-#endif
}
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
@@ -261,7 +259,7 @@ static CURLcode req_send_buffer_flush(struct Curl_easy *data) return result;
}
-CURLcode Curl_req_set_upload_done(struct Curl_easy *data)
+static CURLcode req_set_upload_done(struct Curl_easy *data)
{
DEBUGASSERT(!data->req.upload_done);
data->req.upload_done = TRUE;
@@ -339,7 +337,7 @@ static CURLcode req_flush(struct Curl_easy *data) if(!done)
return CURLE_AGAIN;
}
- return Curl_req_set_upload_done(data);
+ return req_set_upload_done(data);
}
return CURLE_OK;
}
@@ -360,8 +358,6 @@ static ssize_t add_from_client(void *reader_ctx, return (ssize_t)nread;
}
-#ifndef USE_HYPER
-
static CURLcode req_send_buffer_add(struct Curl_easy *data,
const char *buf, size_t blen,
size_t hds_len)
@@ -378,7 +374,8 @@ static CURLcode req_send_buffer_add(struct Curl_easy *data, return CURLE_OK;
}
-CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req)
+CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req,
+ unsigned char httpversion)
{
CURLcode result;
const char *buf;
@@ -387,6 +384,7 @@ CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req) if(!data || !data->conn)
return CURLE_FAILED_INIT;
+ data->req.httpversion_sent = httpversion;
buf = Curl_dyn_ptr(req);
blen = Curl_dyn_len(req);
if(!Curl_creader_total_length(data)) {
@@ -411,7 +409,6 @@ CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req) }
return CURLE_OK;
}
-#endif /* !USE_HYPER */
bool Curl_req_sendbuf_empty(struct Curl_easy *data)
{
@@ -464,7 +461,7 @@ CURLcode Curl_req_abort_sending(struct Curl_easy *data) data->req.upload_aborted = TRUE;
/* no longer KEEP_SEND and KEEP_SEND_PAUSE */
data->req.keepon &= ~KEEP_SENDBITS;
- return Curl_req_set_upload_done(data);
+ return req_set_upload_done(data);
}
return CURLE_OK;
}
diff --git a/libs/libcurl/src/request.h b/libs/libcurl/src/request.h index 12dade3754..f0c8edc006 100644 --- a/libs/libcurl/src/request.h +++ b/libs/libcurl/src/request.h @@ -81,10 +81,11 @@ struct SingleRequest { first one */
curl_off_t offset; /* possible resume offset read from the
Content-Range: header */
- int httpversion; /* Version in response (09, 10, 11, etc.) */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
'RTSP/1.? XXX' line */
int keepon;
+ unsigned char httpversion_sent; /* Version in request (09, 10, 11, etc.) */
+ unsigned char httpversion; /* Version in response (09, 10, 11, etc.) */
enum upgrade101 upgr101; /* 101 upgrade state */
/* Client Writer stack, handles transfer- and content-encodings, protocol
@@ -152,9 +153,6 @@ struct SingleRequest { BIT(sendbuf_init); /* sendbuf is initialized */
BIT(shutdown); /* request end will shutdown connection */
BIT(shutdown_err_ignore); /* errors in shutdown will not fail request */
-#ifdef USE_HYPER
- BIT(bodywritten);
-#endif
};
/**
@@ -196,18 +194,17 @@ void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data); */
void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data);
-#ifndef USE_HYPER
/**
* Send request headers. If not all could be sent
* they will be buffered. Use `Curl_req_flush()` to make sure
* bytes are really send.
* @param data the transfer making the request
* @param buf the complete header bytes, no body
+ * @param httpversion version used in request (09, 10, 11, etc.)
* @return CURLE_OK (on blocking with *pnwritten == 0) or error.
*/
-CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *buf);
-
-#endif /* !USE_HYPER */
+CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *buf,
+ unsigned char httpversion);
/**
* TRUE iff the request has sent all request headers and data.
diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c index 356515a3f4..cc649b67db 100644 --- a/libs/libcurl/src/rtsp.c +++ b/libs/libcurl/src/rtsp.c @@ -24,7 +24,7 @@ #include "curl_setup.h"
-#if !defined(CURL_DISABLE_RTSP) && !defined(USE_HYPER)
+#if !defined(CURL_DISABLE_RTSP)
#include "urldata.h"
#include <curl/curl.h>
@@ -117,6 +117,7 @@ const struct Curl_handler Curl_handler_rtsp = { ZERO_NULL, /* write_resp_hd */
rtsp_conncheck, /* connection_check */
ZERO_NULL, /* attach connection */
+ Curl_http_follow, /* follow */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
CURLPROTO_RTSP, /* family */
@@ -230,6 +231,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp = data->req.p.rtsp;
struct dynbuf req_buffer;
+ unsigned char httpversion = 11; /* RTSP is close to HTTP/1.1, sort of... */
const char *p_request = NULL;
const char *p_session_id = NULL;
@@ -499,7 +501,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) goto out;
}
- result = Curl_add_custom_headers(data, FALSE, &req_buffer);
+ result = Curl_add_custom_headers(data, FALSE, httpversion, &req_buffer);
if(result)
goto out;
@@ -585,7 +587,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
/* issue the request */
- result = Curl_req_send(data, &req_buffer);
+ result = Curl_req_send(data, &req_buffer, httpversion);
if(result) {
failf(data, "Failed sending RTSP request");
goto out;
@@ -1043,4 +1045,4 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport) }
-#endif /* CURL_DISABLE_RTSP or using Hyper */
+#endif /* CURL_DISABLE_RTSP */
diff --git a/libs/libcurl/src/rtsp.h b/libs/libcurl/src/rtsp.h index 27e04a0992..e442676f25 100644 --- a/libs/libcurl/src/rtsp.h +++ b/libs/libcurl/src/rtsp.h @@ -23,9 +23,6 @@ * SPDX-License-Identifier: curl
*
***************************************************************************/
-#ifdef USE_HYPER
-#define CURL_DISABLE_RTSP 1
-#endif
#ifndef CURL_DISABLE_RTSP
diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index d01820d966..e4e66e17d2 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -78,7 +78,7 @@ int Curl_wait_ms(timediff_t timeout_ms) return -1;
}
#if defined(MSDOS)
- delay(timeout_ms);
+ delay((unsigned int)timeout_ms);
#elif defined(_WIN32)
/* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
#if TIMEDIFF_T_MAX >= ULONG_MAX
@@ -488,43 +488,47 @@ CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds, return CURLE_OK;
}
-void Curl_waitfds_init(struct curl_waitfds *cwfds,
+void Curl_waitfds_init(struct Curl_waitfds *cwfds,
struct curl_waitfd *static_wfds,
unsigned int static_count)
{
DEBUGASSERT(cwfds);
- DEBUGASSERT(static_wfds);
+ DEBUGASSERT(static_wfds || !static_count);
memset(cwfds, 0, sizeof(*cwfds));
cwfds->wfds = static_wfds;
cwfds->count = static_count;
}
-static CURLcode cwfds_add_sock(struct curl_waitfds *cwfds,
- curl_socket_t sock, short events)
+static unsigned int cwfds_add_sock(struct Curl_waitfds *cwfds,
+ curl_socket_t sock, short events)
{
int i;
-
+ if(!cwfds->wfds) {
+ DEBUGASSERT(!cwfds->count && !cwfds->n);
+ return 1;
+ }
if(cwfds->n <= INT_MAX) {
for(i = (int)cwfds->n - 1; i >= 0; --i) {
if(sock == cwfds->wfds[i].fd) {
cwfds->wfds[i].events |= events;
- return CURLE_OK;
+ return 0;
}
}
}
/* not folded, add new entry */
- if(cwfds->n >= cwfds->count)
- return CURLE_OUT_OF_MEMORY;
- cwfds->wfds[cwfds->n].fd = sock;
- cwfds->wfds[cwfds->n].events = events;
- ++cwfds->n;
- return CURLE_OK;
+ if(cwfds->n < cwfds->count) {
+ cwfds->wfds[cwfds->n].fd = sock;
+ cwfds->wfds[cwfds->n].events = events;
+ ++cwfds->n;
+ }
+ return 1;
}
-CURLcode Curl_waitfds_add_ps(struct curl_waitfds *cwfds,
- struct easy_pollset *ps)
+unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds,
+ struct easy_pollset *ps)
{
size_t i;
+ unsigned int need = 0;
DEBUGASSERT(cwfds);
DEBUGASSERT(ps);
@@ -534,10 +538,8 @@ CURLcode Curl_waitfds_add_ps(struct curl_waitfds *cwfds, events |= CURL_WAIT_POLLIN;
if(ps->actions[i] & CURL_POLL_OUT)
events |= CURL_WAIT_POLLOUT;
- if(events) {
- if(cwfds_add_sock(cwfds, ps->sockets[i], events))
- return CURLE_OUT_OF_MEMORY;
- }
+ if(events)
+ need += cwfds_add_sock(cwfds, ps->sockets[i], events);
}
- return CURLE_OK;
+ return need;
}
diff --git a/libs/libcurl/src/select.h b/libs/libcurl/src/select.h index 6af855f950..899c9c9b67 100644 --- a/libs/libcurl/src/select.h +++ b/libs/libcurl/src/select.h @@ -130,18 +130,17 @@ CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds, CURLcode Curl_pollfds_add_sock(struct curl_pollfds *cpfds,
curl_socket_t sock, short events);
-struct curl_waitfds {
+struct Curl_waitfds {
struct curl_waitfd *wfds;
unsigned int n;
unsigned int count;
};
-void Curl_waitfds_init(struct curl_waitfds *cwfds,
+void Curl_waitfds_init(struct Curl_waitfds *cwfds,
struct curl_waitfd *static_wfds,
unsigned int static_count);
-CURLcode Curl_waitfds_add_ps(struct curl_waitfds *cwfds,
- struct easy_pollset *ps);
-
+unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds,
+ struct easy_pollset *ps);
#endif /* HEADER_CURL_SELECT_H */
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index 723ef1458a..a4fcb5b224 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -316,9 +316,6 @@ static CURLcode cw_download_write(struct Curl_easy *data, }
/* Update stats, write and report progress */
data->req.bytecount += nwrite;
-#ifdef USE_HYPER
- data->req.bodywritten = TRUE;
-#endif
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result)
return result;
@@ -497,22 +494,6 @@ struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data, return NULL;
}
-void Curl_cwriter_remove_by_name(struct Curl_easy *data,
- const char *name)
-{
- struct Curl_cwriter **anchor = &data->req.writer_stack;
-
- while(*anchor) {
- if(!strcmp(name, (*anchor)->cwt->name)) {
- struct Curl_cwriter *w = (*anchor);
- *anchor = w->next;
- Curl_cwriter_free(data, w);
- continue;
- }
- anchor = &((*anchor)->next);
- }
-}
-
bool Curl_cwriter_is_paused(struct Curl_easy *data)
{
return Curl_cw_out_is_paused(data);
diff --git a/libs/libcurl/src/sendf.h b/libs/libcurl/src/sendf.h index cda179b920..cefd58dfa3 100644 --- a/libs/libcurl/src/sendf.h +++ b/libs/libcurl/src/sendf.h @@ -166,9 +166,6 @@ CURLcode Curl_cwriter_add(struct Curl_easy *data, struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
const struct Curl_cwtype *cwt);
-void Curl_cwriter_remove_by_name(struct Curl_easy *data,
- const char *name);
-
struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
const char *name);
diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 13a4754da3..3c1bb803f4 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -601,8 +601,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, switch(arg) {
case CURL_HTTP_VERSION_NONE:
#ifdef USE_HTTP2
- /* TODO: this seems an undesirable quirk to force a behaviour on
- * lower implementations that they should recognize independently? */
+ /* This seems an undesirable quirk to force a behaviour on lower
+ * implementations that they should recognize independently? */
arg = CURL_HTTP_VERSION_2TLS;
#endif
/* accepted */
@@ -644,13 +644,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, break;
case CURLOPT_HTTP09_ALLOWED:
-#ifdef USE_HYPER
- /* Hyper does not support HTTP/0.9 */
- if(enabled)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-#else
data->set.http09_allowed = enabled;
-#endif
break;
#endif /* ! CURL_DISABLE_HTTP */
@@ -923,6 +917,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, break;
#endif
+#ifdef HAVE_GSSAPI
case CURLOPT_GSSAPI_DELEGATION:
/*
* GSS-API credential delegation bitmask
@@ -930,6 +925,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, data->set.gssapi_delegation = (unsigned char)uarg&
(CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
break;
+#endif
case CURLOPT_SSL_VERIFYPEER:
/*
* Enable peer SSL verifying.
@@ -991,7 +987,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, /*
* Enable TLS false start.
*/
- if(!Curl_ssl_false_start(data))
+ if(!Curl_ssl_false_start())
return CURLE_NOT_BUILT_IN;
data->set.ssl.falsestart = enabled;
@@ -1110,7 +1106,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, */
if(arg > 2)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.connect_only = (unsigned char)arg;
+ data->set.connect_only = !!arg;
+ data->set.connect_only_ws = (arg == 2);
break;
case CURLOPT_SSL_SESSIONID_CACHE:
@@ -1587,10 +1584,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, if(data->share->hsts == data->hsts)
data->hsts = NULL;
#endif
-#ifdef USE_SSL
- if(data->share->sslsession == data->state.session)
- data->state.session = NULL;
-#endif
#ifdef USE_LIBPSL
if(data->psl == &data->share->psl)
data->psl = data->multi ? &data->multi->psl : NULL;
@@ -1631,12 +1624,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, data->hsts = data->share->hsts;
}
#endif
-#ifdef USE_SSL
- if(data->share->sslsession) {
- data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
- data->state.session = data->share->sslsession;
- }
-#endif
#ifdef USE_LIBPSL
if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
data->psl = &data->share->psl;
@@ -2111,7 +2098,6 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * The URL to fetch.
*/
if(data->state.url_alloc) {
- /* the already set URL is allocated, free it first! */
Curl_safefree(data->state.url);
data->state.url_alloc = FALSE;
}
@@ -2199,6 +2185,13 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, /*
* pass CURLU to set URL
*/
+ if(data->state.url_alloc) {
+ Curl_safefree(data->state.url);
+ data->state.url_alloc = FALSE;
+ }
+ else
+ data->state.url = NULL;
+ Curl_safefree(data->set.str[STRING_SET_URL]);
data->set.uh = (CURLU *)ptr;
break;
case CURLOPT_SSLCERT:
@@ -2424,6 +2417,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, */
return Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], ptr);
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
/*
* Option to allow for the MD5 of the host public key to be checked
@@ -2436,7 +2430,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * Store the filename to read known hosts from.
*/
return Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], ptr);
-
+#endif
case CURLOPT_SSH_KEYDATA:
/*
* Custom client data to pass to the SSH keyfunc callback
diff --git a/libs/libcurl/src/setup-vms.h b/libs/libcurl/src/setup-vms.h index 98cd6eb979..a75b4130d3 100644 --- a/libs/libcurl/src/setup-vms.h +++ b/libs/libcurl/src/setup-vms.h @@ -370,7 +370,7 @@ static struct passwd *vms_getpwuid(uid_t uid) #define USE_UPPERCASE_KRBAPI 1
-/* AI_NUMERICHOST needed for IP V6 support in Curl */
+/* AI_NUMERICHOST needed for IP V6 support in curl */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#ifndef AI_NUMERICHOST
diff --git a/libs/libcurl/src/setup-win32.h b/libs/libcurl/src/setup-win32.h index 3d16dce8fc..ee5996fe2e 100644 --- a/libs/libcurl/src/setup-win32.h +++ b/libs/libcurl/src/setup-win32.h @@ -77,17 +77,6 @@ # if defined(_UNICODE) && !defined(UNICODE)
# error "_UNICODE is defined but UNICODE is not defined"
# endif
-/*
- * Do not include unneeded stuff in Windows headers to avoid compiler
- * warnings and macro clashes.
- * Make sure to define this macro before including any Windows headers.
- */
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# ifndef NOGDI
-# define NOGDI
-# endif
# include <winsock2.h>
# include <ws2tcpip.h>
# include <windows.h>
diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c index 6074adb644..3b4258752c 100644 --- a/libs/libcurl/src/sha256.c +++ b/libs/libcurl/src/sha256.c @@ -26,7 +26,7 @@ #include "curl_setup.h"
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
- || defined(USE_LIBSSH2)
+ || defined(USE_LIBSSH2) || defined(USE_SSL)
#include "warnless.h"
#include "curl_sha256.h"
diff --git a/libs/libcurl/src/share.c b/libs/libcurl/src/share.c index 6caed2f7a6..917a315628 100644 --- a/libs/libcurl/src/share.c +++ b/libs/libcurl/src/share.c @@ -30,6 +30,7 @@ #include "share.h"
#include "psl.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "hsts.h"
#include "url.h"
@@ -108,12 +109,13 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
- if(!share->sslsession) {
- share->max_ssl_sessions = 8;
- share->sslsession = calloc(share->max_ssl_sessions,
- sizeof(struct Curl_ssl_session));
- share->sessionage = 0;
- if(!share->sslsession)
+ if(!share->ssl_scache) {
+ /* There is no way (yet) for the application to configure the
+ * session cache size, shared between many transfers. As for curl
+ * itself, a high session count will impact startup time. Also, the
+ * scache is not optimized for several hundreds of peers. So,
+ * keep it at a reasonable level. */
+ if(Curl_ssl_scache_create(25, 2, &share->ssl_scache))
res = CURLSHE_NOMEM;
}
#else
@@ -174,7 +176,10 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
- Curl_safefree(share->sslsession);
+ if(share->ssl_scache) {
+ Curl_ssl_scache_destroy(share->ssl_scache);
+ share->ssl_scache = NULL;
+ }
#else
res = CURLSHE_NOT_BUILT_IN;
#endif
@@ -245,11 +250,9 @@ curl_share_cleanup(CURLSH *sh) #endif
#ifdef USE_SSL
- if(share->sslsession) {
- size_t i;
- for(i = 0; i < share->max_ssl_sessions; i++)
- Curl_ssl_kill_session(&(share->sslsession[i]));
- free(share->sslsession);
+ if(share->ssl_scache) {
+ Curl_ssl_scache_destroy(share->ssl_scache);
+ share->ssl_scache = NULL;
}
#endif
diff --git a/libs/libcurl/src/share.h b/libs/libcurl/src/share.h index 05cd2b0be2..4d68020629 100644 --- a/libs/libcurl/src/share.h +++ b/libs/libcurl/src/share.h @@ -31,6 +31,8 @@ #include "urldata.h"
#include "conncache.h"
+struct Curl_ssl_scache;
+
#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
@@ -58,9 +60,7 @@ struct Curl_share { struct hsts *hsts;
#endif
#ifdef USE_SSL
- struct Curl_ssl_session *sslsession;
- size_t max_ssl_sessions;
- long sessionage;
+ struct Curl_ssl_scache *ssl_scache;
#endif
};
@@ -68,4 +68,9 @@ CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, curl_lock_access);
CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data);
+/* convenience macro to check if this handle is using a shared SSL spool */
+#define CURL_SHARE_ssl_scache(data) (data->share && \
+ (data->share->specifier & \
+ (1<<CURL_LOCK_DATA_SSL_SESSION)))
+
#endif /* HEADER_CURL_SHARE_H */
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c index 34439a6510..f4808e5756 100644 --- a/libs/libcurl/src/smb.c +++ b/libs/libcurl/src/smb.c @@ -273,6 +273,7 @@ const struct Curl_handler Curl_handler_smb = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
CURLPROTO_SMB, /* family */
@@ -301,6 +302,7 @@ const struct Curl_handler Curl_handler_smbs = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
CURLPROTO_SMB, /* family */
@@ -840,7 +842,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) if(smbc->state == SMB_CONNECTING) {
#ifdef USE_SSL
- if((conn->handler->flags & PROTOPT_SSL)) {
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
bool ssl_done = FALSE;
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssl_done);
if(result && result != CURLE_AGAIN)
@@ -879,7 +881,16 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) return CURLE_COULDNT_CONNECT;
}
nrsp = msg;
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic push
+/* error: 'memcpy' offset [74, 80] from the object at '<unknown>' is out of
+ the bounds of referenced subobject 'bytes' with type 'char[1]' */
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic pop
+#endif
smbc->session_key = smb_swap32(nrsp->session_key);
result = smb_send_setup(data);
if(result) {
@@ -915,7 +926,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) */
static void get_posix_time(time_t *out, curl_off_t timestamp)
{
- timestamp -= 116444736000000000;
+ timestamp -= CURL_OFF_T_C(116444736000000000);
timestamp /= 10000000;
#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
if(timestamp > TIME_T_MAX)
diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index 4809987224..b23b74ae60 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -135,6 +135,7 @@ const struct Curl_handler Curl_handler_smtp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
CURLPROTO_SMTP, /* family */
@@ -165,6 +166,7 @@ const struct Curl_handler Curl_handler_smtps = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
CURLPROTO_SMTP, /* family */
@@ -187,19 +189,6 @@ static const struct SASLproto saslsmtp = { SASL_FLAG_BASE64 /* Configuration flags */
};
-#ifdef USE_SSL
-static void smtp_to_smtps(struct connectdata *conn)
-{
- /* Change the connection handler */
- conn->handler = &Curl_handler_smtps;
-
- /* Set the connection's upgraded to TLS flag */
- conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define smtp_to_smtps(x) Curl_nop_stmt
-#endif
-
/***********************************************************************
*
* smtp_endofresp()
@@ -394,31 +383,38 @@ static CURLcode smtp_perform_starttls(struct Curl_easy *data, */
static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
{
+#ifdef USE_SSL
/* Start the SSL connection */
struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
CURLcode result;
bool ssldone = FALSE;
+ DEBUGASSERT(smtpc->state == SMTP_UPGRADETLS);
if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
+ /* Change the connection handler and SMTP state */
+ conn->handler = &Curl_handler_smtps;
+ conn->bits.tls_upgraded = TRUE;
}
+ DEBUGASSERT(!smtpc->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
- if(!result) {
+ DEBUGF(infof(data, "smtp_perform_upgrade_tls, connect -> %d, %d",
+ result, ssldone));
+ if(!result && ssldone) {
smtpc->ssldone = ssldone;
- if(smtpc->state != SMTP_UPGRADETLS)
- smtp_state(data, SMTP_UPGRADETLS);
-
- if(smtpc->ssldone) {
- smtp_to_smtps(conn);
- result = smtp_perform_ehlo(data);
- }
+ /* perform EHLO now, changes smpt->state out of SMTP_UPGRADETLS */
+ result = smtp_perform_ehlo(data);
}
out:
return result;
+#else
+ (void)data;
+ return CURLE_NOT_BUILT_IN;
+#endif
}
/***********************************************************************
@@ -873,7 +869,7 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, result = smtp_perform_authentication(data);
}
else
- result = smtp_perform_upgrade_tls(data);
+ smtp_state(data, SMTP_UPGRADETLS);
return result;
}
@@ -1202,8 +1198,11 @@ static CURLcode smtp_statemachine(struct Curl_easy *data, /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
upgrade_tls:
- if(smtpc->state == SMTP_UPGRADETLS)
- return smtp_perform_upgrade_tls(data);
+ if(smtpc->state == SMTP_UPGRADETLS) {
+ result = smtp_perform_upgrade_tls(data);
+ if(result || (smtpc->state == SMTP_UPGRADETLS))
+ return result;
+ }
/* Flush any data that needs to be sent */
if(pp->sendleft)
@@ -1286,14 +1285,6 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
- bool ssldone = FALSE;
- result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
- smtpc->ssldone = ssldone;
- if(result || !smtpc->ssldone)
- return result;
- }
-
result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
*done = (smtpc->state == SMTP_STOP);
diff --git a/libs/libcurl/src/socketpair.c b/libs/libcurl/src/socketpair.c index 22b067335a..b7adf20bfc 100644 --- a/libs/libcurl/src/socketpair.c +++ b/libs/libcurl/src/socketpair.c @@ -53,7 +53,7 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking) return -1;
#ifdef HAVE_FCNTL
if(fcntl(socks[0], F_SETFD, FD_CLOEXEC) ||
- fcntl(socks[1], F_SETFD, FD_CLOEXEC) ) {
+ fcntl(socks[1], F_SETFD, FD_CLOEXEC)) {
close(socks[0]);
close(socks[1]);
socks[0] = socks[1] = CURL_SOCKET_BAD;
diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c index a71fc433bd..bab7957e91 100644 --- a/libs/libcurl/src/socks_gssapi.c +++ b/libs/libcurl/src/socks_gssapi.c @@ -42,6 +42,11 @@ #include "curl_memory.h"
#include "memdebug.h"
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
#define MAX_GSS_LEN 1024
static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
@@ -537,4 +542,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, return CURLE_OK;
}
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */
diff --git a/libs/libcurl/src/strcase.c b/libs/libcurl/src/strcase.c index 86e81295de..0b3fb773ff 100644 --- a/libs/libcurl/src/strcase.c +++ b/libs/libcurl/src/strcase.c @@ -113,7 +113,7 @@ int curl_strequal(const char *first, const char *second) return casecompare(first, second);
/* if both pointers are NULL then treat them as equal */
- return (NULL == first && NULL == second);
+ return NULL == first && NULL == second;
}
static int ncasecompare(const char *first, const char *second, size_t max)
@@ -139,7 +139,7 @@ int curl_strnequal(const char *first, const char *second, size_t max) return ncasecompare(first, second, max);
/* if both pointers are NULL then treat them as equal if max is non-zero */
- return (NULL == first && NULL == second && max);
+ return NULL == first && NULL == second && max;
}
/* Copy an upper case version of the string from src to dest. The
* strings may overlap. No more than n characters of the string are copied
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index 41c8887f54..ab702e0efc 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -808,7 +808,7 @@ get_winapi_error(int err, char *buf, size_t buflen) *p = '\0';
}
- return (*buf ? buf : NULL);
+ return *buf ? buf : NULL;
}
#endif /* _WIN32 || _WIN32_WCE */
@@ -891,7 +891,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) }
#else
{
- /* !checksrc! disable STRERROR 1 */
+ /* !checksrc! disable BANNEDFUNC 1 */
const char *msg = strerror(err);
if(msg)
msnprintf(buf, buflen, "%s", msg);
diff --git a/libs/libcurl/src/strparse.c b/libs/libcurl/src/strparse.c new file mode 100644 index 0000000000..e057598732 --- /dev/null +++ b/libs/libcurl/src/strparse.c @@ -0,0 +1,136 @@ +/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "strparse.h"
+
+/* Get a word until the first DELIM or end of string. At least one byte long.
+ return non-zero on error */
+int Curl_str_until(char **linep, struct Curl_str *out,
+ const size_t max, char delim)
+{
+ char *s = *linep;
+ size_t len = 0;
+ DEBUGASSERT(linep && *linep && out && max && delim);
+
+ out->str = NULL;
+ out->len = 0;
+ while(*s && (*s != delim)) {
+ s++;
+ if(++len > max) {
+ return STRE_BIG;
+ }
+ }
+ if(!len)
+ return STRE_SHORT;
+ out->str = *linep;
+ out->len = len;
+ *linep = s; /* point to the first byte after the word */
+ return STRE_OK;
+}
+
+/* Get a word until the first space or end of string. At least one byte long.
+ return non-zero on error */
+int Curl_str_word(char **linep, struct Curl_str *out,
+ const size_t max)
+{
+ return Curl_str_until(linep, out, max, ' ');
+}
+
+
+/* Get a "quoted" word. No escaping possible.
+ return non-zero on error */
+int Curl_str_quotedword(char **linep, struct Curl_str *out,
+ const size_t max)
+{
+ char *s = *linep;
+ size_t len = 0;
+ DEBUGASSERT(linep && *linep && out && max);
+
+ out->str = NULL;
+ out->len = 0;
+ if(*s != '\"')
+ return STRE_BEGQUOTE;
+ s++;
+ while(*s && (*s != '\"')) {
+ s++;
+ if(++len > max)
+ return STRE_BIG;
+ }
+ if(*s != '\"')
+ return STRE_ENDQUOTE;
+ out->str = (*linep) + 1;
+ out->len = len;
+ *linep = s + 1;
+ return STRE_OK;
+}
+
+/* Advance over a single character.
+ return non-zero on error */
+int Curl_str_single(char **linep, char byte)
+{
+ DEBUGASSERT(linep && *linep);
+ if(**linep != byte)
+ return STRE_BYTE;
+ (*linep)++; /* move over it */
+ return STRE_OK;
+}
+
+/* Advance over a single space.
+ return non-zero on error */
+int Curl_str_singlespace(char **linep)
+{
+ return Curl_str_single(linep, ' ');
+}
+
+/* Get an unsigned number. Leading zeroes are accepted.
+ return non-zero on error */
+int Curl_str_number(char **linep, size_t *nump, size_t max)
+{
+ size_t num = 0;
+ DEBUGASSERT(linep && *linep && nump);
+ *nump = 0;
+ while(ISDIGIT(**linep)) {
+ int n = **linep - '0';
+ if(num > ((SIZE_T_MAX - n) / 10))
+ return STRE_OVERFLOW;
+ num = num * 10 + n;
+ if(num > max)
+ return STRE_BIG; /** too big */
+ (*linep)++;
+ }
+ *nump = num;
+ return STRE_OK;
+}
+
+/* CR or LF
+ return non-zero on error */
+int Curl_str_newline(char **linep)
+{
+ DEBUGASSERT(linep && *linep);
+ if(ISNEWLINE(**linep)) {
+ (*linep)++;
+ return STRE_OK; /* yessir */
+ }
+ return STRE_NEWLINE;
+}
diff --git a/libs/libcurl/src/strparse.h b/libs/libcurl/src/strparse.h new file mode 100644 index 0000000000..1d4d02638d --- /dev/null +++ b/libs/libcurl/src/strparse.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_STRPARSE_H
+#define HEADER_CURL_STRPARSE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#define STRE_OK 0
+#define STRE_BIG 1
+#define STRE_SHORT 2
+#define STRE_BEGQUOTE 3
+#define STRE_ENDQUOTE 4
+#define STRE_BYTE 5
+#define STRE_NEWLINE 6
+#define STRE_OVERFLOW 7
+
+struct Curl_str {
+ char *str;
+ size_t len;
+};
+
+/* Get a word until the first space
+ return non-zero on error */
+int Curl_str_word(char **linep, struct Curl_str *out, const size_t max);
+
+/* Get a word until the first DELIM or end of string
+ return non-zero on error */
+int Curl_str_until(char **linep, struct Curl_str *out, const size_t max,
+ char delim);
+
+/* Get a "quoted" word. No escaping possible.
+ return non-zero on error */
+int Curl_str_quotedword(char **linep, struct Curl_str *out, const size_t max);
+
+/* Advance over a single character.
+ return non-zero on error */
+int Curl_str_single(char **linep, char byte);
+
+/* Advance over a single space.
+ return non-zero on error */
+int Curl_str_singlespace(char **linep);
+
+/* Get an unsigned number
+ return non-zero on error */
+int Curl_str_number(char **linep, size_t *nump, size_t max);
+
+/* Check for CR or LF
+ return non-zero on error */
+int Curl_str_newline(char **linep);
+
+#endif /* HEADER_CURL_STRPARSE_H */
diff --git a/libs/libcurl/src/strtoofft.c b/libs/libcurl/src/strtoofft.c index 141d485331..6d3f63bec0 100644 --- a/libs/libcurl/src/strtoofft.c +++ b/libs/libcurl/src/strtoofft.c @@ -39,7 +39,7 @@ # ifdef HAVE_STRTOLL
# define strtooff strtoll
# else
-# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
+# if defined(_MSC_VER) && (_MSC_VER >= 1300)
# if defined(_SAL_VERSION)
_Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
_In_z_ const char *_String,
diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c index 622850f052..f57addbefe 100644 --- a/libs/libcurl/src/telnet.c +++ b/libs/libcurl/src/telnet.c @@ -190,6 +190,7 @@ const struct Curl_handler Curl_handler_telnet = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_TELNET, /* defport */
CURLPROTO_TELNET, /* protocol */
CURLPROTO_TELNET, /* family */
@@ -695,7 +696,10 @@ static void printsub(struct Curl_easy *data, infof(data, ", not IAC SE) ");
}
}
- length -= 2;
+ if(length >= 2)
+ length -= 2;
+ else /* bad input */
+ return;
}
if(length < 1) {
infof(data, "(Empty suboption?)");
@@ -773,23 +777,15 @@ static void printsub(struct Curl_easy *data, }
}
-#ifdef _MSC_VER
-#pragma warning(push)
-/* warning C4706: assignment within conditional expression */
-#pragma warning(disable:4706)
-#endif
static bool str_is_nonascii(const char *str)
{
char c;
- while((c = *str++))
+ while((c = *str++) != 0)
if(c & 0x80)
return TRUE;
return FALSE;
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
static CURLcode check_telnet_options(struct Curl_easy *data)
{
@@ -1556,10 +1552,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) /* returned not-zero, this an error */
if(result) {
keepon = FALSE;
- /* TODO: in test 1452, macOS sees a ECONNRESET sometimes?
- * Is this the telnet test server not shutting down the socket
- * in a clean way? Seems to be timing related, happens more
- * on slow debug build */
+ /* In test 1452, macOS sees a ECONNRESET sometimes? Is this the
+ * telnet test server not shutting down the socket in a clean way?
+ * Seems to be timing related, happens more on slow debug build */
if(data->state.os_errno == ECONNRESET) {
DEBUGF(infof(data, "telnet_do, unexpected ECONNRESET on recv"));
}
diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index 13d5e068d1..15342cd8b8 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -185,6 +185,7 @@ const struct Curl_handler Curl_handler_tftp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_TFTP, /* defport */
CURLPROTO_TFTP, /* protocol */
CURLPROTO_TFTP, /* family */
@@ -524,7 +525,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0,
- &data->conn->remote_addr->curl_sa_addr,
+ (struct sockaddr *)&data->conn->remote_addr->curl_sa_addr,
(curl_socklen_t)data->conn->remote_addr->addrlen);
if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN];
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index 53b7b84496..98385a6d3e 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -176,9 +176,9 @@ static bool xfer_recv_shutdown_started(struct Curl_easy *data) int sockindex;
if(!data || !data->conn)
- return CURLE_FAILED_INIT;
+ return FALSE;
if(data->conn->sockfd == CURL_SOCKET_BAD)
- return CURLE_FAILED_INIT;
+ return FALSE;
sockindex = (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]);
return Curl_shutdown_started(data, sockindex);
}
@@ -434,15 +434,6 @@ CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp) data->state.select_bits = 0;
}
-#ifdef USE_HYPER
- if(data->conn->datastream) {
- result = data->conn->datastream(data, data->conn, &didwhat,
- CURL_CSELECT_OUT|CURL_CSELECT_IN);
- if(result || data->req.done)
- goto out;
- }
- else {
-#endif
/* We go ahead and do a read if we have a readable socket or if the stream
was rewound (in which case we have data in a buffer) */
if(k->keepon & KEEP_RECV) {
@@ -457,9 +448,6 @@ CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp) if(result)
goto out;
}
-#ifdef USE_HYPER
- }
-#endif
if(!didwhat) {
/* Transfer wanted to send/recv, but nothing was possible. */
@@ -538,22 +526,17 @@ void Curl_init_CONNECT(struct Curl_easy *data) */
CURLcode Curl_pretransfer(struct Curl_easy *data)
{
- CURLcode result;
+ CURLcode result = CURLE_OK;
- if(!data->state.url && !data->set.uh) {
+ if(!data->set.str[STRING_SET_URL] && !data->set.uh) {
/* we cannot do anything without URL */
failf(data, "No URL set");
return CURLE_URL_MALFORMAT;
}
- /* since the URL may have been redirected in a previous use of this handle */
- if(data->state.url_alloc) {
- /* the already set URL is allocated, free it first! */
- Curl_safefree(data->state.url);
- data->state.url_alloc = FALSE;
- }
-
- if(!data->state.url && data->set.uh) {
+ /* CURLOPT_CURLU overrides CURLOPT_URL and the contents of the CURLU handle
+ is allowed to be changed by the user between transfers */
+ if(data->set.uh) {
CURLUcode uc;
free(data->set.str[STRING_SET_URL]);
uc = curl_url_get(data->set.uh,
@@ -564,6 +547,14 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) }
}
+ /* since the URL may have been redirected in a previous use of this handle */
+ if(data->state.url_alloc) {
+ Curl_safefree(data->state.url);
+ data->state.url_alloc = FALSE;
+ }
+
+ data->state.url = data->set.str[STRING_SET_URL];
+
if(data->set.postfields && data->set.set_resume_from) {
/* we cannot */
failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
@@ -575,14 +566,6 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) data->state.list_only = data->set.list_only;
#endif
data->state.httpreq = data->set.method;
- data->state.url = data->set.str[STRING_SET_URL];
-
- /* Init the SSL session ID cache here. We do it here since we want to do it
- after the *_setopt() calls (that could specify the size of the cache) but
- before any transfer takes place. */
- result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
- if(result)
- return result;
data->state.requests = 0;
data->state.followlocation = 0; /* reset the location-follow counter */
@@ -793,7 +776,7 @@ static void xfer_setup( DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
DEBUGASSERT(!shutdown || (sockindex == -1) || (writesockindex == -1));
- if(conn->bits.multiplex || conn->httpversion >= 20 || want_send) {
+ if(Curl_conn_is_multiplex(conn, FIRSTSOCKET) || want_send) {
/* when multiplexing, the read/write sockets need to be the same! */
conn->sockfd = sockindex == -1 ?
((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
@@ -984,9 +967,9 @@ bool Curl_xfer_is_blocked(struct Curl_easy *data) bool want_send = ((data)->req.keepon & KEEP_SEND);
bool want_recv = ((data)->req.keepon & KEEP_RECV);
if(!want_send)
- return (want_recv && Curl_cwriter_is_paused(data));
+ return want_recv && Curl_cwriter_is_paused(data);
else if(!want_recv)
- return (want_send && Curl_creader_is_paused(data));
+ return want_send && Curl_creader_is_paused(data);
else
return Curl_creader_is_paused(data) && Curl_cwriter_is_paused(data);
}
diff --git a/libs/libcurl/src/transfer.h b/libs/libcurl/src/transfer.h index 26a17568bb..40ed03eae5 100644 --- a/libs/libcurl/src/transfer.h +++ b/libs/libcurl/src/transfer.h @@ -33,15 +33,6 @@ void Curl_init_CONNECT(struct Curl_easy *data); CURLcode Curl_pretransfer(struct Curl_easy *data);
-typedef enum {
- FOLLOW_NONE, /* not used within the function, just a placeholder to
- allow initing to this */
- FOLLOW_FAKE, /* only records stuff, not actually following */
- FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
- redirect following */
- FOLLOW_REDIR /* a full true redirect */
-} followtype;
-
CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp);
int Curl_single_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index dcb3e2ab2b..fe8d61aeda 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -125,10 +125,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
#ifdef USE_NGHTTP2
static void data_priority_cleanup(struct Curl_easy *data);
#else
@@ -382,8 +378,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) #endif
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
- /* Set the default size of the SSL session ID cache */
- set->general_ssl.max_ssl_sessions = 5;
/* Timeout every 24 hours by default */
set->general_ssl.ca_cache_timeout = 24 * 60 * 60;
@@ -568,7 +562,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) DEBUGASSERT(conn);
- for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
Curl_conn_cf_discard_all(data, conn, (int)i);
}
@@ -839,8 +833,8 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data, static bool ssh_config_matches(struct connectdata *one,
struct connectdata *two)
{
- return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
- Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub));
+ return Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
+ Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub);
}
#else
#define ssh_config_matches(x,y) FALSE
@@ -958,12 +952,12 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) return FALSE;
#endif
- if((needle->handler->flags&PROTOPT_SSL) !=
- (conn->handler->flags&PROTOPT_SSL))
- /* do not do mixed SSL and non-SSL connections */
- if(get_protocol_family(conn->handler) !=
- needle->handler->protocol || !conn->bits.tls_upgraded)
- /* except protocols that have been upgraded via TLS */
+ if((!(needle->handler->flags&PROTOPT_SSL) !=
+ !Curl_conn_is_ssl(conn, FIRSTSOCKET)) &&
+ !(get_protocol_family(conn->handler) == needle->handler->protocol &&
+ conn->bits.tls_upgraded))
+ /* Deny `conn` if it is not fit for `needle`'s SSL needs,
+ * UNLESS `conn` is the same protocol family and was upgraded to SSL. */
return FALSE;
#ifndef CURL_DISABLE_PROXY
@@ -1004,7 +998,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) if(match->may_multiplex &&
(data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
(needle->handler->protocol & CURLPROTO_HTTP) &&
- !conn->httpversion) {
+ !conn->httpversion_seen) {
if(data->set.pipewait) {
infof(data, "Server upgrade does not support multiplex yet, wait");
match->found = NULL;
@@ -1027,10 +1021,12 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) }
}
+#ifdef HAVE_GSSAPI
/* GSS delegation differences do not actually affect every connection
and auth method, but this check takes precaution before efficiency */
if(needle->gssapi_delegation != conn->gssapi_delegation)
return FALSE;
+#endif
/* If looking for HTTP and the HTTP version we want is less
* than the HTTP version of conn, continue looking.
@@ -1038,17 +1034,18 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) * so we take any existing connection. */
if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
(data->state.httpwant != CURL_HTTP_VERSION_2TLS)) {
- if((conn->httpversion >= 20) &&
+ unsigned char httpversion = Curl_conn_http_version(data);
+ if((httpversion >= 20) &&
(data->state.httpwant < CURL_HTTP_VERSION_2_0)) {
DEBUGF(infof(data, "nor reusing conn #%" CURL_FORMAT_CURL_OFF_T
" with httpversion=%d, we want a version less than h2",
- conn->connection_id, conn->httpversion));
+ conn->connection_id, httpversion));
}
- if((conn->httpversion >= 30) &&
+ if((httpversion >= 30) &&
(data->state.httpwant < CURL_HTTP_VERSION_3)) {
DEBUGF(infof(data, "nor reusing conn #%" CURL_FORMAT_CURL_OFF_T
" with httpversion=%d, we want a version less than h3",
- conn->connection_id, conn->httpversion));
+ conn->connection_id, httpversion));
return FALSE;
}
}
@@ -1390,8 +1387,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->fclosesocket = data->set.fclosesocket;
conn->closesocket_client = data->set.closesocket_client;
conn->lastused = conn->created;
+#ifdef HAVE_GSSAPI
conn->gssapi_delegation = data->set.gssapi_delegation;
-
+#endif
return conn;
error:
@@ -1827,7 +1825,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, /* HSTS upgrade */
if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
/* This MUST use the IDN decoded name */
- if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
+ if(Curl_hsts(data->hsts, conn->host.name, strlen(conn->host.name), TRUE)) {
char *url;
Curl_safefree(data->state.up.scheme);
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
@@ -2688,7 +2686,6 @@ static CURLcode override_login(struct Curl_easy *data, }
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
- int ret;
bool url_provided = FALSE;
if(data->state.aptr.user &&
@@ -2700,17 +2697,19 @@ static CURLcode override_login(struct Curl_easy *data, }
if(!*passwdp) {
- ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
- userp, passwdp,
- data->set.str[STRING_NETRC_FILE]);
- if(ret > 0) {
+ NETRCcode ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
+ userp, passwdp,
+ data->set.str[STRING_NETRC_FILE]);
+ if(ret && ((ret == NETRC_NO_MATCH) ||
+ (data->set.use_netrc == CURL_NETRC_OPTIONAL))) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
conn->host.name,
(data->set.str[STRING_NETRC_FILE] ?
data->set.str[STRING_NETRC_FILE] : ".netrc"));
}
- else if(ret < 0) {
- failf(data, ".netrc parser error");
+ else if(ret) {
+ const char *m = Curl_netrc_strerror(ret);
+ failf(data, ".netrc error: %s", m);
return CURLE_READ_ERROR;
}
else {
@@ -3103,7 +3102,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, DEBUGF(infof(data, "check Alt-Svc for host %s", host));
if(srcalpnid == ALPN_none) {
/* scan all alt-svc protocol ids in order or relevance */
- for(i = 0; !hit && (i < ARRAYSIZE(alpn_ids)); ++i) {
+ for(i = 0; !hit && (i < CURL_ARRAYSIZE(alpn_ids)); ++i) {
srcalpnid = alpn_ids[i];
hit = Curl_altsvc_lookup(data->asi,
srcalpnid, host, conn->remote_port, /* from */
@@ -3137,14 +3136,14 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, /* protocol version switch */
switch(as->dst.alpnid) {
case ALPN_h1:
- conn->httpversion = 11;
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
break;
case ALPN_h2:
- conn->httpversion = 20;
+ data->state.httpwant = CURL_HTTP_VERSION_2_0;
break;
case ALPN_h3:
conn->transport = TRNSPRT_QUIC;
- conn->httpversion = 30;
+ data->state.httpwant = CURL_HTTP_VERSION_3;
break;
default: /* should not be possible */
break;
@@ -3213,7 +3212,7 @@ static CURLcode resolve_server(struct Curl_easy *data, #endif
if(unix_path) {
- /* TODO, this only works if previous transport is TRNSPRT_TCP. Check it? */
+ /* This only works if previous transport is TRNSPRT_TCP. Check it? */
conn->transport = TRNSPRT_UNIX;
return resolve_unix(data, conn, unix_path);
}
@@ -3311,7 +3310,7 @@ static void reuse_conn(struct Curl_easy *data, * We want to reuse an existing conn to the remote endpoint.
* Since connection reuse does not match on conn->host necessarily, we
* switch `existing` conn to `temp` conn's host settings.
- * TODO: is this correct in the case of TLS connections that have
+ * Is this correct in the case of TLS connections that have
* used the original hostname in SNI to negotiate? Do we send
* requests for another host through the different SNI?
*/
@@ -3571,7 +3570,6 @@ static CURLcode create_conn(struct Curl_easy *data, if(result)
goto out;
- /* FIXME: do we really want to run this every time we add a transfer? */
Curl_cpool_prune_dead(data);
/*************************************************************
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index 9b137193dd..6198d1aa04 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -86,6 +86,9 @@ struct Curl_URL { #define DEFAULT_SCHEME "https"
+static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
+ unsigned int flags);
+
static void free_urlhandle(struct Curl_URL *u)
{
free(u->scheme);
@@ -244,92 +247,47 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, /*
* Concatenate a relative URL to a base URL making it absolute.
- * URL-encodes any spaces.
- * The returned pointer must be freed by the caller unless NULL
- * (returns NULL on out of memory).
*
* Note that this function destroys the 'base' string.
*/
-static CURLcode concat_url(char *base, const char *relurl, char **newurl)
+static CURLUcode redirect_url(char *base, const char *relurl,
+ CURLU *u, unsigned int flags)
{
- /***
- TRY to append this new path to the old URL
- to the right of the host part. Oh crap, this is doomed to cause
- problems in the future...
- */
- struct dynbuf newest;
- char *protsep;
- char *pathsep;
+ struct dynbuf urlbuf;
bool host_changed = FALSE;
const char *useurl = relurl;
CURLcode result = CURLE_OK;
CURLUcode uc;
- bool skip_slash = FALSE;
- *newurl = NULL;
-
/* protsep points to the start of the hostname */
- protsep = strstr(base, "//");
+ char *protsep = strstr(base, "//");
+ DEBUGASSERT(protsep);
if(!protsep)
protsep = base;
else
protsep += 2; /* pass the slashes */
- if('/' != relurl[0]) {
- int level = 0;
-
- /* First we need to find out if there is a ?-letter in the URL,
+ if(('/' != relurl[0]) && ('#' != relurl[0])) {
+ /* First we need to find out if there is a ?-letter in the original URL,
and cut it and the right-side of that off */
- pathsep = strchr(protsep, '?');
+ char *pathsep = strchr(protsep, '?');
if(pathsep)
*pathsep = 0;
-
- /* we have a relative path to append to the last slash if there is one
- available, or the new URL is just a query string (starts with a '?') or
- a fragment (starts with '#') we append the new one at the end of the
- current URL */
- if((useurl[0] != '?') && (useurl[0] != '#')) {
- pathsep = strrchr(protsep, '/');
+ else {
+ /* if not, cut off the potential fragment */
+ pathsep = strchr(protsep, '#');
if(pathsep)
*pathsep = 0;
+ }
- /* Check if there is any slash after the hostname, and if so, remember
- that position instead */
- pathsep = strchr(protsep, '/');
+ /* if the redirect-to piece is not just a query, cut the path after the
+ last slash */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
if(pathsep)
- protsep = pathsep + 1;
- else
- protsep = NULL;
-
- /* now deal with one "./" or any amount of "../" in the newurl
- and act accordingly */
-
- if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl += 2; /* just skip the "./" */
-
- while((useurl[0] == '.') &&
- (useurl[1] == '.') &&
- (useurl[2] == '/')) {
- level++;
- useurl += 3; /* pass the "../" */
- }
-
- if(protsep) {
- while(level--) {
- /* cut off one more level from the right of the original URL */
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- else {
- *protsep = 0;
- break;
- }
- }
- }
+ pathsep[1] = 0; /* leave the slash */
}
- else
- skip_slash = TRUE;
}
- else {
+ else if('/' == relurl[0]) {
/* We got a new absolute path for this server */
if(relurl[1] == '/') {
@@ -341,54 +299,36 @@ static CURLcode concat_url(char *base, const char *relurl, char **newurl) host_changed = TRUE;
}
else {
- /* cut off the original URL from the first slash, or deal with URLs
- without slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.example.com?dir=/home/daniel" we must not use the first
- slash, if there is a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
+ /* cut the original URL at first slash */
+ char *pathsep = strchr(protsep, '/');
+ if(pathsep)
*pathsep = 0;
- }
- else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.example.com?id=2380" which does
- not use a slash separator as it is supposed to, we need to check
- for a ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
- }
}
}
+ else {
+ /* the relative piece starts with '#' */
+
+ /* If there is a fragment in the original URL, cut it off */
+ char *pathsep = strchr(protsep, '#');
+ if(pathsep)
+ *pathsep = 0;
+ }
- Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
+ Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
/* copy over the root URL part */
- result = Curl_dyn_add(&newest, base);
+ result = Curl_dyn_add(&urlbuf, base);
if(result)
- return result;
-
- /* check if we need to append a slash */
- if(('/' == useurl[0]) || (protsep && !*protsep) || skip_slash)
- ;
- else {
- result = Curl_dyn_addn(&newest, "/", 1);
- if(result)
- return result;
- }
+ return cc2cu(result);
/* then append the new piece on the right side */
- uc = urlencode_str(&newest, useurl, strlen(useurl), !host_changed,
+ uc = urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed,
FALSE);
- if(uc)
- return (uc == CURLUE_TOO_LARGE) ? CURLE_TOO_LARGE : CURLE_OUT_OF_MEMORY;
-
- *newurl = Curl_dyn_ptr(&newest);
- return CURLE_OK;
+ if(!uc)
+ uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
+ flags&~CURLU_PATH_AS_IS);
+ Curl_dyn_free(&urlbuf);
+ return uc;
}
/* scan for byte values <= 31, 127 and sometimes space */
@@ -455,7 +395,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, /* We will now try to extract the
* possible login information in a string like:
- * ftp://user:password@ftp.my.site:8021/README */
+ * ftp://user:password@ftp.site.example:8021/README */
ptr++;
/* if this is a known scheme, get some details */
@@ -1856,34 +1796,24 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, * If the existing contents is enough for a URL, allow a relative URL to
* replace it.
*/
- CURLcode result;
CURLUcode uc;
char *oldurl;
- char *redired_url;
if(!nalloc)
/* a blank URL is not a valid URL */
return CURLUE_MALFORMED_INPUT;
- /* if the new thing is absolute or the old one is not
- * (we could not get an absolute URL in 'oldurl'),
- * then replace the existing with the new. */
+ /* if the new thing is absolute or the old one is not (we could not get an
+ * absolute URL in 'oldurl'), then replace the existing with the new. */
if(Curl_is_absolute_url(part, NULL, 0,
- flags & (CURLU_GUESS_SCHEME|
- CURLU_DEFAULT_SCHEME))
+ flags & (CURLU_GUESS_SCHEME|CURLU_DEFAULT_SCHEME))
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags);
}
- /* apply the relative part to create a new URL
- * and replace the existing one with it. */
- result = concat_url(oldurl, part, &redired_url);
+ /* apply the relative part to create a new URL */
+ uc = redirect_url(oldurl, part, u, flags);
free(oldurl);
- if(result)
- return cc2cu(result);
-
- uc = parseurl_and_replace(redired_url, u, flags);
- free(redired_url);
return uc;
}
default:
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index 7833211422..08f8254b58 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -105,7 +105,7 @@ typedef unsigned int curl_prot_t; #define CURL_DEFAULT_USER "anonymous"
#define CURL_DEFAULT_PASSWORD "ftp@example.com"
-#if !defined(_WIN32) && !defined(MSDOS) && !defined(__EMX__)
+#if !defined(_WIN32) && !defined(MSDOS)
/* do FTP line-end CRLF => LF conversions on platforms that prefer LF-only. It
also means: keep CRLF line endings on the CRLF platforms */
#define CURL_PREFER_LF_LINEENDS
@@ -180,13 +180,6 @@ typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */ size_t len, /* max amount to read */
CURLcode *err); /* error to return */
-#ifdef USE_HYPER
-typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
- struct connectdata *conn,
- int *didwhat,
- int select_res);
-#endif
-
#include "mime.h"
#include "imap.h"
#include "pop3.h"
@@ -200,7 +193,6 @@ typedef CURLcode (*Curl_datastream)(struct Curl_easy *data, #include "mqtt.h"
#include "ftplistparser.h"
#include "multihandle.h"
-#include "c-hyper.h"
#include "cf-socket.h"
#ifdef HAVE_GSSAPI
@@ -271,21 +263,7 @@ enum protection_level { /* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;
-
-typedef enum {
- CURL_SSL_PEER_DNS,
- CURL_SSL_PEER_IPV4,
- CURL_SSL_PEER_IPV6
-} ssl_peer_type;
-
-struct ssl_peer {
- char *hostname; /* hostname for verification */
- char *dispname; /* display version of hostname */
- char *sni; /* SNI version of hostname or NULL if not usable */
- ssl_peer_type type; /* type of the peer information */
- int port; /* port we are talking to */
- int transport; /* one of TRNSPRT_* defines */
-};
+struct Curl_ssl_scache_entry;
struct ssl_primary_config {
char *CApath; /* certificate dir (does not work on Windows) */
@@ -337,28 +315,9 @@ struct ssl_config_data { };
struct ssl_general_config {
- size_t max_ssl_sessions; /* SSL session id cache size */
int ca_cache_timeout; /* Certificate store cache timeout (seconds) */
};
-typedef void Curl_ssl_sessionid_dtor(void *sessionid, size_t idsize);
-
-/* information stored about one single SSL session */
-struct Curl_ssl_session {
- char *name; /* hostname for which this ID was used */
- char *conn_to_host; /* hostname for the connection (may be NULL) */
- const char *scheme; /* protocol scheme used */
- char *alpn; /* APLN TLS negotiated protocol string */
- void *sessionid; /* as returned from the SSL layer */
- size_t idsize; /* if known, otherwise 0 */
- Curl_ssl_sessionid_dtor *sessionid_free; /* free `sessionid` callback */
- long age; /* just a number, the higher the more recent */
- int remote_port; /* remote port */
- int conn_to_port; /* remote port for the connection (may be -1) */
- int transport; /* TCP or QUIC */
- struct ssl_primary_config ssl_config; /* setup for this session */
-};
-
#ifdef USE_WINDOWS_SSPI
#include "curl_sspi.h"
#endif
@@ -717,6 +676,12 @@ struct Curl_handler { /* attach() attaches this transfer to this connection */
void (*attach)(struct Curl_easy *data, struct connectdata *conn);
+ /* return CURLE_OK if a redirect to `newurl` should be followed,
+ CURLE_TOO_MANY_REDIRECTS otherwise. May alter `data` to change
+ the way the follow request is performed. */
+ CURLcode (*follow)(struct Curl_easy *data, const char *newurl,
+ followtype type);
+
int defport; /* Default port. */
curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single
specific protocol bit */
@@ -962,10 +927,7 @@ struct connectdata { #ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
#endif
-#ifdef USE_HYPER
- /* if set, an alternative data transfer function */
- Curl_datastream datastream;
-#endif
+
/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
@@ -994,7 +956,9 @@ struct connectdata { #endif
unsigned char transport; /* one of the TRNSPRT_* defines */
unsigned char ip_version; /* copied from the Curl_easy at creation time */
- unsigned char httpversion; /* the HTTP version*10 reported by the server */
+ /* HTTP version last responded with by the server.
+ * 0 at start, then one of 09, 10, 11, etc. */
+ unsigned char httpversion_seen;
unsigned char connect_only;
unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */
};
@@ -1026,6 +990,8 @@ struct PureInfo { curl_off_t request_size; /* the amount of bytes sent in the request(s) */
unsigned long proxyauthavail; /* what proxy auth types were announced */
unsigned long httpauthavail; /* what host auth types were announced */
+ unsigned long proxyauthpicked; /* selected proxy auth type */
+ unsigned long httpauthpicked; /* selected host auth type */
long numconnects; /* how many new connection did libcurl created */
char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would have been redirected to if asked to */
@@ -1090,6 +1056,7 @@ struct Progress { struct curltime start;
struct curltime t_startsingle;
struct curltime t_startop;
+ struct curltime t_startqueue;
struct curltime t_acceptdata;
#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */
@@ -1141,7 +1108,6 @@ struct Curl_data_prio_node { /**
* Priority information for an easy handle in relation to others
* on the same connection.
- * TODO: we need to adapt it to the new priority scheme as defined in RFC 9218
*/
struct Curl_data_priority {
#ifdef USE_NGHTTP2
@@ -1232,8 +1198,6 @@ struct UrlState { curl_prot_t first_remote_protocol;
int retrycount; /* number of retries on a new connection */
- struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
- long sessionage; /* number of the most recent session */
int os_errno; /* filled in with errno whenever an error occurs */
long followlocation; /* redirect counter */
int requests; /* request counter: redirects + authentication retakes */
@@ -1254,6 +1218,10 @@ struct UrlState { #if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
void *engine;
+ /* this is just a flag -- we do not need to reference the provider in any
+ * way as OpenSSL takes care of that */
+ BIT(provider);
+ BIT(provider_failed);
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
@@ -1309,10 +1277,6 @@ struct UrlState { struct curl_slist *cookielist; /* list of cookie files set by
curl_easy_setopt(COOKIEFILE) calls */
#endif
-#ifdef USE_HYPER
- bool hconnect; /* set if a CONNECT request */
- CURLcode hresult; /* used to pass return codes back from hyper callbacks */
-#endif
#ifndef CURL_DISABLE_VERBOSE_STRINGS
struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */
@@ -1570,23 +1534,15 @@ struct UserDefined { void *out; /* CURLOPT_WRITEDATA */
void *in_set; /* CURLOPT_READDATA */
void *writeheader; /* write the header to this if non-NULL */
- unsigned short use_port; /* which port to use (when not using default) */
unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
-
void *postfields; /* if POST, set the fields' values here */
curl_seek_callback seek_func; /* function that seeks the input */
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
of strlen(), and then the data *may* be binary
(contain zero bytes) */
-#ifndef CURL_DISABLE_BINDLOCAL
- unsigned short localport; /* local port number to bind to */
- unsigned short localportrange; /* number of additional port numbers to test
- in case the 'localport' one cannot be
- bind()ed */
-#endif
curl_write_callback fwrite_func; /* function that stores the output */
curl_write_callback fwrite_header; /* function that stores headers */
curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
@@ -1616,11 +1572,6 @@ struct UserDefined { #endif
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
- unsigned int timeout; /* ms, 0 means no timeout */
- unsigned int connecttimeout; /* ms, 0 means default timeout */
- unsigned int happy_eyeballs_timeout; /* ms, 0 is a valid value */
- unsigned int server_response_timeout; /* ms, 0 means no timeout */
- unsigned int shutdowntimeout; /* ms, 0 means default timeout */
long maxage_conn; /* in seconds, max idle time to allow a connection that
is to be reused */
long maxlifetime_conn; /* in seconds, max time since creation to allow a
@@ -1648,10 +1599,6 @@ struct UserDefined { struct curl_slist *connect_to; /* list of host:port mappings to override
the hostname and port to connect to */
time_t timevalue; /* what time to compare with */
- unsigned char timecondition; /* kind of time comparison: curl_TimeCond */
- unsigned char method; /* what kind of HTTP request: Curl_HttpReq */
- unsigned char httpwant; /* when non-zero, a specific HTTP version requested
- to be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
#ifndef CURL_DISABLE_PROXY
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
@@ -1671,24 +1618,17 @@ struct UserDefined { #ifndef CURL_DISABLE_HTTP
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
#endif
- unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
- file 0 - whatever, 1 - v2, 2 - v6 */
curl_off_t max_filesize; /* Maximum file size to download */
#ifndef CURL_DISABLE_FTP
+ unsigned int accepttimeout; /* in milliseconds, 0 means no timeout */
unsigned char ftp_filemethod; /* how to get to a file: curl_ftpfile */
unsigned char ftpsslauth; /* what AUTH XXX to try: curl_ftpauth */
unsigned char ftp_ccc; /* FTP CCC options: curl_ftpccc */
- unsigned int accepttimeout; /* in milliseconds, 0 means no timeout */
#endif
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
struct curl_slist *quote; /* after connection is established */
struct curl_slist *postquote; /* after the transfer */
struct curl_slist *prequote; /* before the transfer, after type */
- /* Despite the name, ftp_create_missing_dirs is for FTP(S) and SFTP
- 1 - create directories that do not exist
- 2 - the same but also allow MKD to fail once
- */
- unsigned char ftp_create_missing_dirs;
#endif
#ifdef USE_LIBSSH2
curl_sshhostkeycallback ssh_hostkeyfunc; /* hostkey check callback */
@@ -1700,9 +1640,6 @@ struct UserDefined { int ssh_auth_types; /* allowed SSH auth types */
unsigned int new_directory_perms; /* when creating remote dirs */
#endif
-#ifndef CURL_DISABLE_NETRC
- unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */
-#endif
unsigned int new_file_perms; /* when creating remote files */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
struct curl_blob *blobs[BLOB_LAST];
@@ -1726,10 +1663,12 @@ struct UserDefined { void *fnmatch_data;
void *wildcardptr;
#endif
- /* GSS-API credential delegation, see the documentation of
- CURLOPT_GSSAPI_DELEGATION */
- unsigned char gssapi_delegation;
+ unsigned int timeout; /* ms, 0 means no timeout */
+ unsigned int connecttimeout; /* ms, 0 means default timeout */
+ unsigned int happy_eyeballs_timeout; /* ms, 0 is a valid value */
+ unsigned int server_response_timeout; /* ms, 0 means no timeout */
+ unsigned int shutdowntimeout; /* ms, 0 means default timeout */
int tcp_keepidle; /* seconds in idle before sending keepalive probe */
int tcp_keepintvl; /* seconds between TCP keepalive probes */
int tcp_keepcnt; /* maximum number of keepalive probes */
@@ -1751,18 +1690,49 @@ struct UserDefined { void *trailer_data; /* pointer to pass to trailer data callback */
curl_trailer_callback trailer_callback; /* trailing data callback */
#endif
- char keep_post; /* keep POSTs as POSTs after a 30x request; each
- bit represents a request, from 301 to 303 */
#ifndef CURL_DISABLE_SMTP
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
- BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
- recipients */
#endif
unsigned int maxconnects; /* Max idle connections in the connection cache */
+ unsigned short use_port; /* which port to use (when not using default) */
+#ifndef CURL_DISABLE_BINDLOCAL
+ unsigned short localport; /* local port number to bind to */
+ unsigned short localportrange; /* number of additional port numbers to test
+ in case the 'localport' one cannot be
+ bind()ed */
+#endif
+#ifndef CURL_DISABLE_NETRC
+ unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */
+#endif
+#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
+ /* Despite the name, ftp_create_missing_dirs is for FTP(S) and SFTP
+ 1 - create directories that do not exist
+ 2 - the same but also allow MKD to fail once
+ */
+ unsigned char ftp_create_missing_dirs;
+#endif
unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! (type: curl_usessl)*/
- unsigned char connect_only; /* make connection/request, then let
- application use the socket */
+ char keep_post; /* keep POSTs as POSTs after a 30x request; each
+ bit represents a request, from 301 to 303 */
+ unsigned char timecondition; /* kind of time comparison: curl_TimeCond */
+ unsigned char method; /* what kind of HTTP request: Curl_HttpReq */
+ unsigned char httpwant; /* when non-zero, a specific HTTP version requested
+ to be used in the library's request(s) */
+ unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
+ file 0 - whatever, 1 - v2, 2 - v6 */
+#ifdef HAVE_GSSAPI
+ /* GSS-API credential delegation, see the documentation of
+ CURLOPT_GSSAPI_DELEGATION */
+ unsigned char gssapi_delegation;
+#endif
+ BIT(connect_only); /* make connection/request, then let application use the
+ socket */
+ BIT(connect_only_ws); /* special websocket connect-only level */
+#ifndef CURL_DISABLE_SMTP
+ BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
+ recipients */
+#endif
#ifndef CURL_DISABLE_MIME
BIT(mime_formescape);
#endif
@@ -1956,9 +1926,6 @@ struct Curl_easy { struct PureInfo info; /* stats, reports and info data */
struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
valid after a client has asked for it */
-#ifdef USE_HYPER
- struct hyptransfer hyp;
-#endif
};
#define LIBCURL_NAME "libcurl"
diff --git a/libs/libcurl/src/vauth/digest_sspi.c b/libs/libcurl/src/vauth/digest_sspi.c index 9c6b1d8667..01c1a05d2b 100644 --- a/libs/libcurl/src/vauth/digest_sspi.c +++ b/libs/libcurl/src/vauth/digest_sspi.c @@ -69,7 +69,7 @@ bool Curl_auth_is_digest_supported(void) Curl_pSecFn->FreeContextBuffer(SecurityPackage);
}
- return (status == SEC_E_OK);
+ return status == SEC_E_OK;
}
/*
diff --git a/libs/libcurl/src/vauth/krb5_gssapi.c b/libs/libcurl/src/vauth/krb5_gssapi.c index fa799354fb..2048938483 100644 --- a/libs/libcurl/src/vauth/krb5_gssapi.c +++ b/libs/libcurl/src/vauth/krb5_gssapi.c @@ -42,6 +42,11 @@ #include "curl_memory.h"
#include "memdebug.h"
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
/*
* Curl_auth_is_gssapi_supported()
*
@@ -321,4 +326,8 @@ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) }
}
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* HAVE_GSSAPI && USE_KERBEROS5 */
diff --git a/libs/libcurl/src/vauth/krb5_sspi.c b/libs/libcurl/src/vauth/krb5_sspi.c index a5393b202d..d7a66aa628 100644 --- a/libs/libcurl/src/vauth/krb5_sspi.c +++ b/libs/libcurl/src/vauth/krb5_sspi.c @@ -64,7 +64,7 @@ bool Curl_auth_is_gssapi_supported(void) Curl_pSecFn->FreeContextBuffer(SecurityPackage);
}
- return (status == SEC_E_OK);
+ return status == SEC_E_OK;
}
/*
diff --git a/libs/libcurl/src/vauth/ntlm_sspi.c b/libs/libcurl/src/vauth/ntlm_sspi.c index 6778b70e79..3bb21cc10b 100644 --- a/libs/libcurl/src/vauth/ntlm_sspi.c +++ b/libs/libcurl/src/vauth/ntlm_sspi.c @@ -63,7 +63,7 @@ bool Curl_auth_is_ntlm_supported(void) Curl_pSecFn->FreeContextBuffer(SecurityPackage);
}
- return (status == SEC_E_OK);
+ return status == SEC_E_OK;
}
/*
diff --git a/libs/libcurl/src/vauth/spnego_gssapi.c b/libs/libcurl/src/vauth/spnego_gssapi.c index 74d4fa3362..850d749c1c 100644 --- a/libs/libcurl/src/vauth/spnego_gssapi.c +++ b/libs/libcurl/src/vauth/spnego_gssapi.c @@ -42,6 +42,11 @@ #include "curl_memory.h"
#include "memdebug.h"
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
/*
* Curl_auth_is_spnego_supported()
*
@@ -288,4 +293,8 @@ void Curl_auth_cleanup_spnego(struct negotiatedata *nego) nego->havemultiplerequests = FALSE;
}
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* HAVE_GSSAPI && USE_SPNEGO */
diff --git a/libs/libcurl/src/vauth/spnego_sspi.c b/libs/libcurl/src/vauth/spnego_sspi.c index 5f82e9a51e..b47475dc31 100644 --- a/libs/libcurl/src/vauth/spnego_sspi.c +++ b/libs/libcurl/src/vauth/spnego_sspi.c @@ -67,7 +67,7 @@ bool Curl_auth_is_spnego_supported(void) }
- return (status == SEC_E_OK);
+ return status == SEC_E_OK;
}
/*
diff --git a/libs/libcurl/src/vauth/vauth.c b/libs/libcurl/src/vauth/vauth.c index 98f5e05d65..d61669c2b8 100644 --- a/libs/libcurl/src/vauth/vauth.c +++ b/libs/libcurl/src/vauth/vauth.c @@ -153,10 +153,10 @@ bool Curl_auth_user_contains_domain(const char *user) bool Curl_auth_allowed_to_host(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- return (!data->state.this_is_a_follow ||
- data->set.allow_auth_to_other_hosts ||
- (data->state.first_host &&
- strcasecompare(data->state.first_host, conn->host.name) &&
- (data->state.first_remote_port == conn->remote_port) &&
- (data->state.first_remote_protocol == conn->handler->protocol)));
+ return !data->state.this_is_a_follow ||
+ data->set.allow_auth_to_other_hosts ||
+ (data->state.first_host &&
+ strcasecompare(data->state.first_host, conn->host.name) &&
+ (data->state.first_remote_port == conn->remote_port) &&
+ (data->state.first_remote_protocol == conn->handler->protocol));
}
diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index 6e92c1c5ee..28d1fd0b95 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -38,10 +38,6 @@ #include "easy_lock.h"
#ifdef USE_ARES
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(_WIN32)
-# define CARES_STATICLIB
-# endif
# include <ares.h>
#endif
@@ -210,9 +206,6 @@ char *curl_version(void) #ifdef USE_LIBRTMP
char rtmp_version[30];
#endif
-#ifdef USE_HYPER
- char hyper_buf[30];
-#endif
#ifdef USE_GSASL
char gsasl_buf[30];
#endif
@@ -277,10 +270,6 @@ char *curl_version(void) Curl_rtmp_version(rtmp_version, sizeof(rtmp_version));
src[i++] = rtmp_version;
#endif
-#ifdef USE_HYPER
- msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
- src[i++] = hyper_buf;
-#endif
#ifdef USE_GSASL
msnprintf(gsasl_buf, sizeof(gsasl_buf), "libgsasl/%s",
gsasl_check_version(NULL));
@@ -423,10 +412,15 @@ static const char * const supported_protocols[] = { * curl_global_init() and curl_global_cleanup() calls.
*/
-#if defined(USE_LIBIDN2)
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
static int idn_present(curl_version_info_data *info)
{
+#if defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
+ (void)info;
+ return TRUE;
+#else
return info->libidn != NULL;
+#endif
}
#else
#define idn_present NULL
@@ -468,6 +462,9 @@ static const struct feat features_table[] = { #ifndef CURL_DISABLE_ALTSVC
FEATURE("alt-svc", NULL, CURL_VERSION_ALTSVC),
#endif
+#if defined(USE_ARES) && defined(CURLRES_THREADED) && defined(USE_HTTPSRR)
+ FEATURE("asyn-rr", NULL, 0),
+#endif
#ifdef CURLRES_ASYNCH
FEATURE("AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS),
#endif
@@ -479,6 +476,10 @@ static const struct feat features_table[] = { #endif
#if defined(USE_SSL) && defined(USE_ECH)
FEATURE("ECH", ech_present, 0),
+
+#ifndef USE_HTTPSRR
+#error "ECH enabled but not HTTPSRR, must be a config error"
+#endif
#endif
#ifdef USE_GSASL
FEATURE("gsasl", NULL, CURL_VERSION_GSASL),
@@ -499,6 +500,9 @@ static const struct feat features_table[] = { !defined(CURL_DISABLE_HTTP)
FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
#endif
+#if defined(USE_HTTPSRR)
+ FEATURE("HTTPSRR", NULL, 0),
+#endif
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
FEATURE("IDN", idn_present, CURL_VERSION_IDN),
#endif
@@ -530,6 +534,9 @@ static const struct feat features_table[] = { #ifdef USE_SSL
FEATURE("SSL", NULL, CURL_VERSION_SSL),
#endif
+#if defined(USE_SSLS_EXPORT)
+ FEATURE("SSLS-EXPORT", NULL, 0),
+#endif
#ifdef USE_WINDOWS_SSPI
FEATURE("SSPI", NULL, CURL_VERSION_SSPI),
#endif
@@ -676,14 +683,6 @@ curl_version_info_data *curl_version_info(CURLversion stamp) }
#endif
-#ifdef USE_HYPER
- {
- static char hyper_buffer[30];
- msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version());
- version_info.hyper_version = hyper_buffer;
- }
-#endif
-
#ifdef USE_GSASL
{
version_info.gsasl_version = gsasl_check_version(NULL);
diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c index 0ce9fe4cac..ae9e79a662 100644 --- a/libs/libcurl/src/vquic/curl_msh3.c +++ b/libs/libcurl/src/vquic/curl_msh3.c @@ -132,15 +132,23 @@ struct cf_msh3_ctx { static void h3_stream_hash_free(void *stream);
-static void cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
- const struct Curl_addrinfo *ai)
+static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
+ const struct Curl_addrinfo *ai)
{
+ CURLcode result;
+
DEBUGASSERT(!ctx->initialized);
Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
- Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
+
+ result = Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
+ if(result)
+ return result;
+
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
ctx->initialized = TRUE;
+
+ return result;
}
static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
@@ -433,10 +441,10 @@ static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request, CURLcode result;
bool rv = FALSE;
- /* TODO: we would like to limit the amount of data we are buffer here.
- * There seems to be no mechanism in msh3 to adjust flow control and
- * it is undocumented what happens if we return FALSE here or less
- * length (buflen is an inout parameter).
+ /* We would like to limit the amount of data we are buffer here. There seems
+ * to be no mechanism in msh3 to adjust flow control and it is undocumented
+ * what happens if we return FALSE here or less length (buflen is an inout
+ * parameter).
*/
(void)Request;
if(!stream)
@@ -695,8 +703,8 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, goto out;
}
- /* TODO - msh3/msquic will hold onto this memory until the send complete
- event. How do we make sure curl does not free it until then? */
+ /* msh3/msquic will hold onto this memory until the send complete event.
+ How do we make sure curl does not free it until then? */
*err = CURLE_OK;
nwritten = len;
}
@@ -830,7 +838,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
if(verify && (conn_config->CAfile || conn_config->CApath)) {
- /* TODO: need a way to provide trust anchors to MSH3 */
+ /* Need a way to provide trust anchors to MSH3 */
#ifdef DEBUGBUILD
/* we need this for our test cases to run */
CURL_TRC_CF(data, cf, "non-standard CA not supported, "
@@ -910,7 +918,6 @@ static CURLcode cf_msh3_connect(struct Curl_cfilter *cf, if(ctx->handshake_succeeded) {
CURL_TRC_CF(data, cf, "handshake succeeded");
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
cf->connected = TRUE;
cf->conn->alpn = CURL_HTTP_VERSION_3;
*done = TRUE;
@@ -999,7 +1006,7 @@ static CURLcode cf_msh3_query(struct Curl_cfilter *cf, switch(query) {
case CF_QUERY_MAX_CONCURRENT: {
- /* TODO: we do not have access to this so far, fake it */
+ /* We do not have access to this so far, fake it */
(void)ctx;
*pres1 = 100;
return CURLE_OK;
@@ -1017,6 +1024,9 @@ static CURLcode cf_msh3_query(struct Curl_cfilter *cf, *when = ctx->handshake_at;
return CURLE_OK;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 30;
+ return CURLE_OK;
default:
break;
}
@@ -1039,7 +1049,7 @@ static bool cf_msh3_conn_is_alive(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_http3 = {
"HTTP/3",
- CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
0,
cf_msh3_destroy,
cf_msh3_connect,
@@ -1081,13 +1091,16 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, (void)data;
(void)conn;
- (void)ai; /* TODO: msh3 resolves itself? */
+ (void)ai; /* msh3 resolves itself? */
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_msh3_ctx_init(ctx, ai);
+
+ result = cf_msh3_ctx_init(ctx, ai);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.c b/libs/libcurl/src/vquic/curl_ngtcp2.c index b017b49ace..8f54f159ee 100644 --- a/libs/libcurl/src/vquic/curl_ngtcp2.c +++ b/libs/libcurl/src/vquic/curl_ngtcp2.c @@ -66,6 +66,7 @@ #include "vquic-tls.h"
#include "vtls/keylog.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "curl_ngtcp2.h"
#include "warnless.h"
@@ -137,8 +138,16 @@ struct cf_ngtcp2_ctx { uint64_t max_idle_ms; /* max idle time for QUIC connection */
uint64_t used_bidi_streams; /* bidi streams we have opened */
uint64_t max_bidi_streams; /* max bidi streams we can open */
+ size_t earlydata_max; /* max amount of early data supported by
+ server on session reuse */
+ size_t earlydata_skip; /* sending bytes to skip when earlydata
+ * is accepted by peer */
+ CURLcode tls_vrfy_result; /* result of TLS peer verification */
int qlogfd;
BIT(initialized);
+ BIT(tls_handshake_complete); /* TLS handshake is done */
+ BIT(use_earlydata); /* Using 0RTT data */
+ BIT(earlydata_accepted); /* 0RTT was acceptd by server */
BIT(shutdown_started); /* queued shutdown packets */
};
@@ -166,6 +175,8 @@ static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx) static void cf_ngtcp2_ctx_free(struct cf_ngtcp2_ctx *ctx)
{
if(ctx && ctx->initialized) {
+ Curl_vquic_tls_cleanup(&ctx->tls);
+ vquic_ctx_free(&ctx->q);
Curl_bufcp_free(&ctx->stream_bufcp);
Curl_dyn_free(&ctx->scratch);
Curl_hash_clean(&ctx->streams);
@@ -383,7 +394,7 @@ static void quic_printf(void *user_data, const char *fmt, ...) struct Curl_cfilter *cf = user_data;
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- (void)ctx; /* TODO: need an easy handle to infof() message */
+ (void)ctx; /* need an easy handle to infof() message */
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
@@ -442,12 +453,45 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx, }
}
-static CURLcode init_ngh3_conn(struct Curl_cfilter *cf);
+static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
-static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
+static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
- (void)user_data;
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf ? cf->ctx : NULL;
+ struct Curl_easy *data;
+
(void)tconn;
+ DEBUGASSERT(ctx);
+ data = CF_DATA_CURRENT(cf);
+ DEBUGASSERT(data);
+ if(!ctx || !data)
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+
+ ctx->handshake_at = Curl_now();
+ ctx->tls_handshake_complete = TRUE;
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+
+ ctx->tls_vrfy_result = Curl_vquic_tls_verify_peer(&ctx->tls, cf,
+ data, &ctx->peer);
+ CURL_TRC_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
+ /* In case of earlydata, where we simulate being connected, update
+ * the handshake time when we really did connect */
+ if(ctx->use_earlydata)
+ Curl_pgrsTimeWas(data, TIMER_APPCONNECT, ctx->handshake_at);
+#ifdef USE_GNUTLS
+ if(ctx->use_earlydata) {
+ int flags = gnutls_session_get_flags(ctx->tls.gtls.session);
+ ctx->earlydata_accepted = !!(flags & GNUTLS_SFLAGS_EARLY_DATA);
+ CURL_TRC_CF(data, cf, "server did%s accept %zu bytes of early data",
+ ctx->earlydata_accepted ? "" : " not", ctx->earlydata_skip);
+ Curl_pgrsEarlyData(data, ctx->earlydata_accepted ?
+ (curl_off_t)ctx->earlydata_skip :
+ -(curl_off_t)ctx->earlydata_skip);
+ }
+#endif
return 0;
}
@@ -717,16 +761,19 @@ static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level, void *user_data)
{
struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf ? cf->ctx : NULL;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)tconn;
- if(level != NGTCP2_ENCRYPTION_LEVEL_1RTT) {
+ if(level != NGTCP2_ENCRYPTION_LEVEL_1RTT)
return 0;
- }
- if(init_ngh3_conn(cf) != CURLE_OK) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(data);
+ if(ctx && data && !ctx->h3conn) {
+ if(init_ngh3_conn(cf, data))
+ return NGTCP2_ERR_CALLBACK_FAILURE;
}
-
return 0;
}
@@ -739,7 +786,7 @@ static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
ngtcp2_crypto_recv_crypto_data_cb,
- cb_handshake_completed,
+ cf_ngtcp2_handshake_completed,
NULL, /* recv_version_negotiation */
ngtcp2_crypto_encrypt_cb,
ngtcp2_crypto_decrypt_cb,
@@ -1128,14 +1175,15 @@ static nghttp3_callbacks ngh3_callbacks = { NULL /* recv_settings */
};
-static CURLcode init_ngh3_conn(struct Curl_cfilter *cf)
+static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- CURLcode result;
- int rc;
int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
+ int rc;
if(ngtcp2_conn_get_streams_uni_left(ctx->qconn) < 3) {
+ failf(data, "QUIC connection lacks 3 uni streams to run HTTP/3");
return CURLE_QUIC_CONNECT_ERROR;
}
@@ -1147,45 +1195,47 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf) nghttp3_mem_default(),
cf);
if(rc) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
+ failf(data, "error creating nghttp3 connection instance");
+ return CURLE_OUT_OF_MEMORY;
}
rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &ctrl_stream_id, NULL);
if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
+ failf(data, "error creating HTTP/3 control stream: %s",
+ ngtcp2_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
}
rc = nghttp3_conn_bind_control_stream(ctx->h3conn, ctrl_stream_id);
if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
+ failf(data, "error binding HTTP/3 control stream: %s",
+ ngtcp2_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
}
rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_enc_stream_id, NULL);
if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
+ failf(data, "error creating HTTP/3 qpack encoding stream: %s",
+ ngtcp2_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
}
rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_dec_stream_id, NULL);
if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
+ failf(data, "error creating HTTP/3 qpack decoding stream: %s",
+ ngtcp2_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
}
rc = nghttp3_conn_bind_qpack_streams(ctx->h3conn, qpack_enc_stream_id,
qpack_dec_stream_id);
if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
+ failf(data, "error binding HTTP/3 qpack streams: %s",
+ ngtcp2_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
}
return CURLE_OK;
-fail:
-
- return result;
}
static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
@@ -1236,6 +1286,10 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, DEBUGASSERT(ctx->h3conn);
*err = CURLE_OK;
+ /* handshake verification failed in callback, do not recv anything */
+ if(ctx->tls_vrfy_result)
+ return ctx->tls_vrfy_result;
+
pktx_init(&pktx, cf, data);
if(!stream || ctx->shutdown_started) {
@@ -1521,7 +1575,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, {
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
- ssize_t sent = 0;
+ ssize_t sent = -1;
struct cf_call_data save;
struct pkt_io_ctx pktx;
CURLcode result;
@@ -1533,18 +1587,20 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, pktx_init(&pktx, cf, data);
*err = CURLE_OK;
- (void)eos; /* TODO: use for stream EOF and block handling */
+ /* handshake verification failed in callback, do not send anything */
+ if(ctx->tls_vrfy_result)
+ return ctx->tls_vrfy_result;
+
+ (void)eos; /* use for stream EOF and block handling */
result = cf_progress_ingress(cf, data, &pktx);
if(result) {
*err = result;
- sent = -1;
}
if(!stream || stream->id < 0) {
if(ctx->shutdown_started) {
CURL_TRC_CF(data, cf, "cannot open stream on closed connection");
*err = CURLE_SEND_ERROR;
- sent = -1;
goto out;
}
sent = h3_stream_open(cf, data, buf, len, err);
@@ -1558,7 +1614,6 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] xfer write failed", stream->id);
cf_ngtcp2_stream_close(cf, data, stream);
*err = stream->xfer_result;
- sent = -1;
goto out;
}
else if(stream->closed) {
@@ -1583,7 +1638,6 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, else if(ctx->shutdown_started) {
CURL_TRC_CF(data, cf, "cannot send on closed connection");
*err = CURLE_SEND_ERROR;
- sent = -1;
goto out;
}
else {
@@ -1598,6 +1652,9 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, (void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
}
+ if(sent > 0 && !ctx->tls_handshake_complete && ctx->use_earlydata)
+ ctx->earlydata_skip += sent;
+
result = cf_progress_egress(cf, data, &pktx);
if(result) {
*err = result;
@@ -1616,17 +1673,6 @@ out: return sent;
}
-static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
-
- cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
-
- return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
-}
-
static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
struct sockaddr_storage *remote_addr,
socklen_t remote_addrlen, int ecn,
@@ -1696,7 +1742,7 @@ static ssize_t read_pkt_to_send(void *userp, uint32_t flags;
int64_t stream_id;
int fin;
- ssize_t nwritten, n;
+ ssize_t nwritten = 0, n;
veccnt = 0;
stream_id = -1;
fin = 0;
@@ -1708,7 +1754,6 @@ static ssize_t read_pkt_to_send(void *userp, * When ngtcp2 is happy (because it has no other frame that would fit
* or it has nothing more to send), it returns the total length
* of the assembled packet. This may be 0 if there was nothing to send. */
- nwritten = 0;
*err = CURLE_OK;
for(;;) {
@@ -1920,8 +1965,8 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf, struct Curl_easy *data,
bool pause)
{
- /* TODO: there seems right now no API in ngtcp2 to shrink/enlarge
- * the streams windows. As we do in HTTP/2. */
+ /* There seems to exist no API in ngtcp2 to shrink/enlarge the streams
+ * windows. As we do in HTTP/2. */
if(!pause) {
h3_drain_stream(cf, data);
Curl_expire(data, 0, EXPIRE_RUN_NOW);
@@ -1946,9 +1991,6 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DETACH:
- h3_data_done(cf, data);
- break;
case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
@@ -2131,7 +2173,8 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) ctx = cf ? cf->ctx : NULL;
data = cf ? CF_DATA_CURRENT(cf) : NULL;
if(cf && data && ctx) {
- Curl_ossl_add_session(cf, data, &ctx->peer, ssl_sessionid);
+ Curl_ossl_add_session(cf, data, ctx->peer.scache_key, ssl_sessionid,
+ SSL_version(ssl), "h3");
return 1;
}
return 0;
@@ -2139,6 +2182,24 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) #endif /* USE_OPENSSL */
#ifdef USE_GNUTLS
+
+static const char *gtls_hs_msg_name(int mtype)
+{
+ switch(mtype) {
+ case 1: return "ClientHello";
+ case 2: return "ServerHello";
+ case 4: return "SessionTicket";
+ case 8: return "EncryptedExtensions";
+ case 11: return "Certificate";
+ case 13: return "CertificateRequest";
+ case 15: return "CertificateVerify";
+ case 20: return "Finished";
+ case 24: return "KeyUpdate";
+ case 254: return "MessageHash";
+ }
+ return "Unknown";
+}
+
static int quic_gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
unsigned when, unsigned int incoming,
const gnutls_datum_t *msg)
@@ -2152,13 +2213,28 @@ static int quic_gtls_handshake_cb(gnutls_session_t session, unsigned int htype, if(when && cf && ctx) { /* after message has been processed */
struct Curl_easy *data = CF_DATA_CURRENT(cf);
DEBUGASSERT(data);
- if(data) {
- CURL_TRC_CF(data, cf, "handshake: %s message type %d",
- incoming ? "incoming" : "outgoing", htype);
- }
+ if(!data)
+ return 0;
+ CURL_TRC_CF(data, cf, "SSL message: %s %s [%d]",
+ incoming ? "<-" : "->", gtls_hs_msg_name(htype), htype);
switch(htype) {
case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
- (void)Curl_gtls_update_session_id(cf, data, session, &ctx->peer, "h3");
+ ngtcp2_ssize tplen;
+ uint8_t tpbuf[256];
+ unsigned char *quic_tp = NULL;
+ size_t quic_tp_len = 0;
+
+ tplen = ngtcp2_conn_encode_0rtt_transport_params(ctx->qconn, tpbuf,
+ sizeof(tpbuf));
+ if(tplen < 0)
+ CURL_TRC_CF(data, cf, "error encoding 0RTT transport data: %s",
+ ngtcp2_strerror((int)tplen));
+ else {
+ quic_tp = (unsigned char *)tpbuf;
+ quic_tp_len = (size_t)tplen;
+ }
+ (void)Curl_gtls_cache_session(cf, data, ctx->peer.scache_key,
+ session, 0, "h3", quic_tp, quic_tp_len);
break;
}
default:
@@ -2181,16 +2257,17 @@ static int wssl_quic_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) struct Curl_easy *data = CF_DATA_CURRENT(cf);
DEBUGASSERT(data);
if(data && ctx) {
- (void)wssl_cache_session(cf, data, &ctx->peer, session);
+ (void)Curl_wssl_cache_session(cf, data, ctx->peer.scache_key,
+ session, wolfSSL_version(ssl), "h3");
}
}
return 0;
}
#endif /* USE_WOLFSSL */
-static CURLcode tls_ctx_setup(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- void *user_data)
+static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ void *user_data)
{
struct curl_tls_ctx *ctx = user_data;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
@@ -2243,6 +2320,53 @@ static CURLcode tls_ctx_setup(struct Curl_cfilter *cf, return CURLE_OK;
}
+static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct Curl_ssl_session *scs,
+ bool *do_early_data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ *do_early_data = FALSE;
+#ifdef USE_GNUTLS
+ ctx->earlydata_max =
+ gnutls_record_get_max_early_data_size(ctx->tls.gtls.session);
+ if((!ctx->earlydata_max)) {
+ CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
+ }
+ else if(strcmp("h3", scs->alpn)) {
+ CURL_TRC_CF(data, cf, "SSL session from different ALPN, no early data");
+ }
+ else if(!scs->quic_tp || !scs->quic_tp_len) {
+ CURL_TRC_CF(data, cf, "no 0RTT transport parameters, no early data, ");
+ }
+ else {
+ int rv;
+ rv = ngtcp2_conn_decode_and_set_0rtt_transport_params(
+ ctx->qconn, (uint8_t *)scs->quic_tp, scs->quic_tp_len);
+ if(rv)
+ CURL_TRC_CF(data, cf, "no early data, failed to set 0RTT transport "
+ "parameters: %s", ngtcp2_strerror(rv));
+ else {
+ infof(data, "SSL session allows %zu bytes of early data, "
+ "reusing ALPN '%s'", ctx->earlydata_max, scs->alpn);
+ result = init_ngh3_conn(cf, data);
+ if(!result) {
+ ctx->use_earlydata = TRUE;
+ cf->connected = TRUE;
+ *do_early_data = TRUE;
+ }
+ }
+ }
+#else /* USE_GNUTLS */
+ (void)data;
+ (void)ctx;
+ (void)scs;
+#endif
+ return result;
+}
+
/*
* Might be called twice for happy eyeballs.
*/
@@ -2258,21 +2382,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, int qfd;
DEBUGASSERT(ctx->initialized);
- result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
- if(result)
- return result;
-
-#define H3_ALPN "\x2h3\x5h3-29"
- result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
- H3_ALPN, sizeof(H3_ALPN) - 1,
- tls_ctx_setup, &ctx->tls, &ctx->conn_ref);
- if(result)
- return result;
-
-#ifdef USE_OPENSSL
- SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
-#endif
-
ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
result = Curl_rand(data, ctx->dcid.data, NGTCP2_MAX_CIDLEN);
if(result)
@@ -2314,7 +2423,17 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, if(rc)
return CURLE_QUIC_CONNECT_ERROR;
+#define H3_ALPN "\x2h3\x5h3-29"
+ result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+ H3_ALPN, sizeof(H3_ALPN) - 1,
+ cf_ngtcp2_tls_ctx_setup, &ctx->tls,
+ &ctx->conn_ref,
+ cf_ngtcp2_on_session_reuse);
+ if(result)
+ return result;
+
#ifdef USE_OPENSSL
+ SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ossl.ssl);
#elif defined(USE_GNUTLS)
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session);
@@ -2365,6 +2484,11 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, result = cf_connect_start(cf, data, &pktx);
if(result)
goto out;
+ if(cf->connected) {
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ *done = TRUE;
+ goto out;
+ }
result = cf_progress_egress(cf, data, &pktx);
/* we do not expect to be able to recv anything yet */
goto out;
@@ -2379,10 +2503,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, goto out;
if(ngtcp2_conn_get_handshake_completed(ctx->qconn)) {
- ctx->handshake_at = now;
- CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at));
- result = qng_verify_peer(cf, data);
+ result = ctx->tls_vrfy_result;
if(!result) {
CURL_TRC_CF(data, cf, "peer verified");
cf->connected = TRUE;
@@ -2474,6 +2595,9 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf, *when = ctx->handshake_at;
return CURLE_OK;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 30;
+ return CURLE_OK;
default:
break;
}
@@ -2536,7 +2660,7 @@ out: struct Curl_cftype Curl_cft_http3 = {
"HTTP/3",
- CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
0,
cf_ngtcp2_destroy,
cf_ngtcp2_connect,
diff --git a/libs/libcurl/src/vquic/curl_osslq.c b/libs/libcurl/src/vquic/curl_osslq.c index c3d695d415..47dbd9afa2 100644 --- a/libs/libcurl/src/vquic/curl_osslq.c +++ b/libs/libcurl/src/vquic/curl_osslq.c @@ -82,10 +82,6 @@ #define H3_STREAM_SEND_CHUNKS \
(H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
typedef uint32_t sslerr_t;
#else
@@ -292,6 +288,9 @@ struct cf_osslq_ctx { struct Curl_hash streams; /* hash `data->mid` to `h3_stream_ctx` */
size_t max_stream_window; /* max flow window for one stream */
uint64_t max_idle_ms; /* max idle time for QUIC connection */
+ SSL_POLL_ITEM *poll_items; /* Array for polling on writable state */
+ struct Curl_easy **curl_items; /* Array of easy objs */
+ size_t item_count; /* count of elements in poll/curl_items */
BIT(initialized);
BIT(got_first_byte); /* if first byte was received */
BIT(x509_store_setup); /* if x509 store has been set up */
@@ -308,6 +307,9 @@ static void cf_osslq_ctx_init(struct cf_osslq_ctx *ctx) Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+ ctx->poll_items = NULL;
+ ctx->curl_items = NULL;
+ ctx->item_count = 0;
ctx->initialized = TRUE;
}
@@ -318,6 +320,8 @@ static void cf_osslq_ctx_free(struct cf_osslq_ctx *ctx) Curl_hash_clean(&ctx->streams);
Curl_hash_destroy(&ctx->streams);
Curl_ssl_peer_cleanup(&ctx->peer);
+ free(ctx->poll_items);
+ free(ctx->curl_items);
}
free(ctx);
}
@@ -450,7 +454,7 @@ static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3, struct cf_osslq_ctx *ctx = cf->ctx;
curl_int64_t stream_id = (curl_int64_t)SSL_get_stream_id(stream_ssl);
- if(h3->remote_ctrl_n >= ARRAYSIZE(h3->remote_ctrl)) {
+ if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) {
/* rejected, we are full */
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] rejecting remote stream",
stream_id);
@@ -562,7 +566,6 @@ static CURLcode cf_osslq_verify_peer(struct Curl_cfilter *cf, struct cf_osslq_ctx *ctx = cf->ctx;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
}
@@ -1162,14 +1165,11 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf, BIO_ADDR *baddr = NULL;
DEBUGASSERT(ctx->initialized);
- result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
- if(result)
- goto out;
#define H3_ALPN "\x2h3"
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
H3_ALPN, sizeof(H3_ALPN) - 1,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
if(result)
goto out;
@@ -1464,24 +1464,80 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf, {
struct cf_osslq_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream;
+ size_t poll_count = 0;
+ size_t result_count = 0;
+ size_t idx_count = 0;
+ CURLcode res = CURLE_OK;
+ struct timeval timeout;
+ void *tmpptr;
if(ctx->h3.conn) {
struct Curl_llist_node *e;
+
+ res = CURLE_OUT_OF_MEMORY;
+
+ if(ctx->item_count < Curl_llist_count(&data->multi->process)) {
+ ctx->item_count = 0;
+ tmpptr = realloc(ctx->poll_items,
+ Curl_llist_count(&data->multi->process) *
+ sizeof(SSL_POLL_ITEM));
+ if(!tmpptr) {
+ free(ctx->poll_items);
+ ctx->poll_items = NULL;
+ goto out;
+ }
+ ctx->poll_items = tmpptr;
+
+ tmpptr = realloc(ctx->curl_items,
+ Curl_llist_count(&data->multi->process) *
+ sizeof(struct Curl_easy *));
+ if(!tmpptr) {
+ free(ctx->curl_items);
+ ctx->curl_items = NULL;
+ goto out;
+ }
+ ctx->curl_items = tmpptr;
+
+ ctx->item_count = Curl_llist_count(&data->multi->process);
+ }
+
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
struct Curl_easy *sdata = Curl_node_elem(e);
if(sdata->conn == data->conn) {
stream = H3_STREAM_CTX(ctx, sdata);
- if(stream && stream->s.ssl && stream->s.send_blocked &&
- !SSL_want_write(stream->s.ssl)) {
- nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
- stream->s.send_blocked = FALSE;
- h3_drain_stream(cf, sdata);
- CURL_TRC_CF(sdata, cf, "unblocked");
+ if(stream && stream->s.ssl && stream->s.send_blocked) {
+ ctx->poll_items[poll_count].desc =
+ SSL_as_poll_descriptor(stream->s.ssl);
+ ctx->poll_items[poll_count].events = SSL_POLL_EVENT_W;
+ ctx->curl_items[poll_count] = sdata;
+ poll_count++;
}
}
}
+
+ memset(&timeout, 0, sizeof(struct timeval));
+ res = CURLE_UNRECOVERABLE_POLL;
+ if(!SSL_poll(ctx->poll_items, poll_count, sizeof(SSL_POLL_ITEM), &timeout,
+ 0, &result_count))
+ goto out;
+
+ res = CURLE_OK;
+
+ for(idx_count = 0; idx_count < poll_count && result_count > 0;
+ idx_count++) {
+ if(ctx->poll_items[idx_count].revents & SSL_POLL_EVENT_W) {
+ stream = H3_STREAM_CTX(ctx, ctx->curl_items[idx_count]);
+ nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
+ stream->s.send_blocked = FALSE;
+ h3_drain_stream(cf, ctx->curl_items[idx_count]);
+ CURL_TRC_CF(ctx->curl_items[idx_count], cf, "unblocked");
+ result_count--;
+ }
+ }
}
- return CURLE_OK;
+
+out:
+ return res;
}
static CURLcode h3_send_streams(struct Curl_cfilter *cf,
@@ -1504,7 +1560,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf, bool blocked = FALSE, eos_written = FALSE;
n = nghttp3_conn_writev_stream(ctx->h3.conn, &stream_id, &eos,
- vec, ARRAYSIZE(vec));
+ vec, CURL_ARRAYSIZE(vec));
if(n < 0) {
failf(data, "nghttp3_conn_writev_stream returned error: %s",
nghttp3_strerror((int)n));
@@ -1924,7 +1980,7 @@ static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, ssize_t nwritten;
CURLcode result;
- (void)eos; /* TODO: use to end stream */
+ (void)eos; /* use to end stream */
CF_DATA_SAVE(save, cf, data);
DEBUGASSERT(cf->connected);
DEBUGASSERT(ctx->tls.ossl.ssl);
@@ -2139,9 +2195,6 @@ static CURLcode cf_osslq_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DETACH:
- h3_data_done(cf, data);
- break;
case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
@@ -2301,6 +2354,9 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf, *when = ctx->handshake_at;
return CURLE_OK;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 30;
+ return CURLE_OK;
default:
break;
}
@@ -2311,7 +2367,7 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_http3 = {
"HTTP/3",
- CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
0,
cf_osslq_destroy,
cf_osslq_connect,
diff --git a/libs/libcurl/src/vquic/curl_quiche.c b/libs/libcurl/src/vquic/curl_quiche.c index 8cdd512dd0..d4824958de 100644 --- a/libs/libcurl/src/vquic/curl_quiche.c +++ b/libs/libcurl/src/vquic/curl_quiche.c @@ -926,8 +926,8 @@ static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf, nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id,
(uint8_t *)buf, len, eos);
if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) {
- /* TODO: we seem to be blocked on flow control and should HOLD
- * sending. But when do we open again? */
+ /* Blocked on flow control and should HOLD sending. But when do we open
+ * again? */
if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
"-> window exhausted", stream->id, len);
@@ -1204,8 +1204,8 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf, struct Curl_easy *data,
bool pause)
{
- /* TODO: there seems right now no API in quiche to shrink/enlarge
- * the streams windows. As we do in HTTP/2. */
+ /* There seems to exist no API in quiche to shrink/enlarge the streams
+ * windows. As we do in HTTP/2. */
if(!pause) {
h3_drain_stream(cf, data);
Curl_expire(data, 0, EXPIRE_RUN_NOW);
@@ -1228,9 +1228,6 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DETACH:
- h3_data_done(cf, data);
- break;
case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
@@ -1278,10 +1275,6 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf, if(result)
return result;
- result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
- if(result)
- return result;
-
ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
if(!ctx->cfg) {
failf(data, "cannot create quiche config");
@@ -1313,7 +1306,7 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf, result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
QUICHE_H3_APPLICATION_PROTOCOL,
sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
- NULL, NULL, cf);
+ NULL, NULL, cf, NULL);
if(result)
return result;
@@ -1379,7 +1372,6 @@ static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf, struct cf_quiche_ctx *ctx = cf->ctx;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
}
@@ -1573,6 +1565,9 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf, *when = ctx->handshake_at;
return CURLE_OK;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 30;
+ return CURLE_OK;
default:
break;
}
@@ -1620,7 +1615,7 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_http3 = {
"HTTP/3",
- CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
0,
cf_quiche_destroy,
cf_quiche_connect,
diff --git a/libs/libcurl/src/vquic/vquic-tls.c b/libs/libcurl/src/vquic/vquic-tls.c index b246d7fdc3..d92df69cea 100644 --- a/libs/libcurl/src/vquic/vquic-tls.c +++ b/libs/libcurl/src/vquic/vquic-tls.c @@ -50,6 +50,7 @@ #include "multiif.h"
#include "vtls/keylog.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "vquic-tls.h"
/* The last 3 #include files should be in this order */
@@ -57,10 +58,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
#if defined(USE_WOLFSSL)
#define QUIC_CIPHERS \
@@ -221,7 +218,7 @@ static CURLcode wssl_init_ssl(struct curl_tls_ctx *ctx, }
if(ssl_config->primary.cache_session) {
- (void)wssl_setup_session(cf, data, &ctx->wssl, peer);
+ (void)Curl_wssl_setup_session(cf, data, &ctx->wssl, peer->scache_key);
}
return CURLE_OK;
@@ -234,25 +231,43 @@ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx, struct ssl_peer *peer,
const char *alpn, size_t alpn_len,
Curl_vquic_tls_ctx_setup *cb_setup,
- void *cb_user_data, void *ssl_user_data)
+ void *cb_user_data, void *ssl_user_data,
+ Curl_vquic_session_reuse_cb *session_reuse_cb)
{
+ char tls_id[80];
CURLcode result;
#ifdef USE_OPENSSL
+ Curl_ossl_version(tls_id, sizeof(tls_id));
+#elif defined(USE_GNUTLS)
+ Curl_gtls_version(tls_id, sizeof(tls_id));
+#elif defined(USE_WOLFSSL)
+ Curl_wssl_version(tls_id, sizeof(tls_id));
+#else
+#error "no TLS lib in used, should not happen"
+ return CURLE_FAILED_INIT;
+#endif
+ (void)session_reuse_cb;
+ result = Curl_ssl_peer_init(peer, cf, tls_id, TRNSPRT_QUIC);
+ if(result)
+ return result;
+
+#ifdef USE_OPENSSL
(void)result;
- return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, TRNSPRT_QUIC,
+ return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer,
(const unsigned char *)alpn, alpn_len,
cb_setup, cb_user_data, NULL, ssl_user_data);
#elif defined(USE_GNUTLS)
- (void)result;
return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
- (const unsigned char *)alpn, alpn_len, NULL,
- cb_setup, cb_user_data, ssl_user_data);
+ (const unsigned char *)alpn, alpn_len,
+ cb_setup, cb_user_data, ssl_user_data,
+ session_reuse_cb);
#elif defined(USE_WOLFSSL)
result = wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
if(result)
return result;
+ (void)session_reuse_cb;
return wssl_init_ssl(ctx, cf, data, peer, alpn, alpn_len, ssl_user_data);
#else
#error "no TLS lib in used, should not happen"
@@ -346,6 +361,9 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx, }
#endif
+ /* on error, remove any session we might have in the pool */
+ if(result)
+ Curl_ssl_scache_remove_all(cf, data, peer->scache_key);
return result;
}
diff --git a/libs/libcurl/src/vquic/vquic-tls.h b/libs/libcurl/src/vquic/vquic-tls.h index 558170810b..8b250f2245 100644 --- a/libs/libcurl/src/vquic/vquic-tls.h +++ b/libs/libcurl/src/vquic/vquic-tls.h @@ -26,6 +26,7 @@ #include "curl_setup.h"
#include "bufq.h"
+#include "vtls/vtls.h"
#include "vtls/openssl.h"
#if defined(USE_HTTP3) && \
@@ -33,6 +34,9 @@ #include "vtls/wolfssl.h"
+struct ssl_peer;
+struct Curl_ssl_session;
+
struct curl_tls_ctx {
#ifdef USE_OPENSSL
struct ossl_ctx ossl;
@@ -54,6 +58,11 @@ typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf, struct Curl_easy *data,
void *cb_user_data);
+typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct Curl_ssl_session *scs,
+ bool *do_early_data);
+
/**
* Initialize the QUIC TLS instances based of the SSL configurations
* for the connection filter, transfer and peer.
@@ -65,8 +74,9 @@ typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf, * may be NULL
* @param alpn_len the overall number of bytes in `alpn`
* @param cb_setup optional callback for early TLS config
- ± @param cb_user_data user_data param for callback
+ * @param cb_user_data user_data param for callback
* @param ssl_user_data optional pointer to set in TLS application context
+ * @param session_reuse_cb callback to handle session reuse, signal early data
*/
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
@@ -75,7 +85,8 @@ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx, const char *alpn, size_t alpn_len,
Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_user_data,
- void *ssl_user_data);
+ void *ssl_user_data,
+ Curl_vquic_session_reuse_cb *session_reuse_cb);
/**
* Cleanup all data that has been initialized.
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c index 960c710170..44f29963d1 100644 --- a/libs/libcurl/src/vquic/vquic.c +++ b/libs/libcurl/src/vquic/vquic.c @@ -53,12 +53,6 @@ #ifdef USE_HTTP3
-#ifdef O_BINARY
-#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
-#else
-#define QLOGMODE O_WRONLY|O_CREAT
-#endif
-
#define NW_CHUNK_SIZE (64 * 1024)
#define NW_SEND_CHUNKS 2
@@ -169,7 +163,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, case EIO:
if(pktlen > gsolen) {
/* GSO failure */
- failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
+ infof(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
SOCKERRNO);
qctx->no_gso = TRUE;
return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
@@ -248,6 +242,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, /* simulate network blocking/partial writes */
if(qctx->wblock_percent > 0) {
unsigned char c;
+ *psent = 0;
Curl_rand(data, &c, 1);
if(c >= ((100-qctx->wblock_percent)*256/100)) {
CURL_TRC_CF(data, cf, "vquic_flush() simulate EWOULDBLOCK");
@@ -363,7 +358,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf, struct mmsghdr mmsg[MMSG_NUM];
uint8_t msg_ctrl[MMSG_NUM * CMSG_SPACE(sizeof(int))];
struct sockaddr_storage remote_addr[MMSG_NUM];
- size_t total_nread = 0, pkts;
+ size_t total_nread = 0, pkts = 0;
int mcount, i, n;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
@@ -380,7 +375,6 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf, goto out;
bufs = (uint8_t (*)[64*1024])sockbuf;
- pkts = 0;
total_nread = 0;
while(pkts < max_pkts) {
n = (int)CURLMIN(MMSG_NUM, max_pkts);
@@ -657,7 +651,7 @@ CURLcode Curl_qlogdir(struct Curl_easy *data, result = Curl_dyn_add(&fname, ".sqlog");
if(!result) {
- int qlogfd = open(Curl_dyn_ptr(&fname), QLOGMODE,
+ int qlogfd = open(Curl_dyn_ptr(&fname), O_WRONLY|O_CREAT|CURL_O_BINARY,
data->set.new_file_perms);
if(qlogfd != -1)
*qlogfdp = qlogfd;
@@ -695,24 +689,6 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf, #endif
}
-bool Curl_conn_is_http3(const struct Curl_easy *data,
- const struct connectdata *conn,
- int sockindex)
-{
-#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
- return Curl_conn_is_ngtcp2(data, conn, sockindex);
-#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
- return Curl_conn_is_osslq(data, conn, sockindex);
-#elif defined(USE_QUICHE)
- return Curl_conn_is_quiche(data, conn, sockindex);
-#elif defined(USE_MSH3)
- return Curl_conn_is_msh3(data, conn, sockindex);
-#else
- return ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- (conn->httpversion == 30));
-#endif
-}
-
CURLcode Curl_conn_may_http3(struct Curl_easy *data,
const struct connectdata *conn)
{
diff --git a/libs/libcurl/src/vquic/vquic.h b/libs/libcurl/src/vquic/vquic.h index dde9003fa3..8d7474fbdc 100644 --- a/libs/libcurl/src/vquic/vquic.h +++ b/libs/libcurl/src/vquic/vquic.h @@ -46,16 +46,8 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf, const struct Curl_addrinfo *ai,
int transport);
-bool Curl_conn_is_http3(const struct Curl_easy *data,
- const struct connectdata *conn,
- int sockindex);
-
extern struct Curl_cftype Curl_cft_http3;
-#else /* USE_HTTP3 */
-
-#define Curl_conn_is_http3(a,b,c) FALSE
-
#endif /* !USE_HTTP3 */
CURLcode Curl_conn_may_http3(struct Curl_easy *data,
diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index 2e84fbeea8..87ed34ee62 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -161,6 +161,7 @@ const struct Curl_handler Curl_handler_scp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
CURLPROTO_SCP, /* family */
@@ -189,6 +190,7 @@ const struct Curl_handler Curl_handler_sftp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -340,17 +342,11 @@ static int myssh_is_known(struct Curl_easy *data) struct curl_khkey *knownkeyp = NULL;
curl_sshkeycallback func =
data->set.ssh_keyfunc;
-
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
struct ssh_knownhosts_entry *knownhostsentry = NULL;
struct curl_khkey knownkey;
-#endif
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
rc = ssh_get_server_publickey(sshc->ssh_session, &pubkey);
-#else
- rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
-#endif
+
if(rc != SSH_OK)
return rc;
@@ -386,7 +382,6 @@ static int myssh_is_known(struct Curl_easy *data) if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
/* Get the known_key from the known hosts file */
vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
&knownhostsentry);
@@ -444,22 +439,6 @@ static int myssh_is_known(struct Curl_easy *data) break;
}
-#else
- vstate = ssh_is_server_known(sshc->ssh_session);
- switch(vstate) {
- case SSH_SERVER_KNOWN_OK:
- keymatch = CURLKHMATCH_OK;
- break;
- case SSH_SERVER_FILE_NOT_FOUND:
- case SSH_SERVER_NOT_KNOWN:
- keymatch = CURLKHMATCH_MISSING;
- break;
- default:
- keymatch = CURLKHMATCH_MISMATCH;
- break;
- }
-#endif
-
if(func) { /* use callback to determine action */
rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
if(rc != SSH_OK)
@@ -476,18 +455,14 @@ static int myssh_is_known(struct Curl_easy *data) foundkey.keytype = CURLKHTYPE_RSA1;
break;
case SSH_KEYTYPE_ECDSA:
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
case SSH_KEYTYPE_ECDSA_P256:
case SSH_KEYTYPE_ECDSA_P384:
case SSH_KEYTYPE_ECDSA_P521:
-#endif
foundkey.keytype = CURLKHTYPE_ECDSA;
break;
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
case SSH_KEYTYPE_ED25519:
foundkey.keytype = CURLKHTYPE_ED25519;
break;
-#endif
case SSH_KEYTYPE_DSS:
foundkey.keytype = CURLKHTYPE_DSS;
break;
@@ -504,11 +479,7 @@ static int myssh_is_known(struct Curl_easy *data) switch(rc) {
case CURLKHSTAT_FINE_ADD_TO_FILE:
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
rc = ssh_session_update_known_hosts(sshc->ssh_session);
-#else
- rc = ssh_write_knownhost(sshc->ssh_session);
-#endif
if(rc != SSH_OK) {
goto cleanup;
}
@@ -539,11 +510,9 @@ cleanup: if(hash)
ssh_clean_pubkey_hash(&hash);
ssh_key_free(pubkey);
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
if(knownhostsentry) {
ssh_knownhosts_entry_free(knownhostsentry);
}
-#endif
return rc;
}
@@ -1846,7 +1815,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) }
rc = ssh_scp_push_file(sshc->scp_session, protop->path,
- data->state.infilesize,
+ (size_t)data->state.infilesize,
(int)data->set.new_file_perms);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index ee3847324b..a75397e95c 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -83,15 +83,6 @@ #include "curl_memory.h"
#include "memdebug.h"
-#if LIBSSH2_VERSION_NUM >= 0x010206
-/* libssh2_sftp_statvfs and friends were added in 1.2.6 */
-#define HAS_STATVFS_SUPPORT 1
-#endif
-
-#define sftp_libssh2_realpath(s,p,t,m) \
- libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
- (t), (m), LIBSSH2_SFTP_REALPATH)
-
/* Local functions: */
static const char *sftp_libssh2_strerror(unsigned long err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
@@ -139,6 +130,7 @@ const struct Curl_handler Curl_handler_scp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ssh_attach, /* attach */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
CURLPROTO_SCP, /* family */
@@ -169,6 +161,7 @@ const struct Curl_handler Curl_handler_sftp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ssh_attach, /* attach */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -387,8 +380,6 @@ static void state(struct Curl_easy *data, sshstate nowstate) sshc->state = nowstate;
}
-
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
static int sshkeycallback(CURL *easy,
const struct curl_khkey *knownkey, /* known */
const struct curl_khkey *foundkey, /* found */
@@ -403,37 +394,7 @@ static int sshkeycallback(CURL *easy, /* we only allow perfect matches, and we reject everything else */
return (match != CURLKHMATCH_OK) ? CURLKHSTAT_REJECT : CURLKHSTAT_FINE;
}
-#endif
-
-/*
- * Earlier libssh2 versions did not have the ability to seek to 64-bit
- * positions with 32-bit size_t.
- */
-#ifdef HAVE_LIBSSH2_SFTP_SEEK64
-#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
-#else
-#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
-#endif
-/*
- * Earlier libssh2 versions did not do SCP properly beyond 32-bit sizes on
- * 32-bit architectures so we check of the necessary function is present.
- */
-#ifndef HAVE_LIBSSH2_SCP_SEND64
-#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
-#else
-#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
- (libssh2_int64_t)d, 0, 0)
-#endif
-
-/*
- * libssh2 1.2.8 fixed the problem with 32-bit ints used for sockets on win64.
- */
-#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
-#define session_startup(x,y) libssh2_session_handshake(x, y)
-#else
-#define session_startup(x,y) libssh2_session_startup(x, (int)y)
-#endif
static enum curl_khtype convert_ssh2_keytype(int sshkeytype)
{
enum curl_khtype keytype = CURLKHTYPE_UNKNOWN;
@@ -475,7 +436,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) int rc = 0;
CURLcode result = CURLE_OK;
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
/* we are asked to verify the host against a file */
struct connectdata *conn = data->conn;
@@ -535,7 +495,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) /* no check means failure! */
rc = CURLKHSTAT_REJECT;
else {
-#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
keycheck = libssh2_knownhost_checkp(sshc->kh,
conn->host.name,
(conn->remote_port != PORT_SSH) ?
@@ -545,15 +504,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) LIBSSH2_KNOWNHOST_KEYENC_RAW|
keybit,
&host);
-#else
- keycheck = libssh2_knownhost_check(sshc->kh,
- conn->host.name,
- remotekey, keylen,
- LIBSSH2_KNOWNHOST_TYPE_PLAIN|
- LIBSSH2_KNOWNHOST_KEYENC_RAW|
- keybit,
- &host);
-#endif
infof(data, "SSH host check: %d, key: %s", keycheck,
(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) ?
@@ -637,9 +587,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) break;
}
}
-#else /* HAVE_LIBSSH2_KNOWNHOST_API */
- (void)data;
-#endif
return result;
}
@@ -817,8 +764,6 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) {
CURLcode result = CURLE_OK;
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
-
#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
static const char * const hostkey_method_ssh_ed25519
= "ssh-ed25519";
@@ -914,12 +859,10 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) break;
#endif
case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
-#ifdef HAVE_LIBSSH2_VERSION
if(libssh2_version(0x010900))
/* since 1.9.0 libssh2_session_method_pref() works as expected */
hostkey_method = hostkey_method_ssh_rsa_all;
else
-#endif
/* old libssh2 which cannot correctly remove unsupported methods due
* to bug in src/kex.c or does not support the new methods anyways.
*/
@@ -954,8 +897,6 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) }
}
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
-
return result;
}
@@ -1092,12 +1033,10 @@ static CURLcode sftp_quote(struct Curl_easy *data, state(data, SSH_SFTP_QUOTE_UNLINK);
return result;
}
-#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
state(data, SSH_SFTP_QUOTE_STATVFS);
return result;
}
-#endif
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
@@ -1262,7 +1201,8 @@ sftp_upload_init(struct Curl_easy *data, Curl_pgrsSetUploadSize(data, data->state.infilesize);
}
- SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ libssh2_sftp_seek64(sshc->sftp_handle,
+ (libssh2_uint64_t)data->state.resume_from);
}
if(data->state.infilesize > 0) {
data->req.size = data->state.infilesize;
@@ -1563,7 +1503,7 @@ sftp_download_stat(struct Curl_easy *data, size = to - from + 1;
}
- SFTP_SEEK(sshc->sftp_handle, from);
+ libssh2_sftp_seek64(sshc->sftp_handle, (libssh2_uint64_t)from);
}
data->req.size = size;
data->req.maxdownload = size;
@@ -1596,7 +1536,8 @@ sftp_download_stat(struct Curl_easy *data, data->req.maxdownload = attrs.filesize - data->state.resume_from;
Curl_pgrsSetDownloadSize(data,
attrs.filesize - data->state.resume_from);
- SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ libssh2_sftp_seek64(sshc->sftp_handle,
+ (libssh2_uint64_t)data->state.resume_from);
}
/* Setup the actual download */
@@ -1668,10 +1609,10 @@ static CURLcode sftp_readdir(struct Curl_easy *data, return result;
}
}
- else if(rc == 0) {
+ else if(!rc) {
state(data, SSH_SFTP_READDIR_DONE);
}
- else if(rc < 0) {
+ else {
unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result ? result : CURLE_SSH;
@@ -1721,7 +1662,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) FALLTHROUGH();
case SSH_S_STARTUP:
- rc = session_startup(sshc->ssh_session, conn->sock[FIRSTSOCKET]);
+ rc = libssh2_session_handshake(sshc->ssh_session,
+ conn->sock[FIRSTSOCKET]);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1876,7 +1818,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) break;
case SSH_AUTH_AGENT_INIT:
-#ifdef HAVE_LIBSSH2_AGENT_API
if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
&& (strstr(sshc->authlist, "publickey") != NULL)) {
@@ -1906,12 +1847,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) }
}
else
-#endif /* HAVE_LIBSSH2_AGENT_API */
state(data, SSH_AUTH_KEY_INIT);
break;
case SSH_AUTH_AGENT_LIST:
-#ifdef HAVE_LIBSSH2_AGENT_API
rc = libssh2_agent_list_identities(sshc->ssh_agent);
if(rc == LIBSSH2_ERROR_EAGAIN)
@@ -1925,11 +1864,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) state(data, SSH_AUTH_AGENT);
sshc->sshagent_prev_identity = NULL;
}
-#endif
break;
case SSH_AUTH_AGENT:
-#ifdef HAVE_LIBSSH2_AGENT_API
/* as prev_identity evolves only after an identity user auth finished we
can safely request it again as long as EAGAIN is returned here or by
libssh2_agent_userauth */
@@ -1966,7 +1903,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
-#endif
break;
case SSH_AUTH_KEY_INIT:
@@ -2049,8 +1985,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) /*
* Get the "home" directory
*/
- rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
- sshp->readdir_filename, CURL_PATH_MAX);
+ rc = libssh2_sftp_symlink_ex(sshc->sftp_session,
+ ".", curlx_uztoui(strlen(".")),
+ sshp->readdir_filename, CURL_PATH_MAX,
+ LIBSSH2_SFTP_REALPATH);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -2286,7 +2224,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_NEXT_QUOTE);
break;
-#ifdef HAS_STATVFS_SUPPORT
case SSH_SFTP_QUOTE_STATVFS:
{
LIBSSH2_SFTP_STATVFS statvfs;
@@ -2349,7 +2286,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
-#endif
+
case SSH_SFTP_GETINFO:
{
if(data->set.get_filetime) {
@@ -2682,8 +2619,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) * directory in the path.
*/
sshc->ssh_channel =
- SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
- data->state.infilesize);
+ libssh2_scp_send64(sshc->ssh_session, sshp->path,
+ (int)data->set.new_file_perms,
+ (libssh2_int64_t)data->state.infilesize, 0, 0);
if(!sshc->ssh_channel) {
int ssh_err;
char *err_msg = NULL;
@@ -2918,14 +2856,11 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) break;
case SSH_SESSION_FREE:
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(sshc->kh) {
libssh2_knownhost_free(sshc->kh);
sshc->kh = NULL;
}
-#endif
-#ifdef HAVE_LIBSSH2_AGENT_API
if(sshc->ssh_agent) {
rc = libssh2_agent_disconnect(sshc->ssh_agent);
if(rc == LIBSSH2_ERROR_EAGAIN) {
@@ -2946,7 +2881,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) sshc->sshagent_identity = NULL;
sshc->sshagent_prev_identity = NULL;
}
-#endif
if(sshc->ssh_session) {
rc = libssh2_session_free(sshc->ssh_session);
@@ -2968,12 +2902,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) DEBUGASSERT(sshc->ssh_channel == NULL);
DEBUGASSERT(sshc->sftp_session == NULL);
DEBUGASSERT(sshc->sftp_handle == NULL);
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
DEBUGASSERT(sshc->kh == NULL);
-#endif
-#ifdef HAVE_LIBSSH2_AGENT_API
DEBUGASSERT(sshc->ssh_agent == NULL);
-#endif
Curl_safefree(sshc->rsa_pub);
Curl_safefree(sshc->rsa);
@@ -3323,14 +3253,11 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) conn->send[FIRSTSOCKET] = sftp_send;
}
- if(data->set.ssh_compression) {
-#if LIBSSH2_VERSION_NUM >= 0x010208
- if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
-#endif
- infof(data, "Failed to enable compression for ssh session");
+ if(data->set.ssh_compression &&
+ libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) {
+ infof(data, "Failed to enable compression for ssh session");
}
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
int rc;
sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
@@ -3348,7 +3275,6 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) infof(data, "Failed to read known hosts from %s",
data->set.str[STRING_SSH_KNOWNHOSTS]);
}
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
#ifdef CURL_LIBSSH2_DEBUG
libssh2_trace(sshc->ssh_session, ~0);
@@ -3759,25 +3685,21 @@ static const char *sftp_libssh2_strerror(unsigned long err) CURLcode Curl_ssh_init(void)
{
-#ifdef HAVE_LIBSSH2_INIT
if(libssh2_init(0)) {
DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
return CURLE_FAILED_INIT;
}
-#endif
return CURLE_OK;
}
void Curl_ssh_cleanup(void)
{
-#ifdef HAVE_LIBSSH2_EXIT
(void)libssh2_exit();
-#endif
}
void Curl_ssh_version(char *buffer, size_t buflen)
{
- (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
+ (void)msnprintf(buffer, buflen, "libssh2/%s", libssh2_version(0));
}
/* The SSH session is associated with the *CONNECTION* but the callback user
diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index 3178e305bd..4f13ffbb0c 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -201,17 +201,10 @@ struct ssh_conn { Curl_send *tls_send;
#endif
-#ifdef HAVE_LIBSSH2_AGENT_API
LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */
- struct libssh2_agent_publickey *sshagent_identity,
- *sshagent_prev_identity;
-#endif
-
- /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
- header */
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ struct libssh2_agent_publickey *sshagent_identity;
+ struct libssh2_agent_publickey *sshagent_prev_identity;
LIBSSH2_KNOWNHOSTS *kh;
-#endif
#elif defined(USE_WOLFSSH)
WOLFSSH *ssh_session;
WOLFSSH_CTX *ctx;
@@ -221,43 +214,20 @@ struct ssh_conn { #endif /* USE_LIBSSH */
};
-#if defined(USE_LIBSSH2)
-
-/* Feature detection based on version numbers to better work with
- non-configure platforms */
-
-#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000)
-# error "SCP/SFTP protocols require libssh2 0.16 or later"
+#ifdef USE_LIBSSH
+#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 9, 0)
+# error "SCP/SFTP protocols require libssh 0.9.0 or later"
#endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010000
-#define HAVE_LIBSSH2_SFTP_SEEK64 1
#endif
-#if LIBSSH2_VERSION_NUM >= 0x010100
-#define HAVE_LIBSSH2_VERSION 1
-#endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010205
-#define HAVE_LIBSSH2_INIT 1
-#define HAVE_LIBSSH2_EXIT 1
-#endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010206
-#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1
-#define HAVE_LIBSSH2_SCP_SEND64 1
-#endif
+#if defined(USE_LIBSSH2)
-#if LIBSSH2_VERSION_NUM >= 0x010208
-#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1
-#endif
+/* Feature detection based on version numbers to better work with
+ non-configure platforms */
-#ifdef HAVE_LIBSSH2_VERSION
-/* get it runtime if possible */
-#define CURL_LIBSSH2_VERSION libssh2_version(0)
-#else
-/* use build-time if runtime not possible */
-#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
+#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x010208)
+# error "SCP/SFTP protocols require libssh2 1.2.8 or later"
+/* 1.2.8 was released on April 5 2011 */
#endif
#endif /* USE_LIBSSH2 */
diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index 377aa99bcc..910e5c6d6d 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -95,6 +95,7 @@ const struct Curl_handler Curl_handler_scp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
@@ -125,6 +126,7 @@ const struct Curl_handler Curl_handler_sftp = { ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index f4d0cc43b3..24a0ea0646 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -34,6 +34,7 @@ #include "inet_pton.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
@@ -609,20 +610,19 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
if(ssl_config->primary.cache_session) {
- void *sdata;
- size_t slen;
+ struct Curl_ssl_session *sc_session = NULL;
const br_ssl_session_parameters *session;
- CURL_TRC_CF(data, cf, "connect_step1, check session cache");
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, &sdata, &slen, NULL) &&
- slen == sizeof(*session)) {
- session = sdata;
+ ret = Curl_ssl_scache_take(cf, data, connssl->peer.scache_key,
+ &sc_session);
+ if(!ret && sc_session && sc_session->sdata && sc_session->sdata_len) {
+ session = (br_ssl_session_parameters *)(void *)sc_session->sdata;
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
session_set = 1;
infof(data, "BearSSL: reusing session ID");
+ /* single use of sessions */
+ Curl_ssl_scache_return(cf, data, connssl->peer.scache_key, sc_session);
}
- Curl_ssl_sessionid_unlock(data);
}
if(connssl->alpn) {
@@ -804,12 +804,6 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf, return ret;
}
-static void bearssl_session_free(void *sessionid, size_t idsize)
-{
- (void)idsize;
- free(sessionid);
-}
-
static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -832,17 +826,22 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf, }
if(ssl_config->primary.cache_session) {
+ struct Curl_ssl_session *sc_session;
br_ssl_session_parameters *session;
session = malloc(sizeof(*session));
if(!session)
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
- Curl_ssl_sessionid_lock(data);
- ret = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
- session, sizeof(*session),
- bearssl_session_free);
- Curl_ssl_sessionid_unlock(data);
+ ret = Curl_ssl_session_create((unsigned char *)session, sizeof(*session),
+ (int)session->version,
+ connssl->negotiated.alpn,
+ 0, 0, &sc_session);
+ if(!ret) {
+ ret = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key,
+ sc_session);
+ /* took ownership of `sc_session` */
+ }
if(ret)
return ret;
}
@@ -1154,27 +1153,24 @@ const struct Curl_ssl Curl_ssl_bearssl = { sizeof(struct bearssl_ssl_backend_data),
- Curl_none_init, /* init */
- Curl_none_cleanup, /* cleanup */
+ NULL, /* init */
+ NULL, /* cleanup */
bearssl_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
bearssl_shutdown, /* shutdown */
bearssl_data_pending, /* data_pending */
bearssl_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
bearssl_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
bearssl_recv, /* recv decrypted data */
bearssl_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index 398af77bf3..56bae80332 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -47,12 +47,14 @@ #include "gtls.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "vauth/vauth.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "progress.h"
#include "select.h"
#include "strcase.h"
+#include "strdup.h"
#include "warnless.h"
#include "x509asn1.h"
#include "multiif.h"
@@ -61,10 +63,6 @@ /* The last #include file should be: */
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
#define QUIC_PRIORITY \
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
@@ -714,21 +712,20 @@ CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf, return CURLE_OK;
}
-static void gtls_sessionid_free(void *sessionid, size_t idsize)
-{
- (void)idsize;
- free(sessionid);
-}
-
-CURLcode Curl_gtls_update_session_id(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- gnutls_session_t session,
- struct ssl_peer *peer,
- const char *alpn)
+CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ gnutls_session_t session,
+ curl_off_t valid_until,
+ const char *alpn,
+ unsigned char *quic_tp,
+ size_t quic_tp_len)
{
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- void *connect_sessionid;
- size_t connect_idsize = 0;
+ struct Curl_ssl_session *sc_session;
+ unsigned char *sdata, *qtp_clone = NULL;
+ size_t sdata_len = 0;
+ size_t earlydata_max = 0;
CURLcode result = CURLE_OK;
if(!ssl_config->primary.cache_session)
@@ -740,35 +737,68 @@ CURLcode Curl_gtls_update_session_id(struct Curl_cfilter *cf, detect that. */
/* get the session ID data size */
- gnutls_session_get_data(session, NULL, &connect_idsize);
- if(!connect_idsize) /* gnutls does this for some version combinations */
+ gnutls_session_get_data(session, NULL, &sdata_len);
+ if(!sdata_len) /* gnutls does this for some version combinations */
return CURLE_OK;
- connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
- if(!connect_sessionid)
+ sdata = malloc(sdata_len); /* get a buffer for it */
+ if(!sdata)
return CURLE_OUT_OF_MEMORY;
/* extract session ID to the allocated buffer */
- gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
-
- CURL_TRC_CF(data, cf, "get session id (len=%zu, alpn=%s) and store in cache",
- connect_idsize, alpn ? alpn : "-");
- Curl_ssl_sessionid_lock(data);
- /* store this session id, takes ownership */
- result = Curl_ssl_set_sessionid(cf, data, peer, alpn,
- connect_sessionid, connect_idsize,
- gtls_sessionid_free);
- Curl_ssl_sessionid_unlock(data);
+ gnutls_session_get_data(session, sdata, &sdata_len);
+ earlydata_max = gnutls_record_get_max_early_data_size(session);
+
+ CURL_TRC_CF(data, cf, "get session id (len=%zu, alpn=%s, earlymax=%zu) "
+ "and store in cache", sdata_len, alpn ? alpn : "-",
+ earlydata_max);
+ if(quic_tp && quic_tp_len) {
+ qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len);
+ if(!qtp_clone) {
+ free(sdata);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ result = Curl_ssl_session_create2(sdata, sdata_len,
+ Curl_glts_get_ietf_proto(session),
+ alpn, valid_until, earlydata_max,
+ qtp_clone, quic_tp_len,
+ &sc_session);
+ /* call took ownership of `sdata` and `qtp_clone` */
+ if(!result) {
+ result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
+ /* took ownership of `sc_session` */
+ }
return result;
}
+int Curl_glts_get_ietf_proto(gnutls_session_t session)
+{
+ switch(gnutls_protocol_get_version(session)) {
+ case GNUTLS_SSL3:
+ return CURL_IETF_PROTO_SSL3;
+ case GNUTLS_TLS1_0:
+ return CURL_IETF_PROTO_TLS1;
+ case GNUTLS_TLS1_1:
+ return CURL_IETF_PROTO_TLS1_1;
+ case GNUTLS_TLS1_2:
+ return CURL_IETF_PROTO_TLS1_2;
+ case GNUTLS_TLS1_3:
+ return CURL_IETF_PROTO_TLS1_3;
+ default:
+ return CURL_IETF_PROTO_UNKNOWN;
+ }
+}
+
static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf,
struct Curl_easy *data,
gnutls_session_t session)
{
struct ssl_connect_data *connssl = cf->ctx;
- return Curl_gtls_update_session_id(cf, data, session, &connssl->peer,
- connssl->alpn_negotiated);
+ return Curl_gtls_cache_session(cf, data, connssl->peer.scache_key,
+ session, 0, connssl->negotiated.alpn,
+ NULL, 0);
}
static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
@@ -800,6 +830,7 @@ static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype, static CURLcode gtls_client_init(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
+ size_t earlydata_max,
struct gtls_ctx *gtls)
{
struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
@@ -853,6 +884,14 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, /* Initialize TLS session as a client */
init_flags = GNUTLS_CLIENT;
+ if(peer->transport == TRNSPRT_QUIC && earlydata_max > 0)
+ init_flags |= GNUTLS_ENABLE_EARLY_DATA | GNUTLS_NO_END_OF_EARLY_DATA;
+ else if(earlydata_max > 0 && earlydata_max != 0xFFFFFFFFUL)
+ /* See https://gitlab.com/gnutls/gnutls/-/issues/1619
+ * We cannot differentiate between a session announcing no earldata
+ * and one announcing 0xFFFFFFFFUL. On TCP+TLS, this is unlikely, but
+ * on QUIC this is common. */
+ init_flags |= GNUTLS_ENABLE_EARLY_DATA;
#if defined(GNUTLS_FORCE_CLIENT_CERT)
init_flags |= GNUTLS_FORCE_CLIENT_CERT;
@@ -874,6 +913,8 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, init_flags |= GNUTLS_NO_STATUS_REQUEST;
#endif
+ CURL_TRC_CF(data, cf, "gnutls_init(flags=%x), earlydata=%zu",
+ init_flags, earlydata_max);
rc = gnutls_init(>ls->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc);
@@ -1046,96 +1087,129 @@ static int keylog_callback(gnutls_session_t session, const char *label, return 0;
}
+static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct Curl_ssl_session *scs,
+ bool *do_early_data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ CURLcode result = CURLE_OK;
+
+ *do_early_data = FALSE;
+ connssl->earlydata_max =
+ gnutls_record_get_max_early_data_size(backend->gtls.session);
+ if((!connssl->earlydata_max || connssl->earlydata_max == 0xFFFFFFFFUL)) {
+ /* Seems to be GnuTLS way to signal no EarlyData in session */
+ CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
+ }
+ else if(!Curl_alpn_contains_proto(connssl->alpn, scs->alpn)) {
+ CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data");
+ }
+ else {
+ infof(data, "SSL session allows %zu bytes of early data, "
+ "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
+ connssl->earlydata_state = ssl_earlydata_use;
+ connssl->state = ssl_connection_deferred;
+ result = Curl_alpn_set_negotiated(cf, data, connssl,
+ (const unsigned char *)scs->alpn,
+ scs->alpn ? strlen(scs->alpn) : 0);
+ *do_early_data = !result;
+ }
+ return result;
+}
+
CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const unsigned char *alpn, size_t alpn_len,
- struct ssl_connect_data *connssl,
Curl_gtls_ctx_setup_cb *cb_setup,
void *cb_user_data,
- void *ssl_user_data)
+ void *ssl_user_data,
+ Curl_gtls_init_session_reuse_cb *sess_reuse_cb)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct Curl_ssl_session *scs = NULL;
gnutls_datum_t gtls_alpns[5];
size_t gtls_alpns_count = 0;
+ bool gtls_session_setup = FALSE;
CURLcode result;
+ int rc;
DEBUGASSERT(gctx);
-
- result = gtls_client_init(cf, data, peer, gctx);
- if(result)
- return result;
-
- gnutls_session_set_ptr(gctx->session, ssl_user_data);
-
- if(cb_setup) {
- result = cb_setup(cf, data, cb_user_data);
+ /* This might be a reconnect, so we check for a session ID in the cache
+ to speed up things. We need to do this before constructing the gnutls
+ session since we need to set flags depending on the kind of reuse. */
+ if(conn_config->cache_session) {
+ result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
if(result)
- return result;
- }
+ goto out;
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
- gnutls_session_set_keylog_function(gctx->session, keylog_callback);
- }
+ if(scs && scs->sdata && scs->sdata_len) {
+ /* we got a cached session, use it! */
- /* This might be a reconnect, so we check for a session ID in the cache
- to speed up things */
- if(conn_config->cache_session) {
- void *ssl_sessionid;
- size_t ssl_idsize;
- char *session_alpn;
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, peer,
- &ssl_sessionid, &ssl_idsize, &session_alpn)) {
- /* we got a session id, use it! */
- int rc;
-
- rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
+ result = gtls_client_init(cf, data, peer, scs->earlydata_max, gctx);
+ if(result)
+ goto out;
+ gtls_session_setup = TRUE;
+
+ rc = gnutls_session_set_data(gctx->session, scs->sdata, scs->sdata_len);
if(rc < 0)
- infof(data, "SSL failed to set session ID");
+ infof(data, "SSL session not accepted by GnuTLS, continuing without");
else {
- infof(data, "SSL reusing session ID (size=%zu, alpn=%s)",
- ssl_idsize, session_alpn ? session_alpn : "-");
-#ifdef DEBUGBUILD
- if((ssl_config->earlydata || !!getenv("CURL_USE_EARLYDATA")) &&
-#else
+ infof(data, "SSL reusing session with ALPN '%s'",
+ scs->alpn ? scs->alpn : "-");
if(ssl_config->earlydata &&
-#endif
- !cf->conn->connect_only && connssl &&
- (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3) &&
- Curl_alpn_contains_proto(connssl->alpn, session_alpn)) {
- connssl->earlydata_max =
- gnutls_record_get_max_early_data_size(gctx->session);
- if((!connssl->earlydata_max ||
- connssl->earlydata_max == 0xFFFFFFFFUL)) {
- /* Seems to be GnuTLS way to signal no EarlyData in session */
- CURL_TRC_CF(data, cf, "TLS session does not allow earlydata");
- }
- else {
- CURL_TRC_CF(data, cf, "TLS session allows %zu earlydata bytes, "
- "reusing ALPN '%s'",
- connssl->earlydata_max, session_alpn);
- connssl->earlydata_state = ssl_earlydata_use;
- connssl->state = ssl_connection_deferred;
- result = Curl_alpn_set_negotiated(cf, data, connssl,
- (const unsigned char *)session_alpn,
- session_alpn ? strlen(session_alpn) : 0);
+ !cf->conn->connect_only &&
+ (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3)) {
+ bool do_early_data = FALSE;
+ if(sess_reuse_cb) {
+ result = sess_reuse_cb(cf, data, scs, &do_early_data);
if(result)
- return result;
+ goto out;
+ }
+ if(do_early_data) {
/* We only try the ALPN protocol the session used before,
* otherwise we might send early data for the wrong protocol */
- gtls_alpns[0].data = (unsigned char *)session_alpn;
- gtls_alpns[0].size = (unsigned)strlen(session_alpn);
- gtls_alpns_count = 1;
+ gtls_alpns[0].data = (unsigned char *)scs->alpn;
+ gtls_alpns[0].size = (unsigned)strlen(scs->alpn);
+ if(gnutls_alpn_set_protocols(gctx->session,
+ gtls_alpns, 1,
+ GNUTLS_ALPN_MANDATORY)) {
+ failf(data, "failed setting ALPN");
+ result = CURLE_SSL_CONNECT_ERROR;
+ goto out;
+ }
+ /* don't set again below */
+ gtls_alpns_count = 0;
+ alpn = NULL;
}
}
}
}
- Curl_ssl_sessionid_unlock(data);
+ }
+
+ if(!gtls_session_setup) {
+ result = gtls_client_init(cf, data, peer, 0, gctx);
+ if(result)
+ goto out;
+ }
+
+ gnutls_session_set_ptr(gctx->session, ssl_user_data);
+
+ if(cb_setup) {
+ result = cb_setup(cf, data, cb_user_data);
+ if(result)
+ goto out;
+ }
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ gnutls_session_set_keylog_function(gctx->session, keylog_callback);
}
/* convert the ALPN string from our arguments to a list of strings that
@@ -1143,19 +1217,21 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx, * to the server. nice. */
if(!gtls_alpns_count && alpn && alpn_len) {
size_t i, alen = alpn_len;
- unsigned char *s = (unsigned char *)alpn;
+ unsigned char *salpn = (unsigned char *)alpn;
unsigned char slen;
- for(i = 0; (i < ARRAYSIZE(gtls_alpns)) && alen; ++i) {
- slen = s[0];
+ for(i = 0; (i < CURL_ARRAYSIZE(gtls_alpns)) && alen; ++i) {
+ slen = salpn[0];
if(slen >= alen)
return CURLE_FAILED_INIT;
- gtls_alpns[i].data = s + 1;
+ gtls_alpns[i].data = salpn + 1;
gtls_alpns[i].size = slen;
- s += slen + 1;
+ salpn += slen + 1;
alen -= (size_t)slen + 1;
}
- if(alen) /* not all alpn chars used, wrong format or too many */
- return CURLE_FAILED_INIT;
+ if(alen) { /* not all alpn chars used, wrong format or too many */
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
gtls_alpns_count = i;
}
@@ -1164,10 +1240,12 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx, gtls_alpns, (unsigned int)gtls_alpns_count,
GNUTLS_ALPN_MANDATORY)) {
failf(data, "failed setting ALPN");
- return CURLE_SSL_CONNECT_ERROR;
+ result = CURLE_SSL_CONNECT_ERROR;
}
- return CURLE_OK;
+out:
+ Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
+ return result;
}
static CURLcode
@@ -1197,7 +1275,8 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) }
result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
- proto.data, proto.len, connssl, NULL, NULL, cf);
+ proto.data, proto.len,
+ NULL, NULL, cf, gtls_on_session_reuse);
if(result)
return result;
@@ -1886,6 +1965,9 @@ gtls_connect_common(struct Curl_cfilter *cf, goto out;
if(connssl->earlydata_state == ssl_earlydata_sent) {
+ /* report the true time the handshake was done */
+ connssl->handshake_done = Curl_now();
+ Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
if(gnutls_session_get_flags(backend->gtls.session) &
GNUTLS_SFLAGS_EARLY_DATA) {
connssl->earlydata_state = ssl_earlydata_accepted;
@@ -2213,7 +2295,7 @@ out: return ret;
}
-static size_t gtls_version(char *buffer, size_t size)
+size_t Curl_gtls_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
@@ -2268,8 +2350,7 @@ const struct Curl_ssl Curl_ssl_gnutls = { gtls_init, /* init */
gtls_cleanup, /* cleanup */
- gtls_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
+ Curl_gtls_version, /* version */
gtls_shutdown, /* shutdown */
gtls_data_pending, /* data_pending */
gtls_random, /* random */
@@ -2279,14 +2360,12 @@ const struct Curl_ssl Curl_ssl_gnutls = { Curl_ssl_adjust_pollset, /* adjust_pollset */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
gtls_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
gtls_recv, /* recv decrypted data */
gtls_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/gtls.h b/libs/libcurl/src/vtls/gtls.h index 4f3c089bc6..7a45758a32 100644 --- a/libs/libcurl/src/vtls/gtls.h +++ b/libs/libcurl/src/vtls/gtls.h @@ -46,6 +46,9 @@ struct ssl_primary_config; struct ssl_config_data;
struct ssl_peer;
struct ssl_connect_data;
+struct Curl_ssl_session;
+
+int Curl_glts_get_ietf_proto(gnutls_session_t session);
struct gtls_shared_creds {
gnutls_certificate_credentials_t creds;
@@ -70,19 +73,26 @@ struct gtls_ctx { BIT(sent_shutdown);
};
+size_t Curl_gtls_version(char *buffer, size_t size);
+
typedef CURLcode Curl_gtls_ctx_setup_cb(struct Curl_cfilter *cf,
struct Curl_easy *data,
void *user_data);
+typedef CURLcode Curl_gtls_init_session_reuse_cb(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct Curl_ssl_session *scs,
+ bool *do_early_data);
+
CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const unsigned char *alpn, size_t alpn_len,
- struct ssl_connect_data *connssl,
Curl_gtls_ctx_setup_cb *cb_setup,
void *cb_user_data,
- void *ssl_user_data);
+ void *ssl_user_data,
+ Curl_gtls_init_session_reuse_cb *sess_reuse_cb);
CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -96,11 +106,14 @@ CURLcode Curl_gtls_verifyserver(struct Curl_easy *data, const char *pinned_key);
/* Extract TLS session and place in cache, if configured. */
-CURLcode Curl_gtls_update_session_id(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- gnutls_session_t session,
- struct ssl_peer *peer,
- const char *alpn);
+CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ gnutls_session_t session,
+ curl_off_t valid_until,
+ const char *alpn,
+ unsigned char *quic_tp,
+ size_t quic_tp_len);
extern const struct Curl_ssl Curl_ssl_gnutls;
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index ae2acdb0a0..c0e98e12c5 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -64,6 +64,7 @@ #include "mbedtls.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "x509asn1.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
@@ -78,11 +79,8 @@ #include "memdebug.h"
/* ALPN for http2 */
-#ifdef USE_HTTP2
-# undef HAS_ALPN
-# ifdef MBEDTLS_SSL_ALPN
-# define HAS_ALPN
-# endif
+#if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN)
+# define HAS_ALPN_MBEDTLS
#endif
struct mbed_ssl_backend_data {
@@ -96,33 +94,40 @@ struct mbed_ssl_backend_data { #endif
mbedtls_pk_context pk;
mbedtls_ssl_config config;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
const char *protocols[3];
#endif
int *ciphersuites;
+ size_t send_blocked_len;
BIT(initialized); /* mbedtls_ssl_context is initialized */
BIT(sent_shutdown);
+ BIT(send_blocked);
};
/* apply threading? */
-#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
- defined(_WIN32)
-#define THREADING_SUPPORT
+#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+ defined(_WIN32)
+#define HAS_THREADING_SUPPORT
#endif
#ifndef MBEDTLS_ERROR_C
#define mbedtls_strerror(a,b,c) b[0] = 0
#endif
+/* PSA can be used independently of TLS 1.3 */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && MBEDTLS_VERSION_NUMBER >= 0x03060000
+#define HAS_PSA_SUPPORT
+#endif
+
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
-#define TLS13_SUPPORT
+#define HAS_TLS13_SUPPORT
#endif
-#if defined(TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(HAS_TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
#define HAS_SESSION_TICKETS
#endif
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
static mbedtls_entropy_context ts_entropy;
static int entropy_init_initialized = 0;
@@ -160,7 +165,7 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len) return ret;
}
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
#ifdef MBEDTLS_DEBUG
static void mbed_debug(void *context, int level, const char *f_name,
@@ -290,7 +295,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, /* ver_min = MBEDTLS_SSL_VERSION_TLS1_2; */
break;
case CURL_SSLVERSION_TLSv1_3:
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
ver_min = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -304,7 +309,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, case CURL_SSLVERSION_MAX_DEFAULT:
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_TLSv1_3:
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -395,7 +400,7 @@ mbed_set_selected_ciphers(struct Curl_easy *data, if(!selected)
return CURLE_OUT_OF_MEMORY;
-#ifndef TLS13_SUPPORT
+#ifndef HAS_TLS13_SUPPORT
(void) ciphers13, (void) j;
#else
if(!ciphers13) {
@@ -443,7 +448,7 @@ add_ciphers: selected[count++] = id;
}
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
if(ciphers == ciphers13 && ciphers12) {
ciphers = ciphers12;
goto add_ciphers;
@@ -585,7 +590,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_NOT_BUILT_IN;
}
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
mbedtls_ctr_drbg_init(&backend->ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
@@ -608,7 +613,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) -ret, errorbuf);
return CURLE_FAILED_INIT;
}
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
/* Load the trusted CA */
mbedtls_x509_crt_init(&backend->cacert);
@@ -802,7 +807,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED
+#if defined(HAS_SESSION_TICKETS) && MBEDTLS_VERSION_NUMBER >= 0x03060100
/* New in mbedTLS 3.6.1, need to enable, default is now disabled */
mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
@@ -841,7 +846,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_bio_cf_read,
NULL /* rev_timeout() */);
-#ifndef TLS13_SUPPORT
+#ifndef HAS_TLS13_SUPPORT
if(conn_config->cipher_list) {
CURLcode result = mbed_set_selected_ciphers(data, backend,
conn_config->cipher_list,
@@ -875,29 +880,30 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* Check if there is a cached ID we can/should use here! */
if(ssl_config->primary.cache_session) {
- void *sdata = NULL;
- size_t slen = 0;
+ struct Curl_ssl_session *sc_session = NULL;
+ CURLcode result;
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &sdata, &slen, NULL) && slen) {
+ result = Curl_ssl_scache_take(cf, data, connssl->peer.scache_key,
+ &sc_session);
+ if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
mbedtls_ssl_session session;
mbedtls_ssl_session_init(&session);
- ret = mbedtls_ssl_session_load(&session, sdata, slen);
+ ret = mbedtls_ssl_session_load(&session, sc_session->sdata,
+ sc_session->sdata_len);
if(ret) {
- failf(data, "error loading cached session: -0x%x", -ret);
+ failf(data, "SSL session error loading: -0x%x", -ret);
}
else {
ret = mbedtls_ssl_set_session(&backend->ssl, &session);
if(ret)
- failf(data, "error setting session: -0x%x", -ret);
+ failf(data, "SSL session error setting: -0x%x", -ret);
else
infof(data, "SSL reusing session ID");
}
mbedtls_ssl_session_free(&session);
}
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_return(cf, data, connssl->peer.scache_key, sc_session);
}
mbedtls_ssl_conf_ca_chain(&backend->config,
@@ -922,7 +928,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
if(connssl->alpn) {
struct alpn_proto_buf proto;
size_t i;
@@ -1100,7 +1106,7 @@ pinnedpubkey_error: }
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
if(connssl->alpn) {
const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
@@ -1115,12 +1121,6 @@ pinnedpubkey_error: return CURLE_OK;
}
-static void mbedtls_session_free(void *session, size_t slen)
-{
- (void)slen;
- free(session);
-}
-
static CURLcode
mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
{
@@ -1128,48 +1128,64 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) struct mbed_ssl_backend_data *backend =
(struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ mbedtls_ssl_session session;
+ bool msession_alloced = FALSE;
+ struct Curl_ssl_session *sc_session = NULL;
+ unsigned char *sdata = NULL;
+ size_t slen = 0;
+ int ietf_tls_id;
CURLcode result = CURLE_OK;
+ int ret;
DEBUGASSERT(backend);
- if(ssl_config->primary.cache_session) {
- int ret;
- mbedtls_ssl_session session;
- unsigned char *sdata = NULL;
- size_t slen = 0;
+ if(!ssl_config->primary.cache_session)
+ return CURLE_OK;
- mbedtls_ssl_session_init(&session);
- ret = mbedtls_ssl_get_session(&backend->ssl, &session);
- if(ret) {
- if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
- mbedtls_ssl_session_free(&session);
- failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
- return CURLE_SSL_CONNECT_ERROR;
- }
+ mbedtls_ssl_session_init(&session);
+ ret = mbedtls_ssl_get_session(&backend->ssl, &session);
+ msession_alloced = (ret != MBEDTLS_ERR_SSL_ALLOC_FAILED);
+ if(ret) {
+ failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
+ result = CURLE_SSL_CONNECT_ERROR;
+ goto out;
+ }
- mbedtls_ssl_session_save(&session, NULL, 0, &slen);
- if(!slen) {
- failf(data, "failed to serialize session: length is 0");
- }
- else {
- sdata = malloc(slen);
- if(sdata) {
- ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
- if(ret) {
- failf(data, "failed to serialize session: -0x%x", -ret);
- }
- else {
- Curl_ssl_sessionid_lock(data);
- result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
- sdata, slen, mbedtls_session_free);
- Curl_ssl_sessionid_unlock(data);
- if(!result)
- sdata = NULL;
- }
- }
- }
- mbedtls_ssl_session_free(&session);
- free(sdata);
+ mbedtls_ssl_session_save(&session, NULL, 0, &slen);
+ if(!slen) {
+ failf(data, "failed to serialize session: length is 0");
+ goto out;
+ }
+
+ sdata = malloc(slen);
+ if(!sdata) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
+ if(ret) {
+ failf(data, "failed to serialize session: -0x%x", -ret);
+ goto out;
}
+
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+ ietf_tls_id = mbedtls_ssl_get_version_number(&backend->ssl);
+#else
+ ietf_tls_id = CURL_IETF_PROTO_UNKNOWN;
+#endif
+ result = Curl_ssl_session_create(sdata, slen,
+ ietf_tls_id,
+ connssl->negotiated.alpn, 0, 0,
+ &sc_session);
+ sdata = NULL; /* call took ownership */
+ if(!result)
+ result = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key,
+ sc_session);
+
+out:
+ if(msession_alloced)
+ mbedtls_ssl_session_free(&session);
+ free(sdata);
return result;
}
@@ -1184,27 +1200,41 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, (void)data;
DEBUGASSERT(backend);
+ /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked.
+ * It requires to be called with the same amount of bytes again, or it
+ * will lose bytes, e.g. reporting all was sent but they were not.
+ * Remember the blocked length and use that when set. */
+ if(backend->send_blocked) {
+ DEBUGASSERT(backend->send_blocked_len <= len);
+ CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> previously blocked "
+ "on %zu bytes", len, backend->send_blocked_len);
+ len = backend->send_blocked_len;
+ }
+
ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
if(ret < 0) {
CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
len, -ret);
*curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
|| (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
#endif
) ? CURLE_AGAIN : CURLE_SEND_ERROR;
ret = -1;
+ if((*curlcode == CURLE_AGAIN) && !backend->send_blocked) {
+ backend->send_blocked = TRUE;
+ backend->send_blocked_len = len;
+ }
+ }
+ else {
+ CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d", len, ret);
+ backend->send_blocked = FALSE;
}
return ret;
}
-static void mbedtls_close_all(struct Curl_easy *data)
-{
- (void)data;
-}
-
static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool send_shutdown, bool *done)
@@ -1260,7 +1290,7 @@ static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf, * WANT_READ, but has not encountered an EAGAIN. */
if(ret == MBEDTLS_ERR_SSL_WANT_READ)
ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
continue;
#endif
@@ -1314,9 +1344,9 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_ssl_config_free(&backend->config);
mbedtls_ssl_free(&backend->ssl);
mbedtls_ctr_drbg_free(&backend->ctr_drbg);
-#ifndef THREADING_SUPPORT
+#ifndef HAS_THREADING_SUPPORT
mbedtls_entropy_free(&backend->entropy);
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
backend->initialized = FALSE;
}
}
@@ -1558,29 +1588,29 @@ static int mbedtls_init(void) {
if(!Curl_mbedtlsthreadlock_thread_setup())
return 0;
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
entropy_init_mutex(&ts_entropy);
#endif
-#ifdef TLS13_SUPPORT
+#ifdef HAS_PSA_SUPPORT
{
int ret;
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
Curl_mbedtlsthreadlock_lock_function(0);
#endif
ret = psa_crypto_init();
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
Curl_mbedtlsthreadlock_unlock_function(0);
#endif
if(ret != PSA_SUCCESS)
return 0;
}
-#endif /* TLS13_SUPPORT */
+#endif /* HAS_PSA_SUPPORT */
return 1;
}
static void mbedtls_cleanup(void)
{
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
entropy_cleanup_mutex(&ts_entropy);
#endif
(void)Curl_mbedtlsthreadlock_thread_cleanup();
@@ -1603,7 +1633,6 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input, unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
- /* TODO: explain this for different mbedtls 2.x vs 3 version */
(void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
@@ -1637,7 +1666,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = { SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
SSLSUPP_TLS13_CIPHERSUITES |
#endif
SSLSUPP_HTTPS_PROXY |
@@ -1648,24 +1677,21 @@ const struct Curl_ssl Curl_ssl_mbedtls = { mbedtls_init, /* init */
mbedtls_cleanup, /* cleanup */
mbedtls_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
mbedtls_shutdown, /* shutdown */
mbedtls_data_pending, /* data_pending */
mbedtls_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
- mbedtls_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
mbedtls_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
mbed_recv, /* recv decrypted data */
mbed_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index ed4dd5df1f..97c25ef655 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -56,6 +56,7 @@ #include "select.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "vauth/vauth.h"
#include "keylog.h"
#include "strcase.h"
@@ -82,16 +83,15 @@ #include <openssl/tls1.h>
#include <openssl/evp.h>
-#ifdef USE_ECH
+#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST)
+#define USE_ECH_OPENSSL
+#endif
+
+#ifdef USE_ECH_OPENSSL
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
# include <openssl/ech.h>
# endif
-# include "curl_base64.h"
-# define ECH_ENABLED(__data__) \
- (__data__->set.tls_ech && \
- !(__data__->set.tls_ech & CURLECH_DISABLE)\
- )
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
@@ -103,16 +103,19 @@ #include <openssl/engine.h>
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x03000000fL && !defined(OPENSSL_NO_UI_CONSOLE)
+#include <openssl/provider.h>
+#include <openssl/store.h>
+/* this is used in the following conditions to make them easier to read */
+#define OPENSSL_HAS_PROVIDERS
+#endif
+
#include "warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
with HTTP/2 and "an extremely dangerous protocol feature". Beware.
@@ -124,7 +127,7 @@ #error "OPENSSL_VERSION_NUMBER not defined"
#endif
-#ifdef USE_OPENSSL_ENGINE
+#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
#include <openssl/ui.h>
#endif
@@ -172,10 +175,6 @@ #define HAVE_X509_GET0_SIGNATURE 1
#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */
-#define HAVE_SSL_GET_SHUTDOWN 1
-#endif
-
#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \
OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \
!defined(OPENSSL_NO_COMP)
@@ -200,18 +199,6 @@ #define FREE_PKEY_PARAM_BIGNUM(name)
#endif
-/*
- * Whether SSL_CTX_set_keylog_callback is available.
- * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
- * BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: not supported. 3.5.0+ has a stub function that does nothing.
- */
-#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
- !defined(LIBRESSL_VERSION_NUMBER)) || \
- defined(OPENSSL_IS_BORINGSSL)
-#define HAVE_KEYLOG_CALLBACK
-#endif
-
/* Whether SSL_CTX_set_ciphersuites is available.
* OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
* BoringSSL: no
@@ -739,7 +726,7 @@ static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr) #ifdef BIO_CTRL_EOF
case BIO_CTRL_EOF:
/* EOF has been reached on input? */
- return (!cf->next || !cf->next->connected);
+ return !cf->next || !cf->next->connected;
#endif
default:
ret = 0;
@@ -960,8 +947,6 @@ static const char *SSL_ERROR_to_str(int err) }
}
-static size_t ossl_version(char *buffer, size_t size);
-
/* Return error string for last OpenSSL error
*/
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
@@ -970,7 +955,7 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size) DEBUGASSERT(size);
*buf = '\0';
- len = ossl_version(buf, size);
+ len = Curl_ossl_version(buf, size);
DEBUGASSERT(len < (size - 2));
if(len < (size - 2)) {
buf += len;
@@ -1015,7 +1000,7 @@ static int passwd_callback(char *buf, int num, int encrypting, */
static bool rand_enough(void)
{
- return (0 != RAND_status());
+ return 0 != RAND_status();
}
static CURLcode ossl_seed(struct Curl_easy *data)
@@ -1071,8 +1056,8 @@ static CURLcode ossl_seed(struct Curl_easy *data) }
infof(data, "libcurl is now using a weak random seed");
- return (rand_enough() ? CURLE_OK :
- CURLE_SSL_CONNECT_ERROR /* confusing error code */);
+ return rand_enough() ? CURLE_OK :
+ CURLE_SSL_CONNECT_ERROR; /* confusing error code */
#endif
}
@@ -1082,6 +1067,9 @@ static CURLcode ossl_seed(struct Curl_easy *data) #ifndef SSL_FILETYPE_PKCS12
#define SSL_FILETYPE_PKCS12 43
#endif
+#ifndef SSL_FILETYPE_PROVIDER
+#define SSL_FILETYPE_PROVIDER 44
+#endif
static int ossl_do_file_type(const char *type)
{
if(!type || !type[0])
@@ -1090,6 +1078,8 @@ static int ossl_do_file_type(const char *type) return SSL_FILETYPE_PEM;
if(strcasecompare(type, "DER"))
return SSL_FILETYPE_ASN1;
+ if(strcasecompare(type, "PROV"))
+ return SSL_FILETYPE_PROVIDER;
if(strcasecompare(type, "ENG"))
return SSL_FILETYPE_ENGINE;
if(strcasecompare(type, "P12"))
@@ -1097,7 +1087,7 @@ static int ossl_do_file_type(const char *type) return -1;
}
-#ifdef USE_OPENSSL_ENGINE
+#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
/*
* Supply default password to the engine user interface conversation.
* The password is passed by OpenSSL engine from ENGINE_load_private_key()
@@ -1145,12 +1135,16 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis) */
static bool is_pkcs11_uri(const char *string)
{
- return (string && strncasecompare(string, "pkcs11:", 7));
+ return string && strncasecompare(string, "pkcs11:", 7);
}
#endif
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);
+#if !defined(USE_OPENSSL_ENGINE) && defined(OPENSSL_HAS_PROVIDERS)
+static CURLcode ossl_set_provider(struct Curl_easy *data,
+ const char *provider);
+#endif
static int use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob,
int type, const char *key_passwd)
@@ -1299,9 +1293,12 @@ int cert_stuff(struct Curl_easy *data, int file_type = ossl_do_file_type(cert_type);
- if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE)) {
+ if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE) ||
+ (file_type == SSL_FILETYPE_PROVIDER)) {
SSL *ssl;
- X509 *x509;
+ X509 *x509 = NULL;
+ EVP_PKEY *pri = NULL;
+ STACK_OF(X509) *ca = NULL;
int cert_done = 0;
int cert_use_result;
@@ -1410,8 +1407,79 @@ int cert_stuff(struct Curl_easy *data, }
}
break;
+#elif defined(OPENSSL_HAS_PROVIDERS)
+ /* fall through to compatible provider */
+ case SSL_FILETYPE_PROVIDER:
+ {
+ /* Implicitly use pkcs11 provider if none was provided and the
+ * cert_file is a PKCS#11 URI */
+ if(!data->state.provider) {
+ if(is_pkcs11_uri(cert_file)) {
+ if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
+ if(data->state.provider) {
+ /* Load the certificate from the provider */
+ OSSL_STORE_CTX *store = NULL;
+ OSSL_STORE_INFO *info = NULL;
+ X509 *cert = NULL;
+ store = OSSL_STORE_open(cert_file, NULL, NULL, NULL, NULL);
+ if(!store) {
+ failf(data, "Failed to open OpenSSL store: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return 0;
+ }
+ if(OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) != 1) {
+ failf(data, "Failed to set store preference. Ignoring the error: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ }
+
+ for(info = OSSL_STORE_load(store);
+ info != NULL;
+ info = OSSL_STORE_load(store)) {
+ int ossl_type = OSSL_STORE_INFO_get_type(info);
+
+ if(ossl_type == OSSL_STORE_INFO_CERT) {
+ cert = OSSL_STORE_INFO_get1_CERT(info);
+ }
+ else {
+ failf(data, "Ignoring object not matching our type: %d",
+ ossl_type);
+ OSSL_STORE_INFO_free(info);
+ continue;
+ }
+ OSSL_STORE_INFO_free(info);
+ break;
+ }
+ OSSL_STORE_close(store);
+ if(!cert) {
+ failf(data, "No cert found in the openssl store: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ goto fail;
+ }
+
+ if(SSL_CTX_use_certificate(ctx, cert) != 1) {
+ failf(data, "unable to set client certificate [%s]",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return 0;
+ }
+ X509_free(cert); /* we do not need the handle any more... */
+ }
+ else {
+ failf(data, "crypto provider not set, cannot load certificate");
+ return 0;
+ }
+ }
+ break;
#else
- failf(data, "file type ENG for certificate not implemented");
+ failf(data, "file type ENG nor PROV for certificate not implemented");
return 0;
#endif
@@ -1419,8 +1487,6 @@ int cert_stuff(struct Curl_easy *data, {
BIO *cert_bio = NULL;
PKCS12 *p12 = NULL;
- EVP_PKEY *pri;
- STACK_OF(X509) *ca = NULL;
if(cert_blob) {
cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len));
if(!cert_bio) {
@@ -1461,8 +1527,7 @@ int cert_stuff(struct Curl_easy *data, PKCS12_PBE_add();
- if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
- &ca)) {
+ if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) {
failf(data,
"could not parse PKCS12 file, check password, " OSSL_PACKAGE
" error %s",
@@ -1603,10 +1668,96 @@ fail: }
}
break;
+#elif defined(OPENSSL_HAS_PROVIDERS)
+ /* fall through to compatible provider */
+ case SSL_FILETYPE_PROVIDER:
+ {
+ /* Implicitly use pkcs11 provider if none was provided and the
+ * cert_file is a PKCS#11 URI */
+ if(!data->state.provider) {
+ if(is_pkcs11_uri(cert_file)) {
+ if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
+ if(data->state.provider) {
+ /* Load the private key from the provider */
+ EVP_PKEY *priv_key = NULL;
+ OSSL_STORE_CTX *store = NULL;
+ OSSL_STORE_INFO *info = NULL;
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"curl user interface");
+ if(!ui_method) {
+ failf(data, "unable do create " OSSL_PACKAGE
+ " user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
+
+ store = OSSL_STORE_open(key_file, ui_method, NULL, NULL, NULL);
+ if(!store) {
+ failf(data, "Failed to open OpenSSL store: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return 0;
+ }
+ if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) {
+ failf(data, "Failed to set store preference. Ignoring the error: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ }
+
+ for(info = OSSL_STORE_load(store);
+ info != NULL;
+ info = OSSL_STORE_load(store)) {
+ int ossl_type = OSSL_STORE_INFO_get_type(info);
+
+ if(ossl_type == OSSL_STORE_INFO_PKEY) {
+ priv_key = OSSL_STORE_INFO_get1_PKEY(info);
+ }
+ else {
+ failf(data, "Ignoring object not matching our type: %d",
+ ossl_type);
+ OSSL_STORE_INFO_free(info);
+ continue;
+ }
+ OSSL_STORE_INFO_free(info);
+ break;
+ }
+ OSSL_STORE_close(store);
+ UI_destroy_method(ui_method);
+ if(!priv_key) {
+ failf(data, "No private key found in the openssl store: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ goto fail;
+ }
+
+ if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
+ failf(data, "unable to set private key [%s]",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ EVP_PKEY_free(priv_key);
+ return 0;
+ }
+ EVP_PKEY_free(priv_key); /* we do not need the handle any more... */
+ }
+ else {
+ failf(data, "crypto provider not set, cannot load private key");
+ return 0;
+ }
+ }
+ break;
#else
- failf(data, "file type ENG for private key not supported");
+ failf(data, "file type ENG nor PROV for private key not implemented");
return 0;
#endif
+
case SSL_FILETYPE_PKCS12:
if(!cert_done) {
failf(data, "file type P12 for private key not supported");
@@ -1874,6 +2025,38 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data) return list;
}
+#if !defined(USE_OPENSSL_ENGINE) && defined(OPENSSL_HAS_PROVIDERS)
+/* Selects an OpenSSL crypto provider
+ */
+static CURLcode ossl_set_provider(struct Curl_easy *data, const char *provider)
+{
+ OSSL_PROVIDER *pkcs11_provider = NULL;
+ char error_buffer[256];
+
+ if(OSSL_PROVIDER_available(NULL, provider)) {
+ /* already loaded through the configuration - no action needed */
+ data->state.provider = TRUE;
+ return CURLE_OK;
+ }
+ if(data->state.provider_failed) {
+ return CURLE_SSL_ENGINE_NOTFOUND;
+ }
+
+ pkcs11_provider = OSSL_PROVIDER_try_load(NULL, provider, 1);
+ if(!pkcs11_provider) {
+ failf(data, "Failed to initialize provider: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ /* Do not attempt to load it again */
+ data->state.provider_failed = TRUE;
+ return CURLE_SSL_ENGINE_NOTFOUND;
+ }
+ data->state.provider = TRUE;
+ return CURLE_OK;
+}
+#endif
+
+
static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool send_shutdown, bool *done)
@@ -2013,13 +2196,6 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data) }
}
-static void ossl_session_free(void *sessionid, size_t idsize)
-{
- /* free the ID */
- (void)idsize;
- free(sessionid);
-}
-
/*
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
@@ -2688,10 +2864,9 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, /* ====================================================== */
/* Check for OpenSSL 1.0.2 which has ALPN support. */
-#undef HAS_ALPN
#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
&& !defined(OPENSSL_NO_TLSEXT)
-# define HAS_ALPN 1
+# define HAS_ALPN_OPENSSL
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
@@ -2873,20 +3048,23 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
- const struct ssl_peer *peer,
- SSL_SESSION *session)
+ const char *ssl_peer_key,
+ SSL_SESSION *session,
+ int ietf_tls_id,
+ const char *alpn)
{
const struct ssl_config_data *config;
+ unsigned char *der_session_buf = NULL;
CURLcode result = CURLE_OK;
- size_t der_session_size;
- unsigned char *der_session_buf;
- unsigned char *der_session_ptr;
if(!cf || !data)
goto out;
config = Curl_ssl_cf_get_config(cf, data);
if(config->primary.cache_session) {
+ struct Curl_ssl_session *sc_session = NULL;
+ size_t der_session_size;
+ unsigned char *der_session_ptr;
der_session_size = i2d_SSL_SESSION(session, NULL);
if(der_session_size == 0) {
@@ -2903,17 +3081,23 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, der_session_size = i2d_SSL_SESSION(session, &der_session_ptr);
if(der_session_size == 0) {
result = CURLE_OUT_OF_MEMORY;
- free(der_session_buf);
goto out;
}
- Curl_ssl_sessionid_lock(data);
- result = Curl_ssl_set_sessionid(cf, data, peer, NULL, der_session_buf,
- der_session_size, ossl_session_free);
- Curl_ssl_sessionid_unlock(data);
+ result = Curl_ssl_session_create(der_session_buf, der_session_size,
+ ietf_tls_id, alpn,
+ (curl_off_t)time(NULL) +
+ SSL_SESSION_get_timeout(session), 0,
+ &sc_session);
+ der_session_buf = NULL; /* took ownership of sdata */
+ if(!result) {
+ result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
+ /* took ownership of `sc_session` */
+ }
}
out:
+ free(der_session_buf);
return result;
}
@@ -2922,14 +3106,13 @@ out: */
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
{
- struct Curl_cfilter *cf;
- struct Curl_easy *data;
- struct ssl_connect_data *connssl;
-
- cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
- connssl = cf ? cf->ctx : NULL;
- data = connssl ? CF_DATA_CURRENT(cf) : NULL;
- Curl_ossl_add_session(cf, data, &connssl->peer, ssl_sessionid);
+ struct Curl_cfilter *cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
+ if(cf) {
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ struct ssl_connect_data *connssl = cf->ctx;
+ Curl_ossl_add_session(cf, data, connssl->peer.scache_key, ssl_sessionid,
+ SSL_version(ssl), connssl->negotiated.alpn);
+ }
return 0;
}
@@ -3133,9 +3316,9 @@ static CURLcode import_windows_cert_store(struct Curl_easy *data, }
#endif
-static CURLcode populate_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- X509_STORE *store)
+static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
@@ -3151,7 +3334,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, bool imported_native_ca = FALSE;
bool imported_ca_info_blob = FALSE;
- CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+ CURL_TRC_CF(data, cf, "ossl_populate_x509_store, path=%s, blob=%d",
ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
@@ -3169,7 +3352,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, "CA" /* Intermediate Certification Authorities */
};
size_t i;
- for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+ for(i = 0; i < CURL_ARRAYSIZE(storeNames); ++i) {
bool imported = FALSE;
result = import_windows_cert_store(data, storeNames[i], store,
&imported);
@@ -3322,8 +3505,8 @@ static void oss_x509_share_free(void *key, size_t key_len, void *p) }
static bool
-cached_x509_store_expired(const struct Curl_easy *data,
- const struct ossl_x509_share *mb)
+ossl_cached_x509_store_expired(const struct Curl_easy *data,
+ const struct ossl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
if(cfg->ca_cache_timeout < 0)
@@ -3338,8 +3521,8 @@ cached_x509_store_expired(const struct Curl_easy *data, }
static bool
-cached_x509_store_different(struct Curl_cfilter *cf,
- const struct ossl_x509_share *mb)
+ossl_cached_x509_store_different(struct Curl_cfilter *cf,
+ const struct ossl_x509_share *mb)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
if(!mb->CAfile || !conn_config->CAfile)
@@ -3348,8 +3531,8 @@ cached_x509_store_different(struct Curl_cfilter *cf, return strcmp(mb->CAfile, conn_config->CAfile);
}
-static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
+static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct ossl_x509_share *share;
@@ -3360,17 +3543,17 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, (void *)MPROTO_OSSL_X509_KEY,
sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL;
if(share && share->store &&
- !cached_x509_store_expired(data, share) &&
- !cached_x509_store_different(cf, share)) {
+ !ossl_cached_x509_store_expired(data, share) &&
+ !ossl_cached_x509_store_different(cf, share)) {
store = share->store;
}
return store;
}
-static void set_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data,
- X509_STORE *store)
+static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
@@ -3438,16 +3621,16 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, !ssl_config->primary.CRLfile &&
!ssl_config->native_ca_store;
- cached_store = get_cached_x509_store(cf, data);
+ cached_store = ossl_get_cached_x509_store(cf, data);
if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
SSL_CTX_set_cert_store(ssl_ctx, cached_store);
}
else {
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
- result = populate_x509_store(cf, data, store);
+ result = ossl_populate_x509_store(cf, data, store);
if(result == CURLE_OK && cache_criteria_met) {
- set_cached_x509_store(cf, data, store);
+ ossl_set_cached_x509_store(cf, data, store);
}
}
@@ -3460,7 +3643,7 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, {
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
- return populate_x509_store(cf, data, store);
+ return ossl_populate_x509_store(cf, data, store);
}
#endif /* HAVE_SSL_X509_STORE_SHARE */
@@ -3468,7 +3651,6 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
- int transport, /* TCP or QUIC */
const unsigned char *alpn, size_t alpn_len,
Curl_ossl_ctx_setup_cb *cb_setup,
void *cb_user_data,
@@ -3479,12 +3661,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, const char *ciphers;
SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
ctx_option_t ctx_options = 0;
- SSL_SESSION *ssl_session = NULL;
- const unsigned char *der_sessionid = NULL;
- size_t der_sessionid_size = 0;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- const long int ssl_version_min = conn_config->version;
+ unsigned int ssl_version_min = conn_config->version;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
const char * const ssl_cert_type = ssl_config->cert_type;
@@ -3498,7 +3677,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, ssl_config->certverifyresult = !X509_V_OK;
- switch(transport) {
+ switch(peer->transport) {
case TRNSPRT_TCP:
/* check to see if we have been told to use an explicit SSL/TLS version */
switch(ssl_version_min) {
@@ -3527,6 +3706,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, }
break;
case TRNSPRT_QUIC:
+ ssl_version_min = CURL_SSLVERSION_TLSv1_3;
if(conn_config->version_max &&
(conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) {
failf(data, "QUIC needs at least TLS version 1.3");
@@ -3542,7 +3722,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, #endif
break;
default:
- failf(data, "unsupported transport %d in SSL init", transport);
+ failf(data, "unsupported transport %d in SSL init", peer->transport);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -3667,7 +3847,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, #endif
if(alpn && alpn_len) {
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
if(SSL_CTX_set_alpn_protos(octx->ssl_ctx, alpn, (int)alpn_len)) {
failf(data, "Error setting ALPN");
return CURLE_SSL_CONNECT_ERROR;
@@ -3690,7 +3870,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, ciphers = conn_config->cipher_list;
if(!ciphers && (peer->transport != TRNSPRT_QUIC))
ciphers = DEFAULT_CIPHER_SELECTION;
- if(ciphers) {
+ if(ciphers && (ssl_version_min < CURL_SSLVERSION_TLSv1_3)) {
if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
@@ -3701,7 +3881,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
{
const char *ciphers13 = conn_config->cipher_list13;
- if(ciphers13) {
+ if(ciphers13 &&
+ (!conn_config->version_max ||
+ (conn_config->version_max >= CURL_SSLVERSION_MAX_TLSv1_3))) {
if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) {
failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
return CURLE_SSL_CIPHER;
@@ -3832,7 +4014,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, }
}
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
if(ECH_ENABLED(data)) {
unsigned char *ech_config = NULL;
size_t ech_config_len = 0;
@@ -3865,7 +4047,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, }
if(SSL_set1_ech_config_list(octx->ssl, ech_config,
ech_config_len) != 1) {
- infof(data, "ECH: SSL_ECH_set1_echconfig failed");
+ infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
if(data->set.tls_ech & CURLECH_HARD) {
free(ech_config);
return CURLE_SSL_CONNECT_ERROR;
@@ -3880,8 +4062,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, return CURLE_SSL_CONNECT_ERROR;
}
ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
- if(SSL_ech_set1_echconfig(octx->ssl, ech_config, ech_config_len) != 1) {
- infof(data, "ECH: SSL_ECH_set1_echconfig failed");
+ if(SSL_set1_ech_config_list(octx->ssl, ech_config,
+ ech_config_len) != 1) {
+ infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
if(data->set.tls_ech & CURLECH_HARD)
return CURLE_SSL_CONNECT_ERROR;
}
@@ -3909,19 +4092,11 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, size_t elen = rinfo->echconfiglist_len;
infof(data, "ECH: ECHConfig from DoH HTTPS RR");
-# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
- if(SSL_ech_set1_echconfig(octx->ssl, ecl, elen) != 1) {
- infof(data, "ECH: SSL_ECH_set1_echconfig failed");
- if(data->set.tls_ech & CURLECH_HARD)
- return CURLE_SSL_CONNECT_ERROR;
- }
-# else
if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
- infof(data, "ECH: SSL_set1_ech_config_list failed (BoringSSL)");
+ infof(data, "ECH: SSL_set1_ech_config_list failed");
if(data->set.tls_ech & CURLECH_HARD)
return CURLE_SSL_CONNECT_ERROR;
}
-# endif
else {
trying_ech_now = 1;
infof(data, "ECH: imported ECHConfigList of length %zu", elen);
@@ -3944,7 +4119,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, if(trying_ech_now && outername) {
infof(data, "ECH: inner: '%s', outer: '%s'",
peer->hostname ? peer->hostname : "NULL", outername);
- result = SSL_ech_set_server_names(octx->ssl,
+ result = SSL_ech_set1_server_names(octx->ssl,
peer->hostname, outername,
0 /* do send outer */);
if(result != 1) {
@@ -3959,38 +4134,42 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, return CURLE_SSL_CONNECT_ERROR;
}
}
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
#endif
octx->reused_session = FALSE;
if(ssl_config->primary.cache_session) {
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, peer, (void **)&der_sessionid,
- &der_sessionid_size, NULL)) {
- /* we got a session id, use it! */
+ struct Curl_ssl_session *sc_session = NULL;
+
+ result = Curl_ssl_scache_take(cf, data, peer->scache_key, &sc_session);
+ if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
+ const unsigned char *der_sessionid = sc_session->sdata;
+ size_t der_sessionid_size = sc_session->sdata_len;
+ SSL_SESSION *ssl_session = NULL;
+
+ /* If OpenSSL does not accept the session from the cache, this
+ * is not an error. We just continue without it. */
ssl_session = d2i_SSL_SESSION(NULL, &der_sessionid,
- (long)der_sessionid_size);
+ (long)der_sessionid_size);
if(ssl_session) {
if(!SSL_set_session(octx->ssl, ssl_session)) {
- Curl_ssl_sessionid_unlock(data);
- SSL_SESSION_free(ssl_session);
- failf(data, "SSL: SSL_set_session failed: %s",
+ infof(data, "SSL: SSL_set_session not accepted, "
+ "continuing without: %s",
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ infof(data, "SSL reusing session");
+ octx->reused_session = TRUE;
}
SSL_SESSION_free(ssl_session);
- /* Informational message */
- infof(data, "SSL reusing session ID");
- octx->reused_session = TRUE;
}
else {
- Curl_ssl_sessionid_unlock(data);
- return CURLE_SSL_CONNECT_ERROR;
+ infof(data, "SSL session not accepted by OpenSSL, continuing without");
}
}
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_return(cf, data, peer->scache_key, sc_session);
}
return CURLE_OK;
@@ -4008,7 +4187,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
DEBUGASSERT(octx);
memset(&proto, 0, sizeof(proto));
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
if(connssl->alpn) {
result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
if(result) {
@@ -4018,7 +4197,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, }
#endif
- result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer, TRNSPRT_TCP,
+ result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
proto.data, proto.len, NULL, NULL,
ossl_new_session_cb, cf);
if(result)
@@ -4045,7 +4224,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_bio(octx->ssl, bio, bio);
#endif
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
if(connssl->alpn) {
Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
@@ -4055,7 +4234,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, return CURLE_OK;
}
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
/* If we have retry configs, then trace those out */
static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
int reason)
@@ -4079,35 +4258,33 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl, if(!ECH_ENABLED(data))
return;
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
- rv = SSL_ech_get_retry_config(ssl, &rcs, &rcl);
+ rv = SSL_ech_get1_retry_config(ssl, &rcs, &rcl);
# else
SSL_get0_ech_retry_configs(ssl, &rcs, &rcl);
rv = (int)rcl;
# endif
if(rv && rcs) {
-# define HEXSTR_MAX 800
char *b64str = NULL;
size_t blen = 0;
- result = Curl_base64_encode((const char *)rcs, rcl,
- &b64str, &blen);
- if(!result && b64str)
+ result = Curl_base64_encode((const char *)rcs, rcl, &b64str, &blen);
+ if(!result && b64str) {
infof(data, "ECH: retry_configs %s", b64str);
- free(b64str);
-# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
- rv = SSL_ech_get_status(ssl, &inner, &outer);
- infof(data, "ECH: retry_configs for %s from %s, %d %d",
- inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
-# else
- rv = SSL_ech_accepted(ssl);
- servername_type = SSL_get_servername_type(ssl);
- inner = SSL_get_servername(ssl, servername_type);
- SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
- /* TODO: get the inner from BoringSSL */
- infof(data, "ECH: retry_configs for %s from %s, %d %d",
- inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
-# endif
+ free(b64str);
+#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
+ rv = SSL_ech_get1_status(ssl, &inner, &outer);
+ infof(data, "ECH: retry_configs for %s from %s, %d %d",
+ inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
+#else
+ rv = SSL_ech_accepted(ssl);
+ servername_type = SSL_get_servername_type(ssl);
+ inner = SSL_get_servername(ssl, servername_type);
+ SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
+ infof(data, "ECH: retry_configs for %s from %s, %d %d",
+ inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
+#endif
+ }
}
else
infof(data, "ECH: no retry_configs (rv = %d)", rv);
@@ -4230,7 +4407,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
}
#endif
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
else if((lib == ERR_LIB_SSL) &&
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
(reason == SSL_R_ECH_REQUIRED)) {
@@ -4296,14 +4473,14 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, negotiated_group_name ? negotiated_group_name : "[blank]",
OBJ_nid2sn(psigtype_nid));
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
if(ECH_ENABLED(data)) {
char *inner = NULL, *outer = NULL;
const char *status = NULL;
int rv;
- rv = SSL_ech_get_status(octx->ssl, &inner, &outer);
+ rv = SSL_ech_get1_status(octx->ssl, &inner, &outer);
switch(rv) {
case SSL_ECH_STATUS_SUCCESS:
status = "succeeded";
@@ -4356,9 +4533,9 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, infof(data, "ECH: result: status is not attempted");
}
# endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
* negotiated
*/
@@ -4693,21 +4870,6 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf, /* do not do this after Session ID reuse */
result = verifystatus(cf, data, octx);
if(result) {
- /* when verifystatus failed, remove the session id from the cache again
- if present */
- if(!Curl_ssl_cf_is_proxy(cf)) {
- void *old_ssl_sessionid = NULL;
- bool incache;
- Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, peer,
- &old_ssl_sessionid, NULL, NULL));
- if(incache) {
- infof(data, "Remove session ID again from cache");
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
- }
- Curl_ssl_sessionid_unlock(data);
- }
-
X509_free(octx->server_cert);
octx->server_cert = NULL;
return result;
@@ -4757,6 +4919,9 @@ static CURLcode ossl_connect_step3(struct Curl_cfilter *cf, result = Curl_oss_check_peer_cert(cf, data, octx, &connssl->peer);
if(!result)
connssl->connecting_state = ssl_connect_done;
+ else
+ /* on error, remove sessions we might have in the pool */
+ Curl_ssl_scache_remove_all(cf, data, connssl->peer.scache_key);
return result;
}
@@ -5172,7 +5337,7 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, #endif
}
-static size_t ossl_version(char *buffer, size_t size)
+size_t Curl_ossl_version(char *buffer, size_t size)
{
#ifdef LIBRESSL_VERSION_NUMBER
#ifdef HAVE_OPENSSL_VERSION
@@ -5267,7 +5432,7 @@ static CURLcode ossl_random(struct Curl_easy *data, }
/* RAND_bytes() returns 1 on success, 0 otherwise. */
rc = RAND_bytes(entropy, (ossl_valsize_t)curlx_uztosi(length));
- return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
+ return rc == 1 ? CURLE_OK : CURLE_FAILED_INIT;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
@@ -5325,7 +5490,7 @@ const struct Curl_ssl Curl_ssl_openssl = { #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
SSLSUPP_TLS13_CIPHERSUITES |
#endif
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
SSLSUPP_ECH |
#endif
SSLSUPP_CA_CACHE |
@@ -5336,8 +5501,7 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_init, /* init */
ossl_cleanup, /* cleanup */
- ossl_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
+ Curl_ossl_version, /* version */
ossl_shutdown, /* shutdown */
ossl_data_pending, /* data_pending */
ossl_random, /* random */
@@ -5351,14 +5515,12 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_set_engine, /* set_engine */
ossl_set_engine_default, /* set_engine_default */
ossl_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* false_start */
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
ossl_sha256sum, /* sha256sum */
#else
NULL, /* sha256sum */
#endif
- NULL, /* use of data in this connection */
- NULL, /* remote of data from this connection */
ossl_recv, /* recv decrypted data */
ossl_send, /* send data to encrypt */
ossl_get_channel_binding /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/openssl.h b/libs/libcurl/src/vtls/openssl.h index e662e23a8d..bd5aafba96 100644 --- a/libs/libcurl/src/vtls/openssl.h +++ b/libs/libcurl/src/vtls/openssl.h @@ -31,12 +31,27 @@ * This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/opensslv.h>
#include <openssl/ossl_typ.h>
#include <openssl/ssl.h>
#include "urldata.h"
-/* Struct to hold a Curl OpenSSL instance */
+/*
+ * Whether SSL_CTX_set_keylog_callback is available.
+ * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
+ * BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
+ * LibreSSL: not supported. 3.5.0+ has a stub function that does nothing.
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+ !defined(LIBRESSL_VERSION_NUMBER)) || \
+ defined(OPENSSL_IS_BORINGSSL)
+#define HAVE_KEYLOG_CALLBACK
+#endif
+
+struct ssl_peer;
+
+/* Struct to hold a curl OpenSSL instance */
struct ossl_ctx {
/* these ones requires specific SSL-types */
SSL_CTX* ssl_ctx;
@@ -53,6 +68,8 @@ struct ossl_ctx { BIT(reused_session); /* session-ID was reused for this */
};
+size_t Curl_ossl_version(char *buffer, size_t size);
+
typedef CURLcode Curl_ossl_ctx_setup_cb(struct Curl_cfilter *cf,
struct Curl_easy *data,
void *user_data);
@@ -63,7 +80,6 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
- int transport, /* TCP or QUIC */
const unsigned char *alpn, size_t alpn_len,
Curl_ossl_ctx_setup_cb *cb_setup,
void *cb_user_data,
@@ -94,8 +110,10 @@ CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf, */
CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
- const struct ssl_peer *peer,
- SSL_SESSION *ssl_sessionid);
+ const char *ssl_peer_key,
+ SSL_SESSION *ssl_sessionid,
+ int ietf_tls_id,
+ const char *alpn);
/*
* Get the server cert, verify it and show it, etc., only call failf() if
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c index b10328d4aa..ca987d7eed 100644 --- a/libs/libcurl/src/vtls/rustls.c +++ b/libs/libcurl/src/vtls/rustls.c @@ -1076,27 +1076,24 @@ const struct Curl_ssl Curl_ssl_rustls = { SSLSUPP_TLS13_CIPHERSUITES,
sizeof(struct rustls_ssl_backend_data),
- Curl_none_init, /* init */
- Curl_none_cleanup, /* cleanup */
+ NULL, /* init */
+ NULL, /* cleanup */
cr_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
cr_shutdown, /* shutdown */
cr_data_pending, /* data_pending */
cr_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
cr_connect_blocking, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
NULL, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
cr_recv, /* recv decrypted data */
cr_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index 1c9ecc673a..e0a978f1db 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -41,6 +41,7 @@ #include "schannel_int.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "strcase.h"
#include "sendf.h"
#include "connect.h" /* for the connect timeout */
@@ -76,7 +77,7 @@ https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)
-# define HAS_ALPN 1
+# define HAS_ALPN_SCHANNEL
#endif
#ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
@@ -148,7 +149,7 @@ */
#ifndef CALG_SHA_256
-# define CALG_SHA_256 0x0000800c
+#define CALG_SHA_256 0x0000800c
#endif
#ifndef PKCS12_NO_PERSIST_KEY
@@ -887,7 +888,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) SecBufferDesc outbuf_desc;
SecBuffer inbuf;
SecBufferDesc inbuf_desc;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
unsigned char alpn_buffer[128];
#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
@@ -907,7 +908,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) "connect to some servers due to lack of SNI, algorithms, etc.");
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it does not seem to be supported for WINE, see curl bug #983. */
backend->use_alpn = connssl->alpn &&
@@ -954,9 +955,9 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* check for an existing reusable credential handle */
if(ssl_config->primary.cache_session) {
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- (void **)&old_cred, NULL, NULL)) {
+ Curl_ssl_scache_lock(data);
+ if(Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key,
+ (void **)&old_cred)) {
backend->cred = old_cred;
DEBUGF(infof(data, "schannel: reusing existing credential handle"));
@@ -966,7 +967,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) "schannel: incremented credential handle refcount = %d",
backend->cred->refcount));
}
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_unlock(data);
}
if(!backend->cred) {
@@ -990,7 +991,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) infof(data, "schannel: using IP address, SNI is not supported by OS.");
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
if(backend->use_alpn) {
int cur = 0;
int list_start_index = 0;
@@ -1038,7 +1039,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
-#else /* HAS_ALPN */
+#else /* HAS_ALPN_SCHANNEL */
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
#endif
@@ -1501,12 +1502,11 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, bool reverse_order, return args->result == CURLE_OK;
}
-static void schannel_session_free(void *sessionid, size_t idsize)
+static void schannel_session_free(void *sessionid)
{
/* this is expected to be called under sessionid lock */
struct Curl_schannel_cred *cred = sessionid;
- (void)idsize;
if(cred) {
cred->refcount--;
if(cred->refcount == 0) {
@@ -1533,7 +1533,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) CURLcode result = CURLE_OK;
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
SecPkgContext_ApplicationProtocol alpn_result;
#endif
@@ -1562,7 +1562,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
if(backend->use_alpn) {
sspi_status =
Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle,
@@ -1599,14 +1599,12 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) /* save the current session data for possible reuse */
if(ssl_config->primary.cache_session) {
- Curl_ssl_sessionid_lock(data);
+ Curl_ssl_scache_lock(data);
/* Up ref count since call takes ownership */
backend->cred->refcount++;
- result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
- backend->cred,
- sizeof(struct Curl_schannel_cred),
- schannel_session_free);
- Curl_ssl_sessionid_unlock(data);
+ result = Curl_ssl_scache_add_obj(cf, data, connssl->peer.scache_key,
+ backend->cred, schannel_session_free);
+ Curl_ssl_scache_unlock(data);
if(result)
return result;
}
@@ -2275,11 +2273,11 @@ static bool schannel_data_pending(struct Curl_cfilter *cf, DEBUGASSERT(backend);
if(backend->ctxt) /* SSL/TLS is in use */
- return (backend->decdata_offset > 0 ||
- (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) ||
- backend->recv_connection_closed ||
- backend->recv_sspi_close_notify ||
- backend->recv_unrecoverable_err);
+ return backend->decdata_offset > 0 ||
+ (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) ||
+ backend->recv_connection_closed ||
+ backend->recv_sspi_close_notify ||
+ backend->recv_unrecoverable_err;
else
return FALSE;
}
@@ -2369,7 +2367,6 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf, Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if(!result) {
if(written < (ssize_t)outbuf.cbBuffer) {
- /* TODO: handle partial sends */
failf(data, "schannel: failed to send close msg: %s"
" (bytes written: %zd)", curl_easy_strerror(result), written);
result = CURLE_SEND_ERROR;
@@ -2445,9 +2442,9 @@ static void schannel_close(struct Curl_cfilter *cf, struct Curl_easy *data) /* free SSPI Schannel API credential handle */
if(backend->cred) {
- Curl_ssl_sessionid_lock(data);
- schannel_session_free(backend->cred, 0);
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_lock(data);
+ schannel_session_free(backend->cred);
+ Curl_ssl_scache_unlock(data);
backend->cred = NULL;
}
@@ -2469,7 +2466,7 @@ static void schannel_close(struct Curl_cfilter *cf, struct Curl_easy *data) static int schannel_init(void)
{
- return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
+ return Curl_sspi_global_init() == CURLE_OK ? 1 : 0;
}
static void schannel_cleanup(void)
@@ -2798,24 +2795,21 @@ const struct Curl_ssl Curl_ssl_schannel = { schannel_init, /* init */
schannel_cleanup, /* cleanup */
schannel_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
schannel_shutdown, /* shutdown */
schannel_data_pending, /* data_pending */
schannel_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
schannel_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
schannel_recv, /* recv decrypted data */
schannel_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h index 438012d434..e901eacfbd 100644 --- a/libs/libcurl/src/vtls/schannel.h +++ b/libs/libcurl/src/vtls/schannel.h @@ -30,7 +30,7 @@ #ifdef _MSC_VER
#pragma warning(push)
-#pragma warning(disable: 4201)
+#pragma warning(disable:4201)
#endif
#include <subauth.h>
#ifdef _MSC_VER
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 765ce36d92..10dfe1e92e 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -38,6 +38,7 @@ #include "multiif.h"
#include "strcase.h"
#include "x509asn1.h"
+#include "vtls_scache.h"
#include "strerror.h"
#include "cipher_suite.h"
@@ -51,6 +52,11 @@ #pragma GCC diagnostic ignored "-Waddress"
#endif
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
#include <limits.h>
#include <Security/Security.h>
@@ -1015,7 +1021,7 @@ failed: return ret;
}
-static void sectransp_session_free(void *sessionid, size_t idsize)
+static void sectransp_session_free(void *sessionid)
{
/* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
cached session ID inside the Security framework. There is a private
@@ -1023,7 +1029,6 @@ static void sectransp_session_free(void *sessionid, size_t idsize) got your application rejected from the App Store due to the use of a
private API, so the best we can do is free up our own char array that we
created way back in sectransp_connect_step1... */
- (void)idsize;
Curl_safefree(sessionid);
}
@@ -1332,19 +1337,19 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, char *ssl_sessionid;
size_t ssl_sessionid_len;
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- (void **)&ssl_sessionid, &ssl_sessionid_len,
- NULL)) {
+ Curl_ssl_scache_lock(data);
+ if(Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key,
+ (void **)&ssl_sessionid)) {
/* we got a session id, use it! */
- err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- Curl_ssl_sessionid_unlock(data);
+ err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid,
+ strlen(ssl_sessionid));
+ Curl_ssl_scache_unlock(data);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
- /* Informational message */
- infof(data, "SSL reusing session ID");
+ else
+ infof(data, "SSL reusing session ID");
}
/* If there is not one, then let's make one up! This has to be done prior
to starting the handshake. */
@@ -1358,15 +1363,17 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_unlock(data);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
- ssl_sessionid, ssl_sessionid_len,
+ /* This is all a bit weird, as we have not handshaked yet.
+ * I hope this backend will go away soon. */
+ result = Curl_ssl_scache_add_obj(cf, data, connssl->peer.scache_key,
+ (void *)ssl_sessionid,
sectransp_session_free);
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_unlock(data);
if(result)
return result;
}
@@ -1504,9 +1511,11 @@ static CURLcode append_cert_to_array(struct Curl_easy *data, case CURLE_OK:
break;
case CURLE_PEER_FAILED_VERIFICATION:
+ CFRelease(cacert);
return CURLE_SSL_CACERT_BADFILE;
case CURLE_OUT_OF_MEMORY:
default:
+ CFRelease(cacert);
return result;
}
free(certp);
@@ -2424,7 +2433,7 @@ static CURLcode sectransp_shutdown(struct Curl_cfilter *cf, struct st_ssl_backend_data *backend =
(struct st_ssl_backend_data *)connssl->backend;
CURLcode result = CURLE_OK;
- ssize_t nread;
+ ssize_t nread = 0;
char buf[1024];
size_t i;
@@ -2742,32 +2751,33 @@ const struct Curl_ssl Curl_ssl_sectransp = { sizeof(struct st_ssl_backend_data),
- Curl_none_init, /* init */
- Curl_none_cleanup, /* cleanup */
+ NULL, /* init */
+ NULL, /* cleanup */
sectransp_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
sectransp_shutdown, /* shutdown */
sectransp_data_pending, /* data_pending */
sectransp_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
sectransp_false_start, /* false_start */
sectransp_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
sectransp_recv, /* recv decrypted data */
sectransp_send, /* send data to encrypt */
NULL, /* get_channel_binding */
};
+#if defined(__GNUC__) && defined(__APPLE__)
+#pragma GCC diagnostic pop
+#endif
+
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index 0a90bf46fd..182744bb6e 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -55,6 +55,7 @@ #include "vtls.h" /* generic SSL protos etc */
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
@@ -74,6 +75,7 @@ #include "multiif.h"
#include "timeval.h"
#include "curl_md5.h"
+#include "curl_sha256.h"
#include "warnless.h"
#include "curl_base64.h"
#include "curl_printf.h"
@@ -88,11 +90,6 @@ #include "memdebug.h"
-/* convenience macro to check if this handle is using a shared SSL session */
-#define SSLSESSION_SHARED(data) (data->share && \
- (data->share->specifier & \
- (1<<CURL_LOCK_DATA_SSL_SESSION)))
-
#define CLONE_STRING(var) \
do { \
if(source->var) { \
@@ -426,7 +423,9 @@ int Curl_ssl_init(void) return 1;
init_ssl = TRUE; /* never again */
- return Curl_ssl->init();
+ if(Curl_ssl->init)
+ return Curl_ssl->init();
+ return 1;
}
static bool ssl_prefs_check(struct Curl_easy *data)
@@ -463,9 +462,10 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data, if(!ctx)
return NULL;
+ ctx->ssl_impl = Curl_ssl;
ctx->alpn = alpn;
Curl_bufq_init2(&ctx->earlydata, CURL_SSL_EARLY_MAX, 1, BUFQ_OPT_NO_SPARES);
- ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data);
+ ctx->backend = calloc(1, ctx->ssl_impl->sizeof_ssl_backend_data);
if(!ctx->backend) {
free(ctx);
return NULL;
@@ -476,7 +476,7 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data, static void cf_ctx_free(struct ssl_connect_data *ctx)
{
if(ctx) {
- Curl_safefree(ctx->alpn_negotiated);
+ Curl_safefree(ctx->negotiated.alpn);
Curl_bufq_free(&ctx->earlydata);
free(ctx->backend);
free(ctx);
@@ -494,7 +494,7 @@ static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data) /* mark this is being ssl-enabled from here on. */
connssl->state = ssl_connection_negotiating;
- result = Curl_ssl->connect_blocking(cf, data);
+ result = connssl->ssl_impl->connect_blocking(cf, data);
if(!result) {
DEBUGASSERT(connssl->state == ssl_connection_complete);
@@ -507,275 +507,13 @@ static CURLcode ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
bool *done)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
- return Curl_ssl->connect_nonblocking(cf, data, done);
-}
-
-/*
- * Lock shared SSL session data
- */
-void Curl_ssl_sessionid_lock(struct Curl_easy *data)
-{
- if(SSLSESSION_SHARED(data))
- Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
-}
-
-/*
- * Unlock shared SSL session data
- */
-void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
-{
- if(SSLSESSION_SHARED(data))
- Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
-}
-
-/*
- * Check if there is a session ID for the given connection in the cache, and if
- * there is one suitable, it is provided. Returns TRUE when no entry matched.
- */
-bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- void **ssl_sessionid,
- size_t *idsize, /* set 0 if unknown */
- char **palpn)
-{
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct Curl_ssl_session *check;
- size_t i;
- long *general_age;
- bool no_match = TRUE;
-
- *ssl_sessionid = NULL;
- if(palpn)
- *palpn = NULL;
- if(!ssl_config)
- return TRUE;
-
- DEBUGASSERT(ssl_config->primary.cache_session);
-
- if(!ssl_config->primary.cache_session || !data->state.session)
- /* session ID reuse is disabled or the session cache has not been
- setup */
- return TRUE;
-
- /* Lock if shared */
- if(SSLSESSION_SHARED(data))
- general_age = &data->share->sessionage;
- else
- general_age = &data->state.sessionage;
-
- for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
- check = &data->state.session[i];
- if(!check->sessionid)
- /* not session ID means blank entry */
- continue;
- if(strcasecompare(peer->hostname, check->name) &&
- ((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
- (cf->conn->bits.conn_to_host && check->conn_to_host &&
- strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
- ((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
- (cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
- cf->conn->conn_to_port == check->conn_to_port)) &&
- (peer->port == check->remote_port) &&
- (peer->transport == check->transport) &&
- strcasecompare(cf->conn->handler->scheme, check->scheme) &&
- match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
- /* yes, we have a session ID! */
- (*general_age)++; /* increase general age */
- check->age = *general_age; /* set this as used in this age */
- *ssl_sessionid = check->sessionid;
- if(idsize)
- *idsize = check->idsize;
- if(palpn)
- *palpn = check->alpn;
- no_match = FALSE;
- break;
- }
- }
-
- CURL_TRC_CF(data, cf, "%s cached session ID for %s://%s:%d",
- no_match ? "No" : "Found",
- cf->conn->handler->scheme, peer->hostname, peer->port);
- return no_match;
-}
-
-/*
- * Kill a single session ID entry in the cache.
- */
-void Curl_ssl_kill_session(struct Curl_ssl_session *session)
-{
- if(session->sessionid) {
- /* defensive check */
-
- /* free the ID the SSL-layer specific way */
- session->sessionid_free(session->sessionid, session->idsize);
-
- session->sessionid = NULL;
- session->sessionid_free = NULL;
- session->age = 0; /* fresh */
-
- free_primary_ssl_config(&session->ssl_config);
-
- Curl_safefree(session->name);
- Curl_safefree(session->conn_to_host);
- Curl_safefree(session->alpn);
- }
-}
-
-/*
- * Delete the given session ID from the cache.
- */
-void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
-{
- size_t i;
-
- for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
- struct Curl_ssl_session *check = &data->state.session[i];
-
- if(check->sessionid == ssl_sessionid) {
- Curl_ssl_kill_session(check);
- break;
- }
- }
-}
-
-CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- const char *alpn,
- void *ssl_sessionid,
- size_t idsize,
- Curl_ssl_sessionid_dtor *sessionid_free_cb)
-{
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- size_t i;
- struct Curl_ssl_session *store;
- long oldest_age;
- char *clone_host = NULL;
- char *clone_conn_to_host = NULL;
- char *clone_alpn = NULL;
- int conn_to_port;
- long *general_age;
- void *old_sessionid;
- size_t old_size;
- CURLcode result = CURLE_OUT_OF_MEMORY;
-
- DEBUGASSERT(ssl_sessionid);
- DEBUGASSERT(sessionid_free_cb);
-
- if(!data->state.session) {
- sessionid_free_cb(ssl_sessionid, idsize);
- return CURLE_OK;
- }
-
- if(!Curl_ssl_getsessionid(cf, data, peer, &old_sessionid, &old_size, NULL)) {
- if((old_size == idsize) &&
- ((old_sessionid == ssl_sessionid) ||
- (idsize && !memcmp(old_sessionid, ssl_sessionid, idsize)))) {
- /* the very same */
- sessionid_free_cb(ssl_sessionid, idsize);
- return CURLE_OK;
- }
- Curl_ssl_delsessionid(data, old_sessionid);
- }
-
- store = &data->state.session[0];
- oldest_age = data->state.session[0].age; /* zero if unused */
- DEBUGASSERT(ssl_config->primary.cache_session);
- (void)ssl_config;
-
- clone_host = strdup(peer->hostname);
- if(!clone_host)
- goto out;
-
- if(cf->conn->bits.conn_to_host) {
- clone_conn_to_host = strdup(cf->conn->conn_to_host.name);
- if(!clone_conn_to_host)
- goto out;
- }
-
- clone_alpn = alpn ? strdup(alpn) : NULL;
- if(alpn && !clone_alpn)
- goto out;
-
- if(cf->conn->bits.conn_to_port)
- conn_to_port = cf->conn->conn_to_port;
- else
- conn_to_port = -1;
-
- /* Now we should add the session ID and the hostname to the cache, (remove
- the oldest if necessary) */
-
- /* If using shared SSL session, lock! */
- if(SSLSESSION_SHARED(data)) {
- general_age = &data->share->sessionage;
- }
- else {
- general_age = &data->state.sessionage;
- }
-
- /* find an empty slot for us, or find the oldest */
- for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
- data->state.session[i].sessionid; i++) {
- if(data->state.session[i].age < oldest_age) {
- oldest_age = data->state.session[i].age;
- store = &data->state.session[i];
- }
- }
- if(i == data->set.general_ssl.max_ssl_sessions)
- /* cache is full, we must "kill" the oldest entry! */
- Curl_ssl_kill_session(store);
- else
- store = &data->state.session[i]; /* use this slot */
-
- /* now init the session struct wisely */
- if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
- free_primary_ssl_config(&store->ssl_config);
- store->sessionid = NULL; /* let caller free sessionid */
- goto out;
- }
- store->sessionid = ssl_sessionid;
- store->idsize = idsize;
- store->sessionid_free = sessionid_free_cb;
- store->age = *general_age; /* set current age */
- /* free it if there is one already present */
- free(store->name);
- free(store->conn_to_host);
- store->name = clone_host; /* clone hostname */
- clone_host = NULL;
- store->conn_to_host = clone_conn_to_host; /* clone connect to hostname */
- clone_conn_to_host = NULL;
- store->conn_to_port = conn_to_port; /* connect to port number */
- store->alpn = clone_alpn;
- clone_alpn = NULL;
- /* port number */
- store->remote_port = peer->port;
- store->scheme = cf->conn->handler->scheme;
- store->transport = peer->transport;
-
- result = CURLE_OK;
-
-out:
- free(clone_host);
- free(clone_conn_to_host);
- free(clone_alpn);
- if(result) {
- failf(data, "Failed to add Session ID to cache for %s://%s:%d [%s]",
- store->scheme, store->name, store->remote_port,
- Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
- sessionid_free_cb(ssl_sessionid, idsize);
- return result;
- }
- CURL_TRC_CF(data, cf, "Added Session ID to cache for %s://%s:%d [%s]",
- store->scheme, store->name, store->remote_port,
- Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
- return CURLE_OK;
+ return connssl->ssl_impl->connect_nonblocking(cf, data, done);
}
CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex,
@@ -788,18 +526,8 @@ CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex, void Curl_ssl_close_all(struct Curl_easy *data)
{
- /* kill the session ID cache if not shared */
- if(data->state.session && !SSLSESSION_SHARED(data)) {
- size_t i;
- for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
- /* the single-killer function handles empty table slots */
- Curl_ssl_kill_session(&data->state.session[i]);
-
- /* free the cache data */
- Curl_safefree(data->state.session);
- }
-
- Curl_ssl->close_all(data);
+ if(Curl_ssl->close_all)
+ Curl_ssl->close_all(data);
}
void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -828,43 +556,26 @@ void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, */
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
{
- return Curl_ssl->set_engine(data, engine);
+ if(Curl_ssl->set_engine)
+ return Curl_ssl->set_engine(data, engine);
+ return CURLE_NOT_BUILT_IN;
}
/* Selects the default SSL crypto engine
*/
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
{
- return Curl_ssl->set_engine_default(data);
+ if(Curl_ssl->set_engine_default)
+ return Curl_ssl->set_engine_default(data);
+ return CURLE_NOT_BUILT_IN;
}
/* Return list of OpenSSL crypto engine names. */
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
{
- return Curl_ssl->engines_list(data);
-}
-
-/*
- * This sets up a session ID cache to the specified size. Make sure this code
- * is agnostic to what underlying SSL technology we use.
- */
-CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
-{
- struct Curl_ssl_session *session;
-
- if(data->state.session)
- /* this is just a precaution to prevent multiple inits */
- return CURLE_OK;
-
- session = calloc(amount, sizeof(struct Curl_ssl_session));
- if(!session)
- return CURLE_OUT_OF_MEMORY;
-
- /* store the info in the SSL section */
- data->set.general_ssl.max_ssl_sessions = amount;
- data->state.session = session;
- data->state.sessionage = 1; /* this is brand new */
- return CURLE_OK;
+ if(Curl_ssl->engines_list)
+ return Curl_ssl->engines_list(data);
+ return NULL;
}
static size_t multissl_version(char *buffer, size_t size);
@@ -950,7 +661,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, return result;
}
-/* get 32 bits of random */
+/* get length bytes of randomness */
CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
@@ -1185,96 +896,18 @@ end: */
bool Curl_ssl_cert_status_request(void)
{
- return Curl_ssl->cert_status_request();
+ if(Curl_ssl->cert_status_request)
+ return Curl_ssl->cert_status_request();
+ return FALSE;
}
/*
* Check whether the SSL backend supports false start.
*/
-bool Curl_ssl_false_start(struct Curl_easy *data)
-{
- (void)data;
- return Curl_ssl->false_start();
-}
-
-/*
- * Default implementations for unsupported functions.
- */
-
-int Curl_none_init(void)
-{
- return 1;
-}
-
-void Curl_none_cleanup(void)
-{ }
-
-CURLcode Curl_none_shutdown(struct Curl_cfilter *cf UNUSED_PARAM,
- struct Curl_easy *data UNUSED_PARAM,
- bool send_shutdown UNUSED_PARAM,
- bool *done)
-{
- (void)data;
- (void)cf;
- (void)send_shutdown;
- /* Every SSL backend should have a shutdown implementation. Until we
- * have implemented that, we put this fake in place. */
- *done = TRUE;
- return CURLE_OK;
-}
-
-int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- (void)cf;
- (void)data;
- return -1;
-}
-
-void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
-{
- (void)data;
-}
-
-void Curl_none_session_free(void *ptr UNUSED_PARAM)
-{
- (void)ptr;
-}
-
-bool Curl_none_data_pending(struct Curl_cfilter *cf UNUSED_PARAM,
- const struct Curl_easy *data UNUSED_PARAM)
-{
- (void)cf;
- (void)data;
- return 0;
-}
-
-bool Curl_none_cert_status_request(void)
-{
- return FALSE;
-}
-
-CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
- const char *engine UNUSED_PARAM)
-{
- (void)data;
- (void)engine;
- return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
-{
- (void)data;
- return CURLE_NOT_BUILT_IN;
-}
-
-struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
-{
- (void)data;
- return (struct curl_slist *)NULL;
-}
-
-bool Curl_none_false_start(void)
+bool Curl_ssl_false_start(void)
{
+ if(Curl_ssl->false_start)
+ return Curl_ssl->false_start();
return FALSE;
}
@@ -1282,7 +915,9 @@ static int multissl_init(void) {
if(multissl_setup(NULL))
return 1;
- return Curl_ssl->init();
+ if(Curl_ssl->init)
+ return Curl_ssl->init();
+ return 1;
}
static CURLcode multissl_connect(struct Curl_cfilter *cf,
@@ -1351,26 +986,23 @@ static const struct Curl_ssl Curl_ssl_multi = { (size_t)-1, /* something insanely large to be on the safe side */
multissl_init, /* init */
- Curl_none_cleanup, /* cleanup */
+ NULL, /* cleanup */
multissl_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
- Curl_none_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
+ NULL, /* shutdown */
+ NULL, /* data_pending */
NULL, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_adjust_pollset, /* adjust_pollset */
+ multissl_adjust_pollset, /* adjust_pollset */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
NULL, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
multissl_recv_plain, /* recv decrypted data */
multissl_send_plain, /* send data to encrypt */
NULL, /* get_channel_binding */
@@ -1432,7 +1064,8 @@ void Curl_ssl_cleanup(void) {
if(init_ssl) {
/* only cleanup if we did a previous init */
- Curl_ssl->cleanup();
+ if(Curl_ssl->cleanup)
+ Curl_ssl->cleanup();
#if defined(CURL_WITH_MULTI_SSL)
Curl_ssl = &Curl_ssl_multi;
#endif
@@ -1482,8 +1115,8 @@ static size_t multissl_version(char *buffer, size_t size) static int multissl_setup(const struct Curl_ssl *backend)
{
- const char *env;
- char *env_tmp;
+ int i;
+ char *env;
if(Curl_ssl != &Curl_ssl_multi)
return 1;
@@ -1496,25 +1129,31 @@ static int multissl_setup(const struct Curl_ssl *backend) if(!available_backends[0])
return 1;
- env = env_tmp = curl_getenv("CURL_SSL_BACKEND");
-#ifdef CURL_DEFAULT_SSL_BACKEND
- if(!env)
- env = CURL_DEFAULT_SSL_BACKEND;
-#endif
+ env = curl_getenv("CURL_SSL_BACKEND");
if(env) {
- int i;
for(i = 0; available_backends[i]; i++) {
if(strcasecompare(env, available_backends[i]->info.name)) {
Curl_ssl = available_backends[i];
- free(env_tmp);
+ free(env);
return 0;
}
}
}
+#ifdef CURL_DEFAULT_SSL_BACKEND
+ for(i = 0; available_backends[i]; i++) {
+ if(strcasecompare(CURL_DEFAULT_SSL_BACKEND,
+ available_backends[i]->info.name)) {
+ Curl_ssl = available_backends[i];
+ free(env);
+ return 0;
+ }
+ }
+#endif
+
/* Fall back to first available backend */
Curl_ssl = available_backends[0];
- free(env_tmp);
+ free(env);
return 0;
}
@@ -1565,11 +1204,12 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
{
+ Curl_safefree(peer->sni);
if(peer->dispname != peer->hostname)
free(peer->dispname);
- free(peer->sni);
- free(peer->hostname);
- peer->hostname = peer->sni = peer->dispname = NULL;
+ peer->dispname = NULL;
+ Curl_safefree(peer->hostname);
+ Curl_safefree(peer->scache_key);
peer->type = CURL_SSL_PEER_DNS;
}
@@ -1577,7 +1217,7 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) {
struct ssl_connect_data *connssl = cf->ctx;
if(connssl) {
- Curl_ssl->close(cf, data);
+ connssl->ssl_impl->close(cf, data);
connssl->state = ssl_connection_none;
Curl_ssl_peer_cleanup(&connssl->peer);
}
@@ -1603,7 +1243,9 @@ static ssl_peer_type get_peer_type(const char *hostname) return CURL_SSL_PEER_DNS;
}
-CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf,
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer,
+ struct Curl_cfilter *cf,
+ const char *tls_id,
int transport)
{
const char *ehostname, *edispname;
@@ -1665,7 +1307,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf, peer->sni[len] = 0;
}
}
- result = CURLE_OK;
+
+ result = Curl_ssl_peer_key_make(cf, peer, tls_id, &peer->scache_key);
out:
if(result)
@@ -1728,7 +1371,9 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, *done = FALSE;
if(!connssl->peer.hostname) {
- result = Curl_ssl_peer_init(&connssl->peer, cf, TRNSPRT_TCP);
+ char tls_id[80];
+ connssl->ssl_impl->version(tls_id, sizeof(tls_id) - 1);
+ result = Curl_ssl_peer_init(&connssl->peer, cf, tls_id, TRNSPRT_TCP);
if(result)
goto out;
}
@@ -1743,7 +1388,8 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, if(!result && *done) {
cf->connected = TRUE;
- connssl->handshake_done = Curl_now();
+ if(connssl->state == ssl_connection_complete)
+ connssl->handshake_done = Curl_now();
/* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete ||
connssl->state == ssl_connection_deferred);
@@ -1757,11 +1403,13 @@ out: static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
+ struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
bool result;
CF_DATA_SAVE(save, cf, data);
- if(Curl_ssl->data_pending(cf, data))
+ if(connssl->ssl_impl->data_pending &&
+ connssl->ssl_impl->data_pending(cf, data))
result = TRUE;
else
result = cf->next->cft->has_data_pending(cf->next, data);
@@ -1773,6 +1421,7 @@ static ssize_t ssl_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len,
bool eos, CURLcode *err)
{
+ struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
ssize_t nwritten = 0;
@@ -1781,7 +1430,7 @@ static ssize_t ssl_cf_send(struct Curl_cfilter *cf, *err = CURLE_OK;
if(len > 0) {
CF_DATA_SAVE(save, cf, data);
- nwritten = Curl_ssl->send_plain(cf, data, buf, len, err);
+ nwritten = connssl->ssl_impl->send_plain(cf, data, buf, len, err);
CF_DATA_RESTORE(cf, save);
}
return nwritten;
@@ -1791,12 +1440,13 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len,
CURLcode *err)
{
+ struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
ssize_t nread;
CF_DATA_SAVE(save, cf, data);
*err = CURLE_OK;
- nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
+ nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err);
if(nread > 0) {
DEBUGASSERT((size_t)nread <= len);
}
@@ -1814,14 +1464,15 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data,
bool *done)
{
+ struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
*done = TRUE;
- if(!cf->shutdown) {
+ if(!cf->shutdown && Curl_ssl->shut_down) {
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
- result = Curl_ssl->shut_down(cf, data, TRUE, done);
+ result = connssl->ssl_impl->shut_down(cf, data, TRUE, done);
CURL_TRC_CF(data, cf, "cf_shutdown -> %d, done=%d", result, *done);
CF_DATA_RESTORE(cf, save);
cf->shutdown = (result || *done);
@@ -1833,42 +1484,14 @@ static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
struct easy_pollset *ps)
{
+ struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
- Curl_ssl->adjust_pollset(cf, data, ps);
+ connssl->ssl_impl->adjust_pollset(cf, data, ps);
CF_DATA_RESTORE(cf, save);
}
-static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- int event, int arg1, void *arg2)
-{
- struct cf_call_data save;
-
- (void)arg1;
- (void)arg2;
- switch(event) {
- case CF_CTRL_DATA_ATTACH:
- if(Curl_ssl->attach_data) {
- CF_DATA_SAVE(save, cf, data);
- Curl_ssl->attach_data(cf, data);
- CF_DATA_RESTORE(cf, save);
- }
- break;
- case CF_CTRL_DATA_DETACH:
- if(Curl_ssl->detach_data) {
- CF_DATA_SAVE(save, cf, data);
- Curl_ssl->detach_data(cf, data);
- CF_DATA_RESTORE(cf, save);
- }
- break;
- default:
- break;
- }
- return CURLE_OK;
-}
-
static CURLcode ssl_cf_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2)
@@ -1893,28 +1516,9 @@ static CURLcode ssl_cf_query(struct Curl_cfilter *cf, static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data,
bool *input_pending)
{
- struct cf_call_data save;
- int result;
/*
* This function tries to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
*/
- CF_DATA_SAVE(save, cf, data);
- result = Curl_ssl->check_cxn(cf, data);
- CF_DATA_RESTORE(cf, save);
- if(result > 0) {
- *input_pending = TRUE;
- return TRUE;
- }
- if(result == 0) {
- *input_pending = FALSE;
- return FALSE;
- }
- /* ssl backend does not know */
return cf->next ?
cf->next->cft->is_alive(cf->next, data, input_pending) :
FALSE; /* pessimistic in absence of data */
@@ -1933,7 +1537,7 @@ struct Curl_cftype Curl_cft_ssl = { ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
- ssl_cf_cntrl,
+ Curl_cf_def_cntrl,
cf_ssl_is_alive,
Curl_cf_def_conn_keep_alive,
ssl_cf_query,
@@ -1954,7 +1558,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = { ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
- ssl_cf_cntrl,
+ Curl_cf_def_cntrl,
cf_ssl_is_alive,
Curl_cf_def_conn_keep_alive,
Curl_cf_def_query,
@@ -2090,9 +1694,10 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, /* get first SSL filter in chain, if any is present */
cf = get_ssl_filter(data->conn->cfilter[sockindex]);
if(cf) {
+ struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
- result = Curl_ssl->get_internals(cf->ctx, info);
+ result = connssl->ssl_impl->get_internals(cf->ctx, info);
CF_DATA_RESTORE(cf, save);
}
}
@@ -2125,7 +1730,7 @@ static CURLcode vtls_shutdown_blocking(struct Curl_cfilter *cf, return CURLE_OPERATION_TIMEDOUT;
}
- result = Curl_ssl->shut_down(cf, data, send_shutdown, done);
+ result = connssl->ssl_impl->shut_down(cf, data, send_shutdown, done);
if(result ||*done)
goto out;
@@ -2277,28 +1882,28 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, #endif
;
- if(connssl->alpn_negotiated) {
+ if(connssl->negotiated.alpn) {
/* When we ask for a specific ALPN protocol, we need the confirmation
* of it by the server, as we have installed protocol handler and
* connection filter chain for exactly this protocol. */
if(!proto_len) {
failf(data, "ALPN: asked for '%s' from previous session, "
"but server did not confirm it. Refusing to continue.",
- connssl->alpn_negotiated);
+ connssl->negotiated.alpn);
result = CURLE_SSL_CONNECT_ERROR;
goto out;
}
- else if((strlen(connssl->alpn_negotiated) != proto_len) ||
- memcmp(connssl->alpn_negotiated, proto, proto_len)) {
+ else if((strlen(connssl->negotiated.alpn) != proto_len) ||
+ memcmp(connssl->negotiated.alpn, proto, proto_len)) {
failf(data, "ALPN: asked for '%s' from previous session, but server "
"selected '%.*s'. Refusing to continue.",
- connssl->alpn_negotiated, (int)proto_len, proto);
+ connssl->negotiated.alpn, (int)proto_len, proto);
result = CURLE_SSL_CONNECT_ERROR;
goto out;
}
/* ALPN is exactly what we asked for, done. */
infof(data, "ALPN: server confirmed to use '%s'",
- connssl->alpn_negotiated);
+ connssl->negotiated.alpn);
goto out;
}
@@ -2309,11 +1914,11 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, result = CURLE_SSL_CONNECT_ERROR;
goto out;
}
- connssl->alpn_negotiated = malloc(proto_len + 1);
- if(!connssl->alpn_negotiated)
+ connssl->negotiated.alpn = malloc(proto_len + 1);
+ if(!connssl->negotiated.alpn)
return CURLE_OUT_OF_MEMORY;
- memcpy(connssl->alpn_negotiated, proto, proto_len);
- connssl->alpn_negotiated[proto_len] = 0;
+ memcpy(connssl->negotiated.alpn, proto, proto_len);
+ connssl->negotiated.alpn[proto_len] = 0;
}
if(proto && proto_len) {
@@ -2336,8 +1941,8 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, else {
*palpn = CURL_HTTP_VERSION_NONE;
failf(data, "unsupported ALPN protocol: '%.*s'", (int)proto_len, proto);
- /* TODO: do we want to fail this? Previous code just ignored it and
- * some vtls backends even ignore the return code of this function. */
+ /* Previous code just ignored it and some vtls backends even ignore the
+ * return code of this function. */
/* return CURLE_NOT_BUILT_IN; */
goto out;
}
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index 171a5d8e55..3c438a2dba 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -28,7 +28,9 @@ struct connectdata;
struct ssl_config_data;
struct ssl_primary_config;
-struct Curl_ssl_session;
+struct Curl_cfilter;
+struct Curl_easy;
+struct dynbuf;
#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
@@ -41,6 +43,14 @@ struct Curl_ssl_session; #define SSLSUPP_CA_CACHE (1<<8)
#define SSLSUPP_CIPHER_LIST (1<<9) /* supports TLS 1.0-1.2 ciphersuites */
+#ifdef USE_ECH
+# include "curl_base64.h"
+# define ECH_ENABLED(__data__) \
+ (__data__->set.tls_ech && \
+ !(__data__->set.tls_ech & CURLECH_DISABLE)\
+ )
+#endif /* USE_ECH */
+
#define ALPN_ACCEPTED "ALPN: server accepted "
#define VTLS_INFOF_NO_ALPN \
@@ -55,9 +65,31 @@ struct Curl_ssl_session; #define VTLS_INFOF_ALPN_DEFERRED \
"ALPN: deferred handshake for early data using '%.*s'."
-/* Curl_multi SSL backend-specific data; declared differently by each SSL
- backend */
-struct Curl_cfilter;
+/* IETF defined version numbers used in TLS protocol negotiation */
+#define CURL_IETF_PROTO_UNKNOWN 0x0
+#define CURL_IETF_PROTO_SSL3 0x0300
+#define CURL_IETF_PROTO_TLS1 0x0301
+#define CURL_IETF_PROTO_TLS1_1 0x0302
+#define CURL_IETF_PROTO_TLS1_2 0x0303
+#define CURL_IETF_PROTO_TLS1_3 0x0304
+#define CURL_IETF_PROTO_DTLS1 0xFEFF
+#define CURL_IETF_PROTO_DTLS1_2 0xFEFD
+
+typedef enum {
+ CURL_SSL_PEER_DNS,
+ CURL_SSL_PEER_IPV4,
+ CURL_SSL_PEER_IPV6
+} ssl_peer_type;
+
+struct ssl_peer {
+ char *hostname; /* hostname for verification */
+ char *dispname; /* display version of hostname */
+ char *sni; /* SNI version of hostname or NULL if not usable */
+ char *scache_key; /* for lookups in session cache */
+ ssl_peer_type type; /* type of the peer information */
+ int port; /* port we are talking to */
+ int transport; /* one of TRNSPRT_* defines */
+};
CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
const curl_ssl_backend ***avail);
@@ -113,7 +145,9 @@ void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy); * Init SSL peer information for filter. Can be called repeatedly.
*/
CURLcode Curl_ssl_peer_init(struct ssl_peer *peer,
- struct Curl_cfilter *cf, int transport);
+ struct Curl_cfilter *cf,
+ const char *tls_id,
+ int transport);
/**
* Free all allocated data and reset peer information.
*/
@@ -130,8 +164,6 @@ CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);
-/* init the SSL session ID cache */
-CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
void Curl_ssl_version(char *buffer, size_t size);
/* Certificate information list handling. */
@@ -147,33 +179,6 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, /* Functions to be used by SSL library adaptation functions */
-/* Lock session cache mutex.
- * Call this before calling other Curl_ssl_*session* functions
- * Caller should unlock this mutex as soon as possible, as it may block
- * other SSL connection from making progress.
- * The purpose of explicitly locking SSL session cache data is to allow
- * individual SSL engines to manage session lifetime in their specific way.
- */
-void Curl_ssl_sessionid_lock(struct Curl_easy *data);
-
-/* Unlock session cache mutex */
-void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
-
-/* Kill a single session ID entry in the cache
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * This will call engine-specific curlssl_session_free function, which must
- * take sessionid object ownership from sessionid cache
- * (e.g. decrement refcount).
- */
-void Curl_ssl_kill_session(struct Curl_ssl_session *session);
-/* delete a session from the cache
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * This will call engine-specific curlssl_session_free function, which must
- * take sessionid object ownership from sessionid cache
- * (e.g. decrement refcount).
- */
-void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid);
-
/* get N random bytes into the buffer */
CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
size_t length);
@@ -184,7 +189,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, bool Curl_ssl_cert_status_request(void);
-bool Curl_ssl_false_start(struct Curl_easy *data);
+bool Curl_ssl_false_start(void);
/* The maximum size of the SSL channel binding is 85 bytes, as defined in
* RFC 5929, Section 4.1. The 'tls-server-end-point:' prefix is 21 bytes long,
@@ -265,12 +270,10 @@ extern struct Curl_cftype Curl_cft_ssl_proxy; #define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
#define Curl_ssl_engines_list(x) NULL
-#define Curl_ssl_initsessions(x,y) CURLE_OK
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
-#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
-#define Curl_ssl_false_start(a) FALSE
+#define Curl_ssl_false_start() FALSE
#define Curl_ssl_get_internals(a,b,c,d) NULL
#define Curl_ssl_supports(a,b) FALSE
#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h index 250273ef9d..bb37346396 100644 --- a/libs/libcurl/src/vtls/vtls_int.h +++ b/libs/libcurl/src/vtls/vtls_int.h @@ -26,9 +26,11 @@ #include "curl_setup.h"
#include "cfilters.h"
#include "urldata.h"
+#include "vtls.h"
#ifdef USE_SSL
+struct Curl_ssl;
struct ssl_connect_data;
/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
@@ -103,12 +105,15 @@ typedef enum { /* Information in each SSL cfilter context: cf->ctx */
struct ssl_connect_data {
- struct ssl_peer peer;
+ const struct Curl_ssl *ssl_impl; /* TLS backend for this filter */
+ struct ssl_peer peer; /* peer the filter talks to */
const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
struct curltime handshake_done; /* time when handshake finished */
- char *alpn_negotiated; /* negotiated ALPN value or NULL */
+ struct {
+ char *alpn; /* ALPN value or NULL */
+ } negotiated;
struct bufq earlydata; /* earlydata to be send to peer */
size_t earlydata_max; /* max earlydata allowed by peer */
size_t earlydata_skip; /* sending bytes to skip when earlydata
@@ -142,7 +147,6 @@ struct Curl_ssl { void (*cleanup)(void);
size_t (*version)(char *buffer, size_t size);
- int (*check_cxn)(struct Curl_cfilter *cf, struct Curl_easy *data);
CURLcode (*shut_down)(struct Curl_cfilter *cf, struct Curl_easy *data,
bool send_shutdown, bool *done);
bool (*data_pending)(struct Curl_cfilter *cf,
@@ -174,10 +178,6 @@ struct Curl_ssl { bool (*false_start)(void);
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
-
- bool (*attach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
- void (*detach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
-
ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *code);
ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -190,66 +190,14 @@ struct Curl_ssl { extern const struct Curl_ssl *Curl_ssl;
-
-int Curl_none_init(void);
-void Curl_none_cleanup(void);
-CURLcode Curl_none_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data,
- bool send_shutdown, bool *done);
-int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data);
-void Curl_none_close_all(struct Curl_easy *data);
-void Curl_none_session_free(void *ptr);
-bool Curl_none_data_pending(struct Curl_cfilter *cf,
- const struct Curl_easy *data);
-bool Curl_none_cert_status_request(void);
-CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
-CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
-struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
-bool Curl_none_false_start(void);
void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
- struct easy_pollset *ps);
+ struct easy_pollset *ps);
/**
* Get the SSL filter below the given one or NULL if there is none.
*/
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf);
-/* extract a session ID
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * Caller must make sure that the ownership of returned sessionid object
- * is properly taken (e.g. its refcount is incremented
- * under sessionid mutex).
- * @param cf the connection filter wanting to use it
- * @param data the transfer involved
- * @param peer the peer the filter wants to talk to
- * @param sessionid on return the TLS session
- * @param idsize on return the size of the TLS session data
- * @param palpn on return the ALPN string used by the session,
- * set to NULL when not interested
- */
-bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- void **ssl_sessionid,
- size_t *idsize, /* set 0 if unknown */
- char **palpn);
-
-/* Set a TLS session ID for `peer`. Replaces an existing session ID if
- * not already the same.
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * Call takes ownership of `ssl_sessionid`, using `sessionid_free_cb`
- * to deallocate it. Is called in all outcomes, either right away or
- * later when the session cache is cleaned up.
- * Caller must ensure that it has properly shared ownership of this sessionid
- * object with cache (e.g. incrementing refcount on success)
- */
-CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- const char *alpn,
- void *sessionid,
- size_t sessionid_size,
- Curl_ssl_sessionid_dtor *sessionid_free_cb);
-
#endif /* USE_SSL */
#endif /* HEADER_CURL_VTLS_INT_H */
diff --git a/libs/libcurl/src/vtls/vtls_scache.c b/libs/libcurl/src/vtls/vtls_scache.c new file mode 100644 index 0000000000..c78ef7e9a8 --- /dev/null +++ b/libs/libcurl/src/vtls/vtls_scache.c @@ -0,0 +1,1213 @@ +/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_SSL
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "urldata.h"
+#include "cfilters.h"
+
+#include "vtls.h" /* generic SSL protos etc */
+#include "vtls_int.h"
+#include "vtls_scache.h"
+#include "vtls_spack.h"
+
+#include "strcase.h"
+#include "url.h"
+#include "llist.h"
+#include "share.h"
+#include "curl_trc.h"
+#include "curl_sha256.h"
+#include "rand.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "strdup.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* a peer+tls-config we cache sessions for */
+struct Curl_ssl_scache_peer {
+ char *ssl_peer_key; /* id for peer + relevant TLS configuration */
+ char *clientcert;
+ char *srp_username;
+ char *srp_password;
+ struct Curl_llist sessions;
+ void *sobj; /* object instance or NULL */
+ Curl_ssl_scache_obj_dtor *sobj_free; /* free `sobj` callback */
+ unsigned char key_salt[CURL_SHA256_DIGEST_LENGTH]; /* for entry export */
+ unsigned char key_hmac[CURL_SHA256_DIGEST_LENGTH]; /* for entry export */
+ size_t max_sessions;
+ long age; /* just a number, the higher the more recent */
+ BIT(hmac_set); /* if key_salt and key_hmac are present */
+};
+
+#define CURL_SCACHE_MAGIC 0x000e1551
+
+#define GOOD_SCACHE(x) ((x) && (x)->magic == CURL_SCACHE_MAGIC)
+
+struct Curl_ssl_scache {
+ unsigned int magic;
+ struct Curl_ssl_scache_peer *peers;
+ size_t peer_count;
+ int default_lifetime_secs;
+ long age;
+};
+
+static struct Curl_ssl_scache *cf_ssl_scache_get(struct Curl_easy *data)
+{
+ struct Curl_ssl_scache *scache = NULL;
+ /* If a share is present, its ssl_scache has preference over the multi */
+ if(data->share && data->share->ssl_scache)
+ scache = data->share->ssl_scache;
+ else if(data->multi && data->multi->ssl_scache)
+ scache = data->multi->ssl_scache;
+ if(scache && !GOOD_SCACHE(scache)) {
+ failf(data, "transfer would use an invalid scache at %p, denied",
+ (void *)scache);
+ DEBUGASSERT(0);
+ return NULL;
+ }
+ return scache;
+}
+
+static void cf_ssl_scache_clear_session(struct Curl_ssl_session *s)
+{
+ if(s->sdata) {
+ free((void *)s->sdata);
+ s->sdata = NULL;
+ }
+ s->sdata_len = 0;
+ if(s->quic_tp) {
+ free((void *)s->quic_tp);
+ s->quic_tp = NULL;
+ }
+ s->quic_tp_len = 0;
+ s->ietf_tls_id = 0;
+ s->valid_until = 0;
+ Curl_safefree(s->alpn);
+}
+
+static void cf_ssl_scache_sesssion_ldestroy(void *udata, void *s)
+{
+ (void)udata;
+ cf_ssl_scache_clear_session(s);
+ free(s);
+}
+
+CURLcode
+Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len,
+ int ietf_tls_id, const char *alpn,
+ curl_off_t valid_until, size_t earlydata_max,
+ struct Curl_ssl_session **psession)
+{
+ return Curl_ssl_session_create2(sdata, sdata_len, ietf_tls_id, alpn,
+ valid_until, earlydata_max,
+ NULL, 0, psession);
+}
+
+CURLcode
+Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len,
+ int ietf_tls_id, const char *alpn,
+ curl_off_t valid_until, size_t earlydata_max,
+ unsigned char *quic_tp, size_t quic_tp_len,
+ struct Curl_ssl_session **psession)
+{
+ struct Curl_ssl_session *s;
+
+ if(!sdata || !sdata_len) {
+ free(sdata);
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ *psession = NULL;
+ s = calloc(1, sizeof(*s));
+ if(!s) {
+ free(sdata);
+ free(quic_tp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ s->ietf_tls_id = ietf_tls_id;
+ s->valid_until = valid_until;
+ s->earlydata_max = earlydata_max;
+ s->sdata = sdata;
+ s->sdata_len = sdata_len;
+ s->quic_tp = quic_tp;
+ s->quic_tp_len = quic_tp_len;
+ if(alpn) {
+ s->alpn = strdup(alpn);
+ if(!s->alpn) {
+ cf_ssl_scache_sesssion_ldestroy(NULL, s);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ *psession = s;
+ return CURLE_OK;
+}
+
+void Curl_ssl_session_destroy(struct Curl_ssl_session *s)
+{
+ if(s) {
+ /* if in the list, the list destructor takes care of it */
+ if(Curl_node_llist(&s->list))
+ Curl_node_remove(&s->list);
+ else {
+ cf_ssl_scache_sesssion_ldestroy(NULL, s);
+ }
+ }
+}
+
+static void cf_ssl_scache_clear_peer(struct Curl_ssl_scache_peer *peer)
+{
+ Curl_llist_destroy(&peer->sessions, NULL);
+ if(peer->sobj) {
+ DEBUGASSERT(peer->sobj_free);
+ if(peer->sobj_free)
+ peer->sobj_free(peer->sobj);
+ peer->sobj = NULL;
+ }
+ peer->sobj_free = NULL;
+ Curl_safefree(peer->clientcert);
+#ifdef USE_TLS_SRP
+ Curl_safefree(peer->srp_username);
+ Curl_safefree(peer->srp_password);
+#endif
+ Curl_safefree(peer->ssl_peer_key);
+ peer->age = 0;
+ peer->hmac_set = FALSE;
+}
+
+static void cf_ssl_scache_peer_set_obj(struct Curl_ssl_scache_peer *peer,
+ void *sobj,
+ Curl_ssl_scache_obj_dtor *sobj_free)
+{
+ DEBUGASSERT(peer);
+ if(peer->sobj_free) {
+ peer->sobj_free(peer->sobj);
+ }
+ peer->sobj = sobj;
+ peer->sobj_free = sobj_free;
+}
+
+static CURLcode
+cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer,
+ const char *ssl_peer_key,
+ const char *clientcert,
+ const char *srp_username,
+ const char *srp_password,
+ const unsigned char *salt,
+ const unsigned char *hmac)
+{
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ DEBUGASSERT(!peer->ssl_peer_key);
+ if(ssl_peer_key) {
+ peer->ssl_peer_key = strdup(ssl_peer_key);
+ if(!peer->ssl_peer_key)
+ goto out;
+ peer->hmac_set = FALSE;
+ }
+ else if(salt && hmac) {
+ memcpy(peer->key_salt, salt, sizeof(peer->key_salt));
+ memcpy(peer->key_hmac, hmac, sizeof(peer->key_hmac));
+ peer->hmac_set = TRUE;
+ }
+ else {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
+ }
+ if(clientcert) {
+ peer->clientcert = strdup(clientcert);
+ if(!peer->clientcert)
+ goto out;
+ }
+ if(srp_username) {
+ peer->srp_username = strdup(srp_username);
+ if(!peer->srp_username)
+ goto out;
+ }
+ if(srp_password) {
+ peer->srp_password = strdup(srp_password);
+ if(!peer->srp_password)
+ goto out;
+ }
+ result = CURLE_OK;
+out:
+ if(result)
+ cf_ssl_scache_clear_peer(peer);
+ return result;
+}
+
+static void cf_scache_session_remove(struct Curl_ssl_scache_peer *peer,
+ struct Curl_ssl_session *s)
+{
+ (void)peer;
+ DEBUGASSERT(Curl_node_llist(&s->list) == &peer->sessions);
+ Curl_ssl_session_destroy(s);
+}
+
+static bool cf_scache_session_expired(struct Curl_ssl_session *s,
+ curl_off_t now)
+{
+ return (s->valid_until > 0) && (s->valid_until < now);
+}
+
+static void cf_scache_peer_remove_expired(struct Curl_ssl_scache_peer *peer,
+ curl_off_t now)
+{
+ struct Curl_llist_node *n = Curl_llist_head(&peer->sessions);
+ while(n) {
+ struct Curl_ssl_session *s = Curl_node_elem(n);
+ n = Curl_node_next(n);
+ if(cf_scache_session_expired(s, now))
+ cf_scache_session_remove(peer, s);
+ }
+}
+
+static void cf_scache_peer_remove_non13(struct Curl_ssl_scache_peer *peer)
+{
+ struct Curl_llist_node *n = Curl_llist_head(&peer->sessions);
+ while(n) {
+ struct Curl_ssl_session *s = Curl_node_elem(n);
+ n = Curl_node_next(n);
+ if(s->ietf_tls_id != CURL_IETF_PROTO_TLS1_3)
+ cf_scache_session_remove(peer, s);
+ }
+}
+
+CURLcode Curl_ssl_scache_create(size_t max_peers,
+ size_t max_sessions_per_peer,
+ struct Curl_ssl_scache **pscache)
+{
+ struct Curl_ssl_scache *scache;
+ struct Curl_ssl_scache_peer *peers;
+ size_t i;
+
+ *pscache = NULL;
+ peers = calloc(max_peers, sizeof(*peers));
+ if(!peers)
+ return CURLE_OUT_OF_MEMORY;
+
+ scache = calloc(1, sizeof(*scache));
+ if(!scache) {
+ free(peers);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ scache->magic = CURL_SCACHE_MAGIC;
+ scache->default_lifetime_secs = (24*60*60); /* 1 day */
+ scache->peer_count = max_peers;
+ scache->peers = peers;
+ scache->age = 1;
+ for(i = 0; i < scache->peer_count; ++i) {
+ scache->peers[i].max_sessions = max_sessions_per_peer;
+ Curl_llist_init(&scache->peers[i].sessions,
+ cf_ssl_scache_sesssion_ldestroy);
+ }
+
+ *pscache = scache;
+ return CURLE_OK;
+}
+
+void Curl_ssl_scache_destroy(struct Curl_ssl_scache *scache)
+{
+ if(scache && GOOD_SCACHE(scache)) {
+ size_t i;
+ scache->magic = 0;
+ for(i = 0; i < scache->peer_count; ++i) {
+ cf_ssl_scache_clear_peer(&scache->peers[i]);
+ }
+ free(scache->peers);
+ free(scache);
+ }
+}
+
+/* Lock shared SSL session data */
+void Curl_ssl_scache_lock(struct Curl_easy *data)
+{
+ if(CURL_SHARE_ssl_scache(data))
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+}
+
+/* Unlock shared SSL session data */
+void Curl_ssl_scache_unlock(struct Curl_easy *data)
+{
+ if(CURL_SHARE_ssl_scache(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+}
+
+static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
+ const char *name,
+ char *path)
+{
+ if(path && path[0]) {
+ /* We try to add absolute paths, so that the session key can stay
+ * valid when used in another process with different CWD. However,
+ * when a path does not exist, this does not work. Then, we add
+ * the path as is. */
+#ifdef _WIN32
+ char abspath[_MAX_PATH];
+ if(_fullpath(abspath, path, _MAX_PATH))
+ return Curl_dyn_addf(buf, ":%s-%s", name, abspath);
+#elif defined(HAVE_REALPATH)
+ if(path[0] != '/') {
+ char *abspath = realpath(path, NULL);
+ if(abspath) {
+ CURLcode r = Curl_dyn_addf(buf, ":%s-%s", name, abspath);
+ (free)(abspath); /* allocated by libc, free without memdebug */
+ return r;
+ }
+ }
+#endif
+ return Curl_dyn_addf(buf, ":%s-%s", name, path);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_ssl_peer_key_add_hash(struct dynbuf *buf,
+ const char *name,
+ struct curl_blob *blob)
+{
+ CURLcode r = CURLE_OK;
+ if(blob && blob->len) {
+ unsigned char hash[CURL_SHA256_DIGEST_LENGTH];
+ size_t i;
+
+ r = Curl_dyn_addf(buf, ":%s-", name);
+ if(r)
+ goto out;
+ r = Curl_sha256it(hash, blob->data, blob->len);
+ if(r)
+ goto out;
+ for(i = 0; i < CURL_SHA256_DIGEST_LENGTH; ++i) {
+ r = Curl_dyn_addf(buf, "%02x", hash[i]);
+ if(r)
+ goto out;
+ }
+ }
+out:
+ return r;
+}
+
+CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
+ const struct ssl_peer *peer,
+ const char *tls_id,
+ char **ppeer_key)
+{
+ struct ssl_primary_config *ssl = Curl_ssl_cf_get_primary_config(cf);
+ struct dynbuf buf;
+ size_t key_len;
+ CURLcode r;
+
+ *ppeer_key = NULL;
+ Curl_dyn_init(&buf, 10 * 1024);
+
+ r = Curl_dyn_addf(&buf, "%s:%d", peer->hostname, peer->port);
+ if(r)
+ goto out;
+
+ switch(peer->transport) {
+ case TRNSPRT_TCP:
+ break;
+ case TRNSPRT_UDP:
+ r = Curl_dyn_add(&buf, ":UDP");
+ break;
+ case TRNSPRT_QUIC:
+ r = Curl_dyn_add(&buf, ":QUIC");
+ break;
+ case TRNSPRT_UNIX:
+ r = Curl_dyn_add(&buf, ":UNIX");
+ break;
+ default:
+ r = Curl_dyn_addf(&buf, ":TRNSPRT-%d", peer->transport);
+ break;
+ }
+ if(r)
+ goto out;
+
+ if(!ssl->verifypeer) {
+ r = Curl_dyn_add(&buf, ":NO-VRFY-PEER");
+ if(r)
+ goto out;
+ }
+ if(!ssl->verifyhost) {
+ r = Curl_dyn_add(&buf, ":NO-VRFY-HOST");
+ if(r)
+ goto out;
+ }
+ if(ssl->verifystatus) {
+ r = Curl_dyn_add(&buf, ":VRFY-STATUS");
+ if(r)
+ goto out;
+ }
+ if(!ssl->verifypeer || !ssl->verifyhost) {
+ if(cf->conn->bits.conn_to_host) {
+ r = Curl_dyn_addf(&buf, ":CHOST-%s", cf->conn->conn_to_host.name);
+ if(r)
+ goto out;
+ }
+ if(cf->conn->bits.conn_to_port) {
+ r = Curl_dyn_addf(&buf, ":CPORT-%d", cf->conn->conn_to_port);
+ if(r)
+ goto out;
+ }
+ }
+
+ if(ssl->version || ssl->version_max) {
+ r = Curl_dyn_addf(&buf, ":TLSVER-%d-%d", ssl->version,
+ (ssl->version_max >> 16));
+ if(r)
+ goto out;
+ }
+ if(ssl->ssl_options) {
+ r = Curl_dyn_addf(&buf, ":TLSOPT-%x", ssl->ssl_options);
+ if(r)
+ goto out;
+ }
+ if(ssl->cipher_list) {
+ r = Curl_dyn_addf(&buf, ":CIPHER-%s", ssl->cipher_list);
+ if(r)
+ goto out;
+ }
+ if(ssl->cipher_list13) {
+ r = Curl_dyn_addf(&buf, ":CIPHER13-%s", ssl->cipher_list13);
+ if(r)
+ goto out;
+ }
+ if(ssl->curves) {
+ r = Curl_dyn_addf(&buf, ":CURVES-%s", ssl->curves);
+ if(r)
+ goto out;
+ }
+ if(ssl->verifypeer) {
+ r = cf_ssl_peer_key_add_path(&buf, "CA", ssl->CAfile);
+ if(r)
+ goto out;
+ r = cf_ssl_peer_key_add_path(&buf, "CApath", ssl->CApath);
+ if(r)
+ goto out;
+ r = cf_ssl_peer_key_add_path(&buf, "CRL", ssl->CRLfile);
+ if(r)
+ goto out;
+ r = cf_ssl_peer_key_add_path(&buf, "Issuer", ssl->issuercert);
+ if(r)
+ goto out;
+ if(ssl->cert_blob) {
+ r = cf_ssl_peer_key_add_hash(&buf, "CertBlob", ssl->cert_blob);
+ if(r)
+ goto out;
+ }
+ if(ssl->ca_info_blob) {
+ r = cf_ssl_peer_key_add_hash(&buf, "CAInfoBlob", ssl->ca_info_blob);
+ if(r)
+ goto out;
+ }
+ if(ssl->issuercert_blob) {
+ r = cf_ssl_peer_key_add_hash(&buf, "IssuerBlob", ssl->issuercert_blob);
+ if(r)
+ goto out;
+ }
+ }
+ if(ssl->pinned_key && ssl->pinned_key[0]) {
+ r = Curl_dyn_addf(&buf, ":Pinned-%s", ssl->pinned_key);
+ if(r)
+ goto out;
+ }
+
+ if(ssl->clientcert && ssl->clientcert[0]) {
+ r = Curl_dyn_add(&buf, ":CCERT");
+ if(r)
+ goto out;
+ }
+#ifdef USE_TLS_SRP
+ if(ssl->username || ssl->password) {
+ r = Curl_dyn_add(&buf, ":SRP-AUTH");
+ if(r)
+ goto out;
+ }
+#endif
+
+ if(!tls_id || !tls_id[0]) {
+ r = CURLE_FAILED_INIT;
+ goto out;
+ }
+ r = Curl_dyn_addf(&buf, ":IMPL-%s", tls_id);
+ if(r)
+ goto out;
+
+ *ppeer_key = Curl_dyn_take(&buf, &key_len);
+ /* we just added printable char, and dynbuf always 0 terminates,
+ * no need to track length */
+
+
+out:
+ Curl_dyn_free(&buf);
+ return r;
+}
+
+static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer,
+ struct ssl_primary_config *conn_config)
+{
+ if(!conn_config) {
+ if(peer->clientcert)
+ return FALSE;
+#ifdef USE_TLS_SRP
+ if(peer->srp_username || peer->srp_password)
+ return FALSE;
+#endif
+ return TRUE;
+ }
+ else if(!Curl_safecmp(peer->clientcert, conn_config->clientcert))
+ return FALSE;
+#ifdef USE_TLS_SRP
+ if(Curl_timestrcmp(peer->srp_username, conn_config->username) ||
+ Curl_timestrcmp(peer->srp_password, conn_config->password))
+ return FALSE;
+#endif
+ return TRUE;
+}
+
+static CURLcode
+cf_ssl_find_peer_by_key(struct Curl_easy *data,
+ struct Curl_ssl_scache *scache,
+ const char *ssl_peer_key,
+ struct ssl_primary_config *conn_config,
+ struct Curl_ssl_scache_peer **ppeer)
+{
+ size_t i, peer_key_len = 0;
+ CURLcode result = CURLE_OK;
+
+ *ppeer = NULL;
+ if(!GOOD_SCACHE(scache)) {
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ CURL_TRC_SSLS(data, "find peer slot for %s among %zu slots",
+ ssl_peer_key, scache->peer_count);
+
+ /* check for entries with known peer_key */
+ for(i = 0; scache && i < scache->peer_count; i++) {
+ if(scache->peers[i].ssl_peer_key &&
+ strcasecompare(ssl_peer_key, scache->peers[i].ssl_peer_key) &&
+ cf_ssl_scache_match_auth(&scache->peers[i], conn_config)) {
+ /* yes, we have a cached session for this! */
+ *ppeer = &scache->peers[i];
+ goto out;
+ }
+ }
+ /* check for entries with HMAC set but no known peer_key */
+ for(i = 0; scache && i < scache->peer_count; i++) {
+ if(!scache->peers[i].ssl_peer_key &&
+ scache->peers[i].hmac_set &&
+ cf_ssl_scache_match_auth(&scache->peers[i], conn_config)) {
+ /* possible entry with unknown peer_key, check hmac */
+ unsigned char my_hmac[CURL_SHA256_DIGEST_LENGTH];
+ if(!peer_key_len) /* we are lazy */
+ peer_key_len = strlen(ssl_peer_key);
+ result = Curl_hmacit(&Curl_HMAC_SHA256,
+ scache->peers[i].key_salt,
+ sizeof(scache->peers[i].key_salt),
+ (const unsigned char *)ssl_peer_key,
+ peer_key_len,
+ my_hmac);
+ if(result)
+ goto out;
+ if(!memcmp(scache->peers[i].key_hmac, my_hmac, sizeof(my_hmac))) {
+ /* remember peer_key for future lookups */
+ CURL_TRC_SSLS(data, "peer entry %zu key recovered: %s",
+ i, ssl_peer_key);
+ scache->peers[i].ssl_peer_key = strdup(ssl_peer_key);
+ if(!scache->peers[i].ssl_peer_key) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *ppeer = &scache->peers[i];
+ goto out;
+ }
+ }
+ }
+ CURL_TRC_SSLS(data, "peer not found for %s", ssl_peer_key);
+out:
+ return result;
+}
+
+static struct Curl_ssl_scache_peer *
+cf_ssl_get_free_peer(struct Curl_ssl_scache *scache)
+{
+ struct Curl_ssl_scache_peer *peer = NULL;
+ size_t i;
+
+ /* find empty or oldest peer */
+ for(i = 0; i < scache->peer_count; ++i) {
+ /* free peer entry? */
+ if(!scache->peers[i].ssl_peer_key && !scache->peers[i].hmac_set) {
+ peer = &scache->peers[i];
+ break;
+ }
+ /* peer without sessions and obj */
+ if(!scache->peers[i].sobj &&
+ !Curl_llist_count(&scache->peers[i].sessions)) {
+ peer = &scache->peers[i];
+ break;
+ }
+ /* remember "oldest" peer */
+ if(!peer || (scache->peers[i].age < peer->age)) {
+ peer = &scache->peers[i];
+ }
+ }
+ DEBUGASSERT(peer);
+ if(peer)
+ cf_ssl_scache_clear_peer(peer);
+ return peer;
+}
+
+static CURLcode
+cf_ssl_add_peer(struct Curl_easy *data,
+ struct Curl_ssl_scache *scache,
+ const char *ssl_peer_key,
+ struct ssl_primary_config *conn_config,
+ struct Curl_ssl_scache_peer **ppeer)
+{
+ struct Curl_ssl_scache_peer *peer = NULL;
+ CURLcode result = CURLE_OK;
+
+ *ppeer = NULL;
+ if(ssl_peer_key) {
+ result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
+ &peer);
+ if(result || !scache->peer_count)
+ return result;
+ }
+
+ if(peer) {
+ *ppeer = peer;
+ return CURLE_OK;
+ }
+
+ peer = cf_ssl_get_free_peer(scache);
+ if(peer) {
+ const char *ccert = conn_config ? conn_config->clientcert : NULL;
+ const char *username = NULL, *password = NULL;
+#ifdef USE_TLS_SRP
+ username = conn_config ? conn_config->username : NULL;
+ password = conn_config ? conn_config->password : NULL;
+#endif
+ result = cf_ssl_scache_peer_init(peer, ssl_peer_key, ccert,
+ username, password, NULL, NULL);
+ if(result)
+ goto out;
+ /* all ready */
+ *ppeer = peer;
+ result = CURLE_OK;
+ }
+
+out:
+ if(result) {
+ cf_ssl_scache_clear_peer(peer);
+ }
+ return result;
+}
+
+static void cf_scache_peer_add_session(struct Curl_ssl_scache_peer *peer,
+ struct Curl_ssl_session *s,
+ curl_off_t now)
+{
+ /* A session not from TLSv1.3 replaces all other. */
+ if(s->ietf_tls_id != CURL_IETF_PROTO_TLS1_3) {
+ Curl_llist_destroy(&peer->sessions, NULL);
+ Curl_llist_append(&peer->sessions, s, &s->list);
+ }
+ else {
+ /* Expire existing, append, trim from head to obey max_sessions */
+ cf_scache_peer_remove_expired(peer, now);
+ cf_scache_peer_remove_non13(peer);
+ Curl_llist_append(&peer->sessions, s, &s->list);
+ while(Curl_llist_count(&peer->sessions) > peer->max_sessions) {
+ Curl_node_remove(Curl_llist_head(&peer->sessions));
+ }
+ }
+}
+
+static CURLcode cf_scache_add_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct Curl_ssl_scache *scache,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session *s)
+{
+ struct Curl_ssl_scache_peer *peer = NULL;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ curl_off_t now = (curl_off_t)time(NULL);
+ curl_off_t max_lifetime;
+
+ if(!scache || !scache->peer_count) {
+ Curl_ssl_session_destroy(s);
+ return CURLE_OK;
+ }
+
+ if(s->valid_until <= 0)
+ s->valid_until = now + scache->default_lifetime_secs;
+
+ max_lifetime = (s->ietf_tls_id == CURL_IETF_PROTO_TLS1_3) ?
+ CURL_SCACHE_MAX_13_LIFETIME_SEC :
+ CURL_SCACHE_MAX_12_LIFETIME_SEC;
+ if(s->valid_until > (now + max_lifetime))
+ s->valid_until = now + max_lifetime;
+
+ if(cf_scache_session_expired(s, now)) {
+ CURL_TRC_SSLS(data, "add, session already expired");
+ Curl_ssl_session_destroy(s);
+ return CURLE_OK;
+ }
+
+ result = cf_ssl_add_peer(data, scache, ssl_peer_key, conn_config, &peer);
+ if(result || !peer) {
+ CURL_TRC_SSLS(data, "unable to add scache peer: %d", result);
+ Curl_ssl_session_destroy(s);
+ goto out;
+ }
+
+ cf_scache_peer_add_session(peer, s, now);
+
+out:
+ if(result) {
+ failf(data, "[SCACHE] failed to add session for %s, error=%d",
+ ssl_peer_key, result);
+ }
+ else
+ CURL_TRC_SSLS(data, "added session for %s [proto=0x%x, "
+ "valid_secs=%" FMT_OFF_T ", alpn=%s, earlydata=%zu, "
+ "quic_tp=%s], peer has %zu sessions now",
+ ssl_peer_key, s->ietf_tls_id, s->valid_until - now,
+ s->alpn, s->earlydata_max, s->quic_tp ? "yes" : "no",
+ peer ? Curl_llist_count(&peer->sessions) : 0);
+ return result;
+}
+
+CURLcode Curl_ssl_scache_put(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session *s)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ CURLcode result;
+ DEBUGASSERT(ssl_config);
+
+ if(!scache || !ssl_config->primary.cache_session) {
+ Curl_ssl_session_destroy(s);
+ return CURLE_OK;
+ }
+ if(!GOOD_SCACHE(scache)) {
+ Curl_ssl_session_destroy(s);
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ Curl_ssl_scache_lock(data);
+ result = cf_scache_add_session(cf, data, scache, ssl_peer_key, s);
+ Curl_ssl_scache_unlock(data);
+ return result;
+}
+
+void Curl_ssl_scache_return(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session *s)
+{
+ /* See RFC 8446 C.4:
+ * "Clients SHOULD NOT reuse a ticket for multiple connections." */
+ if(s && s->ietf_tls_id < 0x304)
+ (void)Curl_ssl_scache_put(cf, data, ssl_peer_key, s);
+ else
+ Curl_ssl_session_destroy(s);
+}
+
+CURLcode Curl_ssl_scache_take(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session **ps)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_ssl_scache_peer *peer = NULL;
+ struct Curl_llist_node *n;
+ struct Curl_ssl_session *s = NULL;
+ CURLcode result;
+
+ *ps = NULL;
+ if(!scache)
+ return CURLE_OK;
+
+ Curl_ssl_scache_lock(data);
+ result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
+ &peer);
+ if(!result && peer) {
+ cf_scache_peer_remove_expired(peer, (curl_off_t)time(NULL));
+ n = Curl_llist_head(&peer->sessions);
+ if(n) {
+ s = Curl_node_take_elem(n);
+ (scache->age)++; /* increase general age */
+ peer->age = scache->age; /* set this as used in this age */
+ }
+ }
+ Curl_ssl_scache_unlock(data);
+ if(s) {
+ *ps = s;
+ CURL_TRC_SSLS(data, "took session for %s [proto=0x%x, "
+ "alpn=%s, earlydata=%zu, quic_tp=%s], %zu sessions remain",
+ ssl_peer_key, s->ietf_tls_id, s->alpn,
+ s->earlydata_max, s->quic_tp ? "yes" : "no",
+ Curl_llist_count(&peer->sessions));
+ }
+ else {
+ CURL_TRC_SSLS(data, "no cached session for %s", ssl_peer_key);
+ }
+ return result;
+}
+
+CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ void *sobj,
+ Curl_ssl_scache_obj_dtor *sobj_free)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_ssl_scache_peer *peer = NULL;
+ CURLcode result;
+
+ DEBUGASSERT(sobj);
+ DEBUGASSERT(sobj_free);
+
+ if(!scache) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
+ }
+
+ result = cf_ssl_add_peer(data, scache, ssl_peer_key, conn_config, &peer);
+ if(result || !peer) {
+ CURL_TRC_SSLS(data, "unable to add scache peer: %d", result);
+ goto out;
+ }
+
+ cf_ssl_scache_peer_set_obj(peer, sobj, sobj_free);
+ sobj = NULL; /* peer took ownership */
+
+out:
+ if(sobj && sobj_free)
+ sobj_free(sobj);
+ return result;
+}
+
+bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ void **sobj)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_ssl_scache_peer *peer = NULL;
+ CURLcode result;
+
+ *sobj = NULL;
+ if(!scache)
+ return FALSE;
+
+ result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
+ &peer);
+ if(result)
+ return FALSE;
+
+ if(peer)
+ *sobj = peer->sobj;
+
+ CURL_TRC_SSLS(data, "%s cached session for '%s'",
+ *sobj ? "Found" : "No", ssl_peer_key);
+ return !!*sobj;
+}
+
+void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_ssl_scache_peer *peer = NULL;
+ CURLcode result;
+
+ (void)cf;
+ if(!scache)
+ return;
+
+ Curl_ssl_scache_lock(data);
+ result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
+ &peer);
+ if(!result && peer)
+ cf_ssl_scache_clear_peer(peer);
+ Curl_ssl_scache_unlock(data);
+}
+
+#ifdef USE_SSLS_EXPORT
+
+#define CURL_SSL_TICKET_MAX (16*1024)
+
+static CURLcode cf_ssl_scache_peer_set_hmac(struct Curl_ssl_scache_peer *peer)
+{
+ CURLcode result;
+
+ DEBUGASSERT(peer);
+ if(!peer->ssl_peer_key)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ result = Curl_rand(NULL, peer->key_salt, sizeof(peer->key_salt));
+ if(result)
+ return result;
+
+ result = Curl_hmacit(&Curl_HMAC_SHA256,
+ peer->key_salt, sizeof(peer->key_salt),
+ (const unsigned char *)peer->ssl_peer_key,
+ strlen(peer->ssl_peer_key),
+ peer->key_hmac);
+ if(!result)
+ peer->hmac_set = TRUE;
+ return result;
+}
+
+static CURLcode
+cf_ssl_find_peer_by_hmac(struct Curl_ssl_scache *scache,
+ const unsigned char *salt,
+ const unsigned char *hmac,
+ struct Curl_ssl_scache_peer **ppeer)
+{
+ size_t i;
+ CURLcode result = CURLE_OK;
+
+ *ppeer = NULL;
+ if(!GOOD_SCACHE(scache))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* look for an entry that matches salt+hmac exactly or has a known
+ * ssl_peer_key which salt+hmac's to the same. */
+ for(i = 0; scache && i < scache->peer_count; i++) {
+ struct Curl_ssl_scache_peer *peer = &scache->peers[i];
+ if(!cf_ssl_scache_match_auth(peer, NULL))
+ continue;
+ if(scache->peers[i].hmac_set &&
+ !memcmp(peer->key_salt, salt, sizeof(peer->key_salt)) &&
+ !memcmp(peer->key_hmac, hmac, sizeof(peer->key_hmac))) {
+ /* found exact match, return */
+ *ppeer = peer;
+ goto out;
+ }
+ else if(peer->ssl_peer_key) {
+ unsigned char my_hmac[CURL_SHA256_DIGEST_LENGTH];
+ /* compute hmac for the passed salt */
+ result = Curl_hmacit(&Curl_HMAC_SHA256,
+ salt, sizeof(peer->key_salt),
+ (const unsigned char *)peer->ssl_peer_key,
+ strlen(peer->ssl_peer_key),
+ my_hmac);
+ if(result)
+ goto out;
+ if(!memcmp(my_hmac, hmac, sizeof(my_hmac))) {
+ /* cryptohash match, take over salt+hmac if no set and return */
+ if(!peer->hmac_set) {
+ memcpy(peer->key_salt, salt, sizeof(peer->key_salt));
+ memcpy(peer->key_hmac, hmac, sizeof(peer->key_hmac));
+ peer->hmac_set = TRUE;
+ }
+ *ppeer = peer;
+ goto out;
+ }
+ }
+ }
+out:
+ return result;
+}
+
+CURLcode Curl_ssl_session_import(struct Curl_easy *data,
+ const char *ssl_peer_key,
+ const unsigned char *shmac, size_t shmac_len,
+ const unsigned char *sdata, size_t sdata_len)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct Curl_ssl_scache_peer *peer = NULL;
+ struct Curl_ssl_session *s = NULL;
+ bool locked = FALSE;
+ CURLcode r;
+
+ if(!scache) {
+ r = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
+ }
+ if(!ssl_peer_key && (!shmac || !shmac_len)) {
+ r = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
+ }
+
+ r = Curl_ssl_session_unpack(data, sdata, sdata_len, &s);
+ if(r)
+ goto out;
+
+ Curl_ssl_scache_lock(data);
+ locked = TRUE;
+
+ if(ssl_peer_key) {
+ r = cf_ssl_add_peer(data, scache, ssl_peer_key, NULL, &peer);
+ if(r)
+ goto out;
+ }
+ else if(shmac_len != (sizeof(peer->key_salt) + sizeof(peer->key_hmac))) {
+ /* Either salt+hmac was garbled by caller or is from a curl version
+ * that does things differently */
+ r = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
+ }
+ else {
+ const unsigned char *salt = shmac;
+ const unsigned char *hmac = shmac + sizeof(peer->key_salt);
+
+ r = cf_ssl_find_peer_by_hmac(scache, salt, hmac, &peer);
+ if(r)
+ goto out;
+ if(!peer) {
+ peer = cf_ssl_get_free_peer(scache);
+ if(peer) {
+ r = cf_ssl_scache_peer_init(peer, ssl_peer_key, NULL,
+ NULL, NULL, salt, hmac);
+ if(r)
+ goto out;
+ }
+ }
+ }
+
+ if(peer) {
+ cf_scache_peer_add_session(peer, s, time(NULL));
+ s = NULL; /* peer is now owner */
+ CURL_TRC_SSLS(data, "successfully imported ticket for peer %s, now "
+ "with %zu tickets",
+ peer->ssl_peer_key ? peer->ssl_peer_key : "without key",
+ Curl_llist_count(&peer->sessions));
+ }
+
+out:
+ if(locked)
+ Curl_ssl_scache_unlock(data);
+ Curl_ssl_session_destroy(s);
+ return r;
+}
+
+CURLcode Curl_ssl_session_export(struct Curl_easy *data,
+ curl_ssls_export_cb *export_fn,
+ void *userptr)
+{
+ struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+ struct Curl_ssl_scache_peer *peer;
+ struct dynbuf sbuf, hbuf;
+ struct Curl_llist_node *n;
+ size_t i, npeers = 0, ntickets = 0;
+ curl_off_t now = time(NULL);
+ CURLcode r = CURLE_OK;
+
+ if(!export_fn)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(!scache)
+ return CURLE_OK;
+
+ Curl_ssl_scache_lock(data);
+
+ Curl_dyn_init(&hbuf, (CURL_SHA256_DIGEST_LENGTH * 2) + 1);
+ Curl_dyn_init(&sbuf, CURL_SSL_TICKET_MAX);
+
+ for(i = 0; scache && i < scache->peer_count; i++) {
+ peer = &scache->peers[i];
+ if(!peer->ssl_peer_key && !peer->hmac_set)
+ continue; /* skip free entry */
+ if(peer->clientcert || peer->srp_username || peer->srp_password)
+ continue; /* not exporting those */
+
+ Curl_dyn_reset(&hbuf);
+ cf_scache_peer_remove_expired(peer, now);
+ n = Curl_llist_head(&peer->sessions);
+ if(n)
+ ++npeers;
+ while(n) {
+ struct Curl_ssl_session *s = Curl_node_elem(n);
+ if(!peer->hmac_set) {
+ r = cf_ssl_scache_peer_set_hmac(peer);
+ if(r)
+ goto out;
+ }
+ if(!Curl_dyn_len(&hbuf)) {
+ r = Curl_dyn_addn(&hbuf, peer->key_salt, sizeof(peer->key_salt));
+ if(r)
+ goto out;
+ r = Curl_dyn_addn(&hbuf, peer->key_hmac, sizeof(peer->key_hmac));
+ if(r)
+ goto out;
+ }
+ Curl_dyn_reset(&sbuf);
+ r = Curl_ssl_session_pack(data, s, &sbuf);
+ if(r)
+ goto out;
+
+ r = export_fn(data, userptr, peer->ssl_peer_key,
+ Curl_dyn_uptr(&hbuf), Curl_dyn_len(&hbuf),
+ Curl_dyn_uptr(&sbuf), Curl_dyn_len(&sbuf),
+ s->valid_until, s->ietf_tls_id,
+ s->alpn, s->earlydata_max);
+ if(r)
+ goto out;
+ ++ntickets;
+ n = Curl_node_next(n);
+ }
+
+ }
+ r = CURLE_OK;
+ CURL_TRC_SSLS(data, "exported %zu session tickets for %zu peers",
+ ntickets, npeers);
+
+out:
+ Curl_ssl_scache_unlock(data);
+ Curl_dyn_free(&hbuf);
+ Curl_dyn_free(&sbuf);
+ return r;
+}
+
+#endif /* USE_SSLS_EXPORT */
+
+#endif /* USE_SSL */
diff --git a/libs/libcurl/src/vtls/vtls_scache.h b/libs/libcurl/src/vtls/vtls_scache.h new file mode 100644 index 0000000000..e9b5b76e36 --- /dev/null +++ b/libs/libcurl/src/vtls/vtls_scache.h @@ -0,0 +1,218 @@ +#ifndef HEADER_CURL_VTLS_SCACHE_H
+#define HEADER_CURL_VTLS_SCACHE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include "cfilters.h"
+#include "urldata.h"
+
+#ifdef USE_SSL
+
+struct Curl_cfilter;
+struct Curl_easy;
+struct Curl_ssl_scache;
+struct Curl_ssl_session;
+struct ssl_peer;
+
+/* RFC 8446 (TLSv1.3) restrict lifetime to one week max, for
+ * other, less secure versions, we restrict it to a day */
+#define CURL_SCACHE_MAX_13_LIFETIME_SEC (60*60*24*7)
+#define CURL_SCACHE_MAX_12_LIFETIME_SEC (60*60*24)
+
+/* Create a session cache for up to max_peers endpoints with a total
+ * of up to max_sessions SSL sessions per peer */
+CURLcode Curl_ssl_scache_create(size_t max_peers,
+ size_t max_sessions_per_peer,
+ struct Curl_ssl_scache **pscache);
+
+void Curl_ssl_scache_destroy(struct Curl_ssl_scache *scache);
+
+/* Create a key from peer and TLS configuration information that is
+ * unique for how the connection filter wants to establish a TLS
+ * connection to the peer.
+ * If the filter is a TLS proxy filter, it will use the proxy relevant
+ * information.
+ * @param cf the connection filter wanting to use it
+ * @param peer the peer the filter wants to talk to
+ * @param tls_id identifier of TLS implementation for sessions. Should
+ * include full version if session data from other versions
+ * is to be avoided.
+ * @param ppeer_key on successful return, the key generated
+ */
+CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
+ const struct ssl_peer *peer,
+ const char *tls_id,
+ char **ppeer_key);
+
+/* Lock session cache mutex.
+ * Call this before calling other Curl_ssl_*session* functions
+ * Caller should unlock this mutex as soon as possible, as it may block
+ * other SSL connection from making progress.
+ * The purpose of explicitly locking SSL session cache data is to allow
+ * individual SSL engines to manage session lifetime in their specific way.
+ */
+void Curl_ssl_scache_lock(struct Curl_easy *data);
+
+/* Unlock session cache mutex */
+void Curl_ssl_scache_unlock(struct Curl_easy *data);
+
+/* Get TLS session object from the cache for the ssl_peer_ey.
+ * scache mutex must be locked (see Curl_ssl_scache_lock).
+ * Caller must make sure that the ownership of returned session object
+ * is properly taken (e.g. its refcount is incremented
+ * under scache mutex).
+ * @param cf the connection filter wanting to use it
+ * @param data the transfer involved
+ * @param ssl_peer_key the key for lookup
+ * @param sobj on return, the object for the peer key or NULL
+ */
+bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ void **sobj);
+
+typedef void Curl_ssl_scache_obj_dtor(void *sobj);
+
+/* Add a TLS session related object to the cache.
+ * Replaces an existing object with the same peer_key.
+ * scache mutex must be locked (see Curl_ssl_scache_lock).
+ * Call takes ownership of `sobj`, using `sobj_dtor_cb`
+ * to deallocate it. Is called in all outcomes, either right away or
+ * later when the session cache is cleaned up.
+ * Caller must ensure that it has properly shared ownership of `sobj`
+ * with cache (e.g. incrementing refcount on success)
+ * @param cf the connection filter wanting to use it
+ * @param data the transfer involved
+ * @param ssl_peer_key the key for lookup
+ * @param sobj the TLS session object
+ * @param sobj_free_cb callback to free the session objectt
+ */
+CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ void *sobj,
+ Curl_ssl_scache_obj_dtor *sobj_dtor_cb);
+
+/* All about a SSL session ticket */
+struct Curl_ssl_session {
+ const unsigned char *sdata; /* session ticket data, plain bytes */
+ size_t sdata_len; /* number of bytes in sdata */
+ curl_off_t valid_until; /* seconds since EPOCH until ticket expires */
+ int ietf_tls_id; /* TLS protocol identifier negotiated */
+ char *alpn; /* APLN TLS negotiated protocol string */
+ size_t earlydata_max; /* max 0-RTT data supported by peer */
+ const unsigned char *quic_tp; /* Optional QUIC transport param bytes */
+ size_t quic_tp_len; /* number of bytes in quic_tp */
+ struct Curl_llist_node list; /* internal storage handling */
+};
+
+/* Create a `session` instance. Does NOT need locking.
+ * Takes ownership of `sdata` and `sobj` regardless of return code.
+ * @param sdata bytes of SSL session data or NULL (sobj then required)
+ * @param sdata_len amount of session data bytes
+ * @param ietf_tls_id IETF protocol version, e.g. 0x304 for TLSv1.3
+ * @param alpn ALPN protocol selected or NULL
+ * @param valid_until seconds since EPOCH when session expires, pass 0
+ * in case this is not known.
+ * @param psession on return the scached session instance created
+ */
+CURLcode
+Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len,
+ int ietf_tls_id, const char *alpn,
+ curl_off_t valid_until,
+ size_t earlydata_max,
+ struct Curl_ssl_session **psession);
+
+/* Variation of session creation with quic transport parameter bytes,
+ * Takes ownership of `quic_tp` regardless of return code. */
+CURLcode
+Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len,
+ int ietf_tls_id, const char *alpn,
+ curl_off_t valid_until,
+ size_t earlydata_max,
+ unsigned char *quic_tp, size_t quic_tp_len,
+ struct Curl_ssl_session **psession);
+
+/* Destroy a `session` instance. Can be called with NULL.
+ * Does NOT need locking. */
+void Curl_ssl_session_destroy(struct Curl_ssl_session *s);
+
+/* Put the scache session into the cache. Does NOT need locking.
+ * Call takes ownership of `s` in all outcomes.
+ * @param cf the connection filter wanting to use it
+ * @param data the transfer involved
+ * @param ssl_peer_key the key for lookup
+ * @param s the scache session object
+ */
+CURLcode Curl_ssl_scache_put(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session *s);
+
+/* Take a matching scache session from the cache. Does NOT need locking.
+ * @param cf the connection filter wanting to use it
+ * @param data the transfer involved
+ * @param ssl_peer_key the key for lookup
+ * @param s on return, the scache session object or NULL
+ */
+CURLcode Curl_ssl_scache_take(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session **ps);
+
+/* Return a taken scache session to the cache. Does NOT need locking.
+ * Depending on TLS version and other criteria, it may cache it again
+ * or destroy it. Maybe called with a NULL session.
+ */
+void Curl_ssl_scache_return(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ struct Curl_ssl_session *s);
+
+/* Remove all sessions and obj for the peer_key. Does NOT need locking. */
+void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key);
+
+#ifdef USE_SSLS_EXPORT
+
+CURLcode Curl_ssl_session_import(struct Curl_easy *data,
+ const char *ssl_peer_key,
+ const unsigned char *shmac, size_t shmac_len,
+ const unsigned char *sdata, size_t sdata_len);
+
+CURLcode Curl_ssl_session_export(struct Curl_easy *data,
+ curl_ssls_export_cb *export_fn,
+ void *userptr);
+
+#endif /* USE_SSLS_EXPORT */
+
+#else /* USE_SSL */
+
+#define Curl_ssl_scache_create(x,y,z) ((void)x, CURLE_OK)
+#define Curl_ssl_scache_destroy(x) do {} while(0)
+
+#endif /* USE_SSL (else) */
+
+#endif /* HEADER_CURL_VTLS_SCACHE_H */
diff --git a/libs/libcurl/src/vtls/vtls_spack.c b/libs/libcurl/src/vtls/vtls_spack.c new file mode 100644 index 0000000000..22c84e8a38 --- /dev/null +++ b/libs/libcurl/src/vtls/vtls_spack.c @@ -0,0 +1,345 @@ +/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_SSLS_EXPORT
+
+#include "urldata.h"
+#include "curl_trc.h"
+#include "vtls_scache.h"
+#include "vtls_spack.h"
+#include "strdup.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1600
+#include <stdint.h>
+#else
+typedef unsigned char uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif
+#endif /* _MSC_VER */
+
+#ifndef UINT16_MAX
+#define UINT16_MAX 0xffff
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
+#define CURL_SPACK_VERSION 0x01
+#define CURL_SPACK_IETF_ID 0x02
+#define CURL_SPACK_VALID_UNTIL 0x03
+#define CURL_SPACK_TICKET 0x04
+#define CURL_SPACK_ALPN 0x05
+#define CURL_SPACK_EARLYDATA 0x06
+#define CURL_SPACK_QUICTP 0x07
+
+static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b)
+{
+ return Curl_dyn_addn(buf, &b, 1);
+}
+
+static CURLcode
+spack_dec8(uint8_t *val, const uint8_t **src, const uint8_t *end)
+{
+ if(end - *src < 1)
+ return CURLE_READ_ERROR;
+ *val = **src;
+ *src += 1;
+ return CURLE_OK;
+}
+
+static CURLcode spack_enc16(struct dynbuf *buf, uint16_t val)
+{
+ uint8_t nval[2];
+ nval[0] = (uint8_t)(val >> 8);
+ nval[1] = (uint8_t)val;
+ return Curl_dyn_addn(buf, nval, sizeof(nval));
+}
+
+static CURLcode
+spack_dec16(uint16_t *val, const uint8_t **src, const uint8_t *end)
+{
+ if(end - *src < 2)
+ return CURLE_READ_ERROR;
+ *val = (uint16_t)((*src)[0] << 8 | (*src)[1]);
+ *src += 2;
+ return CURLE_OK;
+}
+
+static CURLcode spack_enc32(struct dynbuf *buf, uint32_t val)
+{
+ uint8_t nval[4];
+ nval[0] = (uint8_t)(val >> 24);
+ nval[1] = (uint8_t)(val >> 16);
+ nval[2] = (uint8_t)(val >> 8);
+ nval[3] = (uint8_t)val;
+ return Curl_dyn_addn(buf, nval, sizeof(nval));
+}
+
+static CURLcode
+spack_dec32(uint32_t *val, const uint8_t **src, const uint8_t *end)
+{
+ if(end - *src < 4)
+ return CURLE_READ_ERROR;
+ *val = (uint32_t)(*src)[0] << 24 | (uint32_t)(*src)[1] << 16 |
+ (uint32_t)(*src)[2] << 8 | (*src)[3];
+ *src += 4;
+ return CURLE_OK;
+}
+
+static CURLcode spack_enc64(struct dynbuf *buf, uint64_t val)
+{
+ uint8_t nval[8];
+ nval[0] = (uint8_t)(val >> 56);
+ nval[1] = (uint8_t)(val >> 48);
+ nval[2] = (uint8_t)(val >> 40);
+ nval[3] = (uint8_t)(val >> 32); \
+ nval[4] = (uint8_t)(val >> 24);
+ nval[5] = (uint8_t)(val >> 16);
+ nval[6] = (uint8_t)(val >> 8);
+ nval[7] = (uint8_t)val;
+ return Curl_dyn_addn(buf, nval, sizeof(nval));
+}
+
+static CURLcode
+spack_dec64(uint64_t *val, const uint8_t **src, const uint8_t *end)
+{
+ if(end - *src < 8)
+ return CURLE_READ_ERROR;
+ *val = (uint64_t)(*src)[0] << 56 | (uint64_t)(*src)[1] << 48 |
+ (uint64_t)(*src)[2] << 40 | (uint64_t)(*src)[3] << 32 |
+ (uint64_t)(*src)[4] << 24 | (uint64_t)(*src)[5] << 16 |
+ (uint64_t)(*src)[6] << 8 | (*src)[7];
+ *src += 8;
+ return CURLE_OK;
+}
+
+static CURLcode spack_encstr16(struct dynbuf *buf, const char *s)
+{
+ size_t slen = strlen(s);
+ CURLcode r;
+ if(slen > UINT16_MAX)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ r = spack_enc16(buf, (uint16_t)slen);
+ if(!r) {
+ r = Curl_dyn_addn(buf, s, slen);
+ }
+ return r;
+}
+
+static CURLcode
+spack_decstr16(char **val, const uint8_t **src, const uint8_t *end)
+{
+ uint16_t slen;
+ CURLcode r;
+
+ *val = NULL;
+ r = spack_dec16(&slen, src, end);
+ if(r)
+ return r;
+ if(end - *src < slen)
+ return CURLE_READ_ERROR;
+ *val = Curl_memdup0((const char *)(*src), slen);
+ *src += slen;
+ return *val ? CURLE_OK : CURLE_OUT_OF_MEMORY;
+}
+
+static CURLcode spack_encdata16(struct dynbuf *buf,
+ const uint8_t *data, size_t data_len)
+{
+ CURLcode r;
+ if(data_len > UINT16_MAX)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ r = spack_enc16(buf, (uint16_t)data_len);
+ if(!r) {
+ r = Curl_dyn_addn(buf, data, data_len);
+ }
+ return r;
+}
+
+static CURLcode
+spack_decdata16(uint8_t **val, size_t *val_len,
+ const uint8_t **src, const uint8_t *end)
+{
+ uint16_t data_len;
+ CURLcode r;
+
+ *val = NULL;
+ r = spack_dec16(&data_len, src, end);
+ if(r)
+ return r;
+ if(end - *src < data_len)
+ return CURLE_READ_ERROR;
+ *val = Curl_memdup0((const char *)(*src), data_len);
+ *val_len = data_len;
+ *src += data_len;
+ return *val ? CURLE_OK : CURLE_OUT_OF_MEMORY;
+}
+
+CURLcode Curl_ssl_session_pack(struct Curl_easy *data,
+ struct Curl_ssl_session *s,
+ struct dynbuf *buf)
+{
+ CURLcode r;
+ DEBUGASSERT(s->sdata);
+ DEBUGASSERT(s->sdata_len);
+
+ if(s->valid_until < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ r = spack_enc8(buf, CURL_SPACK_VERSION);
+ if(!r)
+ r = spack_enc8(buf, CURL_SPACK_TICKET);
+ if(!r)
+ r = spack_encdata16(buf, s->sdata, s->sdata_len);
+ if(!r)
+ r = spack_enc8(buf, CURL_SPACK_IETF_ID);
+ if(!r)
+ r = spack_enc16(buf, (uint16_t)s->ietf_tls_id);
+ if(!r)
+ r = spack_enc8(buf, CURL_SPACK_VALID_UNTIL);
+ if(!r)
+ r = spack_enc64(buf, (uint64_t)s->valid_until);
+ if(!r && s->alpn) {
+ r = spack_enc8(buf, CURL_SPACK_ALPN);
+ if(!r)
+ r = spack_encstr16(buf, s->alpn);
+ }
+ if(!r && s->earlydata_max) {
+ if(s->earlydata_max > UINT32_MAX)
+ r = CURLE_BAD_FUNCTION_ARGUMENT;
+ if(!r)
+ r = spack_enc8(buf, CURL_SPACK_EARLYDATA);
+ if(!r)
+ r = spack_enc32(buf, (uint32_t)s->earlydata_max);
+ }
+ if(!r && s->quic_tp && s->quic_tp_len) {
+ r = spack_enc8(buf, CURL_SPACK_QUICTP);
+ if(!r)
+ r = spack_encdata16(buf, s->quic_tp, s->quic_tp_len);
+ }
+
+ if(r)
+ CURL_TRC_SSLS(data, "error packing data: %d", r);
+ return r;
+}
+
+CURLcode Curl_ssl_session_unpack(struct Curl_easy *data,
+ const unsigned char *buf, size_t buflen,
+ struct Curl_ssl_session **ps)
+{
+ struct Curl_ssl_session *s = NULL;
+ const unsigned char *end = buf + buflen;
+ uint8_t val8, *pval8;
+ uint16_t val16;
+ uint32_t val32;
+ uint64_t val64;
+ CURLcode r;
+
+ DEBUGASSERT(buf);
+ DEBUGASSERT(buflen);
+ *ps = NULL;
+
+ r = spack_dec8(&val8, &buf, end);
+ if(r)
+ goto out;
+ if(val8 != CURL_SPACK_VERSION) {
+ r = CURLE_READ_ERROR;
+ goto out;
+ }
+
+ s = calloc(1, sizeof(*s));
+ if(!s) {
+ r = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ while(buf < end) {
+ r = spack_dec8(&val8, &buf, end);
+ if(r)
+ goto out;
+
+ switch(val8) {
+ case CURL_SPACK_ALPN:
+ r = spack_decstr16(&s->alpn, &buf, end);
+ if(r)
+ goto out;
+ break;
+ case CURL_SPACK_EARLYDATA:
+ r = spack_dec32(&val32, &buf, end);
+ if(r)
+ goto out;
+ s->earlydata_max = val32;
+ break;
+ case CURL_SPACK_IETF_ID:
+ r = spack_dec16(&val16, &buf, end);
+ if(r)
+ goto out;
+ s->ietf_tls_id = val16;
+ break;
+ case CURL_SPACK_QUICTP: {
+ r = spack_decdata16(&pval8, &s->quic_tp_len, &buf, end);
+ if(r)
+ goto out;
+ s->quic_tp = pval8;
+ break;
+ }
+ case CURL_SPACK_TICKET: {
+ r = spack_decdata16(&pval8, &s->sdata_len, &buf, end);
+ if(r)
+ goto out;
+ s->sdata = pval8;
+ break;
+ }
+ case CURL_SPACK_VALID_UNTIL:
+ r = spack_dec64(&val64, &buf, end);
+ if(r)
+ goto out;
+ s->valid_until = (curl_off_t)val64;
+ break;
+ default: /* unknown tag */
+ r = CURLE_READ_ERROR;
+ goto out;
+ }
+ }
+
+out:
+ if(r) {
+ CURL_TRC_SSLS(data, "error unpacking data: %d", r);
+ Curl_ssl_session_destroy(s);
+ }
+ else
+ *ps = s;
+ return r;
+}
+
+#endif /* USE_SSLS_EXPORT */
diff --git a/libs/libcurl/src/vtls/vtls_spack.h b/libs/libcurl/src/vtls/vtls_spack.h new file mode 100644 index 0000000000..ec48853e4c --- /dev/null +++ b/libs/libcurl/src/vtls/vtls_spack.h @@ -0,0 +1,43 @@ +#ifndef HEADER_CURL_VTLS_SPACK_H
+#define HEADER_CURL_VTLS_SPACK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_SSLS_EXPORT
+
+struct dynbuf;
+struct Curl_ssl_session;
+
+CURLcode Curl_ssl_session_pack(struct Curl_easy *data,
+ struct Curl_ssl_session *s,
+ struct dynbuf *buf);
+
+CURLcode Curl_ssl_session_unpack(struct Curl_easy *data,
+ const unsigned char *buf, size_t buflen,
+ struct Curl_ssl_session **ps);
+
+#endif /* USE_SSLS_EXPORT */
+
+#endif /* HEADER_CURL_VTLS_SPACK_H */
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index a624d3ff0c..edd60e3e1a 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -60,6 +60,7 @@ #include "inet_pton.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "keylog.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
@@ -69,7 +70,6 @@ #include "curl_printf.h"
#include "multiif.h"
-#include <wolfssl/openssl/ssl.h>
#include <wolfssl/ssl.h>
#include <wolfssl/error-ssl.h>
#include "wolfssl.h"
@@ -78,13 +78,9 @@ #include "curl_memory.h"
#include "memdebug.h"
-#ifdef USE_ECH
-# include "curl_base64.h"
-# define ECH_ENABLED(__data__) \
- (__data__->set.tls_ech && \
- !(__data__->set.tls_ech & CURLECH_DISABLE)\
- )
-#endif /* USE_ECH */
+#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
+#define USE_ECH_WOLFSSL
+#endif
/* KEEP_PEER_CERT is a product of the presence of build time symbol
OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
@@ -299,7 +295,7 @@ static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) #ifdef WOLFSSL_BIO_CTRL_EOF
case WOLFSSL_BIO_CTRL_EOF:
/* EOF has been reached on input? */
- return (!cf->next || !cf->next->connected);
+ return !cf->next || !cf->next->connected;
#endif
default:
ret = 0;
@@ -400,57 +396,54 @@ static void wolfssl_bio_cf_free_methods(void) #endif /* !USE_BIO_CHAIN */
-static void wolfssl_session_free(void *sdata, size_t slen)
-{
- (void)slen;
- free(sdata);
-}
-
-CURLcode wssl_cache_session(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct ssl_peer *peer,
- WOLFSSL_SESSION *session)
+CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ WOLFSSL_SESSION *session,
+ int ietf_tls_id,
+ const char *alpn)
{
CURLcode result = CURLE_OK;
+ struct Curl_ssl_session *sc_session = NULL;
unsigned char *sdata = NULL;
- unsigned int slen;
+ unsigned int sdata_len;
if(!session)
goto out;
- slen = wolfSSL_i2d_SSL_SESSION(session, NULL);
- if(slen <= 0) {
- CURL_TRC_CF(data, cf, "fail to assess session length: %u", slen);
+ sdata_len = wolfSSL_i2d_SSL_SESSION(session, NULL);
+ if(sdata_len <= 0) {
+ CURL_TRC_CF(data, cf, "fail to assess session length: %u", sdata_len);
result = CURLE_FAILED_INIT;
goto out;
}
- sdata = calloc(1, slen);
+ sdata = calloc(1, sdata_len);
if(!sdata) {
- failf(data, "unable to allocate session buffer of %u bytes", slen);
+ failf(data, "unable to allocate session buffer of %u bytes", sdata_len);
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- slen = wolfSSL_i2d_SSL_SESSION(session, &sdata);
- if(slen <= 0) {
- CURL_TRC_CF(data, cf, "fail to serialize session: %u", slen);
+ sdata_len = wolfSSL_i2d_SSL_SESSION(session, &sdata);
+ if(sdata_len <= 0) {
+ CURL_TRC_CF(data, cf, "fail to serialize session: %u", sdata_len);
result = CURLE_FAILED_INIT;
goto out;
}
- Curl_ssl_sessionid_lock(data);
- result = Curl_ssl_set_sessionid(cf, data, peer, NULL,
- sdata, slen, wolfssl_session_free);
- Curl_ssl_sessionid_unlock(data);
- if(result)
- failf(data, "failed to add new ssl session to cache (%d)", result);
- else {
- CURL_TRC_CF(data, cf, "added new session to cache");
- sdata = NULL;
+ result = Curl_ssl_session_create(sdata, sdata_len,
+ ietf_tls_id, alpn,
+ (curl_off_t)time(NULL) +
+ wolfSSL_SESSION_get_timeout(session), 0,
+ &sc_session);
+ sdata = NULL; /* took ownership of sdata */
+ if(!result) {
+ result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
+ /* took ownership of `sc_session` */
}
out:
free(sdata);
- return 0;
+ return result;
}
static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
@@ -465,32 +458,35 @@ static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) DEBUGASSERT(connssl);
DEBUGASSERT(data);
if(connssl && data) {
- (void)wssl_cache_session(cf, data, &connssl->peer, session);
+ (void)Curl_wssl_cache_session(cf, data, connssl->peer.scache_key,
+ session, wolfSSL_version(ssl),
+ connssl->negotiated.alpn);
}
}
return 0;
}
-CURLcode wssl_setup_session(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct wolfssl_ctx *wss,
- struct ssl_peer *peer)
+CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct wolfssl_ctx *wss,
+ const char *ssl_peer_key)
{
- void *psdata;
- const unsigned char *sdata = NULL;
- size_t slen = 0;
- CURLcode result = CURLE_OK;
+ struct Curl_ssl_session *sc_session = NULL;
+ CURLcode result;
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, peer, &psdata, &slen, NULL)) {
+ result = Curl_ssl_scache_take(cf, data, ssl_peer_key, &sc_session);
+ if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
WOLFSSL_SESSION *session;
- sdata = psdata;
- session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata, (long)slen);
+ /* wolfSSL changes the passed pointer for whatever reasons, yikes */
+ const unsigned char *sdata = sc_session->sdata;
+ session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata,
+ (long)sc_session->sdata_len);
if(session) {
int ret = wolfSSL_set_session(wss->handle, session);
if(ret != WOLFSSL_SUCCESS) {
- Curl_ssl_delsessionid(data, psdata);
- infof(data, "previous session not accepted (%d), "
+ Curl_ssl_session_destroy(sc_session);
+ sc_session = NULL;
+ infof(data, "cached session not accepted (%d), "
"removing from cache", ret);
}
else
@@ -501,14 +497,14 @@ CURLcode wssl_setup_session(struct Curl_cfilter *cf, failf(data, "could not decode previous session");
}
}
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_return(cf, data, ssl_peer_key, sc_session);
return result;
}
-static CURLcode populate_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- WOLFSSL_X509_STORE *store,
- struct wolfssl_ctx *wssl)
+static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ WOLFSSL_X509_STORE *store,
+ struct wolfssl_ctx *wssl)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
@@ -556,7 +552,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, #ifndef NO_FILESYSTEM
/* load trusted cacert from file if not blob */
- CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+ CURL_TRC_CF(data, cf, "wssl_populate_x509_store, path=%s, blob=%d",
ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
@@ -620,8 +616,8 @@ static void wssl_x509_share_free(void *key, size_t key_len, void *p) }
static bool
-cached_x509_store_expired(const struct Curl_easy *data,
- const struct wssl_x509_share *mb)
+wssl_cached_x509_store_expired(const struct Curl_easy *data,
+ const struct wssl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
struct curltime now = Curl_now();
@@ -635,8 +631,8 @@ cached_x509_store_expired(const struct Curl_easy *data, }
static bool
-cached_x509_store_different(struct Curl_cfilter *cf,
- const struct wssl_x509_share *mb)
+wssl_cached_x509_store_different(struct Curl_cfilter *cf,
+ const struct wssl_x509_share *mb)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
if(!mb->CAfile || !conn_config->CAfile)
@@ -645,8 +641,8 @@ cached_x509_store_different(struct Curl_cfilter *cf, return strcmp(mb->CAfile, conn_config->CAfile);
}
-static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
+static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct wssl_x509_share *share;
@@ -657,17 +653,17 @@ static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, (void *)MPROTO_WSSL_X509_KEY,
sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
if(share && share->store &&
- !cached_x509_store_expired(data, share) &&
- !cached_x509_store_different(cf, share)) {
+ !wssl_cached_x509_store_expired(data, share) &&
+ !wssl_cached_x509_store_different(cf, share)) {
store = share->store;
}
return store;
}
-static void set_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data,
- WOLFSSL_X509_STORE *store)
+static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ WOLFSSL_X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
@@ -735,7 +731,8 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, !ssl_config->primary.CRLfile &&
!ssl_config->native_ca_store;
- cached_store = cache_criteria_met ? get_cached_x509_store(cf, data) : NULL;
+ cached_store = cache_criteria_met ? wssl_get_cached_x509_store(cf, data)
+ : NULL;
if(cached_store && wolfSSL_CTX_get_cert_store(wssl->ctx) == cached_store) {
/* The cached store is already in use, do nothing. */
}
@@ -752,15 +749,15 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, }
wolfSSL_CTX_set_cert_store(wssl->ctx, store);
- result = populate_x509_store(cf, data, store, wssl);
+ result = wssl_populate_x509_store(cf, data, store, wssl);
if(!result) {
- set_cached_x509_store(cf, data, store);
+ wssl_set_cached_x509_store(cf, data, store);
}
}
else {
/* We never share the CTX's store, use it. */
WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
- result = populate_x509_store(cf, data, store, wssl);
+ result = wssl_populate_x509_store(cf, data, store, wssl);
}
return result;
@@ -773,7 +770,7 @@ wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) int i;
char *str;
- for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
+ for(i = 0; (str = wolfSSL_get_cipher_list(i)) != NULL; i++) {
size_t n;
if((strncmp(str, "TLS13", 5) == 0) != tls13)
continue;
@@ -1192,13 +1189,13 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* Check if there is a cached ID we can/should use here! */
if(ssl_config->primary.cache_session) {
/* Set session from cache if there is one */
- (void)wssl_setup_session(cf, data, backend, &connssl->peer);
+ (void)Curl_wssl_setup_session(cf, data, backend, connssl->peer.scache_key);
/* Register to get notified when a new session is received */
wolfSSL_set_app_data(backend->handle, cf);
wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
}
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
if(ECH_ENABLED(data)) {
int trying_ech_now = 0;
@@ -1265,14 +1262,14 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) }
}
- if(trying_ech_now
- && SSL_set_min_proto_version(backend->handle, TLS1_3_VERSION) != 1) {
+ if(trying_ech_now && wolfSSL_set_min_proto_version(backend->handle,
+ TLS1_3_VERSION) != 1) {
infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
return CURLE_SSL_CONNECT_ERROR;
}
}
-#endif /* USE_ECH */
+#endif /* USE_ECH_WOLFSSL */
#ifdef USE_BIO_CHAIN
{
@@ -1441,7 +1438,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) failf(data, "server verification failed: certificate not valid yet.");
return CURLE_PEER_FAILED_VERIFICATION;
}
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
else if(-1 == detail) {
/* try access a retry_config ECHConfigList for tracing */
byte echConfigs[1000];
@@ -1796,7 +1793,7 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, }
-static size_t wolfssl_version(char *buffer, size_t size)
+size_t Curl_wssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
@@ -2020,7 +2017,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { #endif
SSLSUPP_CA_PATH |
SSLSUPP_CAINFO_BLOB |
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
SSLSUPP_ECH |
#endif
SSLSUPP_SSL_CTX |
@@ -2034,25 +2031,22 @@ const struct Curl_ssl Curl_ssl_wolfssl = { wolfssl_init, /* init */
wolfssl_cleanup, /* cleanup */
- wolfssl_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
+ Curl_wssl_version, /* version */
wolfssl_shutdown, /* shutdown */
wolfssl_data_pending, /* data_pending */
wolfssl_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
wolfssl_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
wolfssl_recv, /* recv decrypted data */
wolfssl_send, /* send data to encrypt */
NULL, /* get_channel_binding */
diff --git a/libs/libcurl/src/vtls/wolfssl.h b/libs/libcurl/src/vtls/wolfssl.h index 0a4d253a58..24f676366c 100644 --- a/libs/libcurl/src/vtls/wolfssl.h +++ b/libs/libcurl/src/vtls/wolfssl.h @@ -47,19 +47,23 @@ struct wolfssl_ctx { BIT(shutting_down); /* TLS is being shut down */
};
+size_t Curl_wssl_version(char *buffer, size_t size);
+
CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct wolfssl_ctx *wssl);
-CURLcode wssl_setup_session(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct wolfssl_ctx *wss,
- struct ssl_peer *peer);
+CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct wolfssl_ctx *wss,
+ const char *ssl_peer_key);
-CURLcode wssl_cache_session(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct ssl_peer *peer,
- WOLFSSL_SESSION *session);
+CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key,
+ WOLFSSL_SESSION *session,
+ int ietf_tls_id,
+ const char *alpn);
#endif /* USE_WOLFSSL */
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c index 6e1fbfab49..f38137e0f2 100644 --- a/libs/libcurl/src/vtls/x509asn1.c +++ b/libs/libcurl/src/vtls/x509asn1.c @@ -178,8 +178,11 @@ static const char *getASN1Element(struct Curl_asn1Element *elem, const char *beg, const char *end)
WARN_UNUSED_RESULT;
-static const char *getASN1Element(struct Curl_asn1Element *elem,
- const char *beg, const char *end)
+#define CURL_ASN1_MAX_RECURSIONS 16
+
+static const char *getASN1Element_(struct Curl_asn1Element *elem,
+ const char *beg, const char *end,
+ size_t lvl)
{
unsigned char b;
size_t len;
@@ -190,7 +193,8 @@ static const char *getASN1Element(struct Curl_asn1Element *elem, Returns a pointer in source string after the parsed element, or NULL
if an error occurs. */
if(!beg || !end || beg >= end || !*beg ||
- (size_t)(end - beg) > CURL_ASN1_MAX)
+ ((size_t)(end - beg) > CURL_ASN1_MAX) ||
+ lvl >= CURL_ASN1_MAX_RECURSIONS)
return NULL;
/* Process header byte. */
@@ -216,7 +220,7 @@ static const char *getASN1Element(struct Curl_asn1Element *elem, return NULL;
elem->beg = beg;
while(beg < end && *beg) {
- beg = getASN1Element(&lelem, beg, end);
+ beg = getASN1Element_(&lelem, beg, end, lvl + 1);
if(!beg)
return NULL;
}
@@ -243,6 +247,12 @@ static const char *getASN1Element(struct Curl_asn1Element *elem, return elem->end;
}
+static const char *getASN1Element(struct Curl_asn1Element *elem,
+ const char *beg, const char *end)
+{
+ return getASN1Element_(elem, beg, end, 0);
+}
+
#ifdef WANT_EXTRACT_CERTINFO
/*
@@ -259,6 +269,17 @@ static const struct Curl_OID *searchOID(const char *oid) return NULL;
}
+#ifdef UNITTESTS
+/* used by unit1657.c */
+CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
+ const char *beg, const char *end)
+{
+ if(getASN1Element(elem, beg, end))
+ return CURLE_OK;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+}
+#endif
+
/*
* Convert an ASN.1 Boolean value into its string representation.
*
diff --git a/libs/libcurl/src/vtls/x509asn1.h b/libs/libcurl/src/vtls/x509asn1.h index b0155d11a2..670a565302 100644 --- a/libs/libcurl/src/vtls/x509asn1.h +++ b/libs/libcurl/src/vtls/x509asn1.h @@ -85,6 +85,9 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data, /* used by unit1656.c */
CURLcode Curl_x509_GTime2str(struct dynbuf *store,
const char *beg, const char *end);
+/* used by unit1657.c */
+CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
+ const char *beg, const char *end);
#endif
#endif
diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/warnless.c index 33aec8aec1..ecfbfb8c9e 100644 --- a/libs/libcurl/src/warnless.c +++ b/libs/libcurl/src/warnless.c @@ -101,28 +101,6 @@ unsigned char curlx_ultouc(unsigned long ulnum) }
/*
-** unsigned size_t to signed curl_off_t
-*/
-
-curl_off_t curlx_uztoso(size_t uznum)
-{
-#ifdef __INTEL_COMPILER
-# pragma warning(push)
-# pragma warning(disable:810) /* conversion may lose significant bits */
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning(disable:4310) /* cast truncates constant value */
-#endif
-
- DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT);
- return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT);
-
-#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-}
-
-/*
** unsigned size_t to signed int
*/
@@ -148,8 +126,8 @@ int curlx_uztosi(size_t uznum) unsigned long curlx_uztoul(size_t uznum)
{
#ifdef __INTEL_COMPILER
-# pragma warning(push)
-# pragma warning(disable:810) /* conversion may lose significant bits */
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
#if ULONG_MAX < SIZE_T_MAX
@@ -158,7 +136,7 @@ unsigned long curlx_uztoul(size_t uznum) return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
#ifdef __INTEL_COMPILER
-# pragma warning(pop)
+# pragma warning(pop)
#endif
}
@@ -169,8 +147,8 @@ unsigned long curlx_uztoul(size_t uznum) unsigned int curlx_uztoui(size_t uznum)
{
#ifdef __INTEL_COMPILER
-# pragma warning(push)
-# pragma warning(disable:810) /* conversion may lose significant bits */
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
#if UINT_MAX < SIZE_T_MAX
@@ -179,7 +157,7 @@ unsigned int curlx_uztoui(size_t uznum) return (unsigned int)(uznum & (size_t) CURL_MASK_UINT);
#ifdef __INTEL_COMPILER
-# pragma warning(pop)
+# pragma warning(pop)
#endif
}
diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/warnless.h index 633494544d..549ed461a1 100644 --- a/libs/libcurl/src/warnless.h +++ b/libs/libcurl/src/warnless.h @@ -39,8 +39,6 @@ unsigned char curlx_ultouc(unsigned long ulnum); int curlx_uztosi(size_t uznum);
-curl_off_t curlx_uztoso(size_t uznum);
-
unsigned long curlx_uztoul(size_t uznum);
unsigned int curlx_uztoui(size_t uznum);
diff --git a/libs/libcurl/src/ws.c b/libs/libcurl/src/ws.c index 656c54e3f2..92e9eb5635 100644 --- a/libs/libcurl/src/ws.c +++ b/libs/libcurl/src/ws.c @@ -47,6 +47,10 @@ #define WSBIT_FIN 0x80
+#define WSBIT_RSV1 0x40
+#define WSBIT_RSV2 0x20
+#define WSBIT_RSV3 0x10
+#define WSBIT_RSV_MASK (WSBIT_RSV1 | WSBIT_RSV2 | WSBIT_RSV3)
#define WSBIT_OPCODE_CONT 0
#define WSBIT_OPCODE_TEXT (1)
#define WSBIT_OPCODE_BIN (2)
@@ -108,6 +112,13 @@ static unsigned char ws_frame_flags2op(int flags) return 0;
}
+/* No extensions are supported. If any of the RSV bits are set, we must fail */
+static bool ws_frame_rsv_supported(int flags)
+{
+ unsigned char reserved_bits = flags & WSBIT_RSV_MASK;
+ return reserved_bits == 0;
+}
+
static void ws_dec_info(struct ws_decoder *dec, struct Curl_easy *data,
const char *msg)
{
@@ -175,9 +186,17 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec, dec->head[0] = *inbuf;
Curl_bufq_skip(inraw, 1);
+ if(!ws_frame_rsv_supported(dec->head[0])) {
+ failf(data, "WS: unknown reserved bit in frame header: %x",
+ dec->head[0] & WSBIT_RSV_MASK);
+ ws_dec_reset(dec);
+ return CURLE_RECV_ERROR;
+ }
+
dec->frame_flags = ws_frame_op2flags(dec->head[0]);
if(!dec->frame_flags) {
- failf(data, "WS: unknown opcode: %x", dec->head[0]);
+ failf(data, "WS: unknown opcode: %x",
+ dec->head[0] & WSBIT_OPCODE_MASK);
ws_dec_reset(dec);
return CURLE_RECV_ERROR;
}
@@ -676,7 +695,7 @@ struct wsfield { const char *val;
};
-CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req)
+CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req)
{
unsigned int i;
CURLcode result = CURLE_OK;
@@ -729,16 +748,8 @@ CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req) free(randstr);
for(i = 0; !result && (i < sizeof(heads)/sizeof(heads[0])); i++) {
if(!Curl_checkheaders(data, STRCONST(heads[i].name))) {
-#ifdef USE_HYPER
- char field[128];
- msnprintf(field, sizeof(field), "%s %s", heads[i].name,
- heads[i].val);
- result = Curl_hyper_header(data, req, field);
-#else
- (void)data;
result = Curl_dyn_addf(req, "%s %s\r\n", heads[i].name,
heads[i].val);
-#endif
}
}
k->upgr101 = UPGR101_WS;
@@ -1017,8 +1028,28 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws, CURLcode result;
const unsigned char *out;
size_t outlen, n;
+#ifdef DEBUGBUILD
+ /* Simulate a blocking send after this chunk has been sent */
+ bool eagain_next = FALSE;
+ size_t chunk_egain = 0;
+ char *p = getenv("CURL_WS_CHUNK_EAGAIN");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l > 0 && l <= (1*1024*1024)) {
+ chunk_egain = (size_t)l;
+ }
+ }
+#endif
while(Curl_bufq_peek(&ws->sendbuf, &out, &outlen)) {
+#ifdef DEBUGBUILD
+ if(eagain_next)
+ return CURLE_AGAIN;
+ if(chunk_egain && (outlen > chunk_egain)) {
+ outlen = chunk_egain;
+ eagain_next = TRUE;
+ }
+#endif
if(blocking) {
result = ws_send_raw_blocking(data, ws, (char *)out, outlen);
n = result ? 0 : outlen;
@@ -1127,15 +1158,15 @@ static CURLcode ws_send_raw(struct Curl_easy *data, const void *buffer, return result;
}
-CURL_EXTERN CURLcode curl_ws_send(CURL *d, const void *buffer,
+CURL_EXTERN CURLcode curl_ws_send(CURL *d, const void *buffer_arg,
size_t buflen, size_t *sent,
curl_off_t fragsize,
unsigned int flags)
{
struct websocket *ws;
+ const unsigned char *buffer = buffer_arg;
ssize_t n;
- size_t space, payload_added;
- CURLcode result;
+ CURLcode result = CURLE_OK;
struct Curl_easy *data = d;
CURL_TRC_WS(data, "curl_ws_send(len=%zu, fragsize=%" FMT_OFF_T
@@ -1159,13 +1190,13 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *d, const void *buffer, }
ws = data->conn->proto.ws;
- /* try flushing any content still waiting to be sent. */
- result = ws_flush(data, ws, FALSE);
- if(result)
- goto out;
-
if(data->set.ws_raw_mode) {
/* In raw mode, we write directly to the connection */
+ /* try flushing any content still waiting to be sent. */
+ result = ws_flush(data, ws, FALSE);
+ if(result)
+ goto out;
+
if(fragsize || flags) {
failf(data, "ws_send, raw mode: fragsize and flags cannot be non-zero");
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1175,87 +1206,87 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *d, const void *buffer, }
/* Not RAW mode, buf we do the frame encoding */
- space = Curl_bufq_space(&ws->sendbuf);
- CURL_TRC_WS(data, "curl_ws_send(len=%zu), sendbuf=%zu space_left=%zu",
- buflen, Curl_bufq_len(&ws->sendbuf), space);
- if(space < 14) {
- result = CURLE_AGAIN;
- goto out;
- }
- if(flags & CURLWS_OFFSET) {
- if(fragsize) {
- /* a frame series 'fragsize' bytes big, this is the first */
- n = ws_enc_write_head(data, &ws->enc, flags, fragsize,
- &ws->sendbuf, &result);
- if(n < 0)
- goto out;
+ if(ws->enc.payload_remain || !Curl_bufq_is_empty(&ws->sendbuf)) {
+ /* a frame is ongoing with payload buffered or more payload
+ * that needs to be encoded into the buffer */
+ if(buflen < ws->sendbuf_payload) {
+ /* We have been called with LESS buffer data than before. This
+ * is not how it's supposed too work. */
+ failf(data, "curl_ws_send() called with smaller 'buflen' than "
+ "bytes already buffered in previous call, %zu vs %zu",
+ buflen, ws->sendbuf_payload);
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
}
- else {
- if((curl_off_t)buflen > ws->enc.payload_remain) {
- infof(data, "WS: unaligned frame size (sending %zu instead of %"
- FMT_OFF_T ")",
- buflen, ws->enc.payload_remain);
- }
+ if((curl_off_t)buflen >
+ (ws->enc.payload_remain + (curl_off_t)ws->sendbuf_payload)) {
+ /* too large buflen beyond payload length of frame */
+ infof(data, "WS: unaligned frame size (sending %zu instead of %"
+ FMT_OFF_T ")",
+ buflen, ws->enc.payload_remain + ws->sendbuf_payload);
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto out;
}
}
- else if(!ws->enc.payload_remain) {
- n = ws_enc_write_head(data, &ws->enc, flags, (curl_off_t)buflen,
+ else {
+ /* starting a new frame, we want a clean sendbuf */
+ curl_off_t payload_len = (flags & CURLWS_OFFSET) ?
+ fragsize : (curl_off_t)buflen;
+ result = ws_flush(data, ws, Curl_is_in_callback(data));
+ if(result)
+ goto out;
+
+ n = ws_enc_write_head(data, &ws->enc, flags, payload_len,
&ws->sendbuf, &result);
if(n < 0)
goto out;
}
- n = ws_enc_write_payload(&ws->enc, data,
- buffer, buflen, &ws->sendbuf, &result);
- if(n < 0)
- goto out;
- payload_added = (size_t)n;
+ /* While there is either sendbuf to flush OR more payload to encode... */
+ while(!Curl_bufq_is_empty(&ws->sendbuf) || (buflen > ws->sendbuf_payload)) {
+ /* Try to add more payload to sendbuf */
+ if(buflen > ws->sendbuf_payload) {
+ size_t prev_len = Curl_bufq_len(&ws->sendbuf);
+ n = ws_enc_write_payload(&ws->enc, data,
+ buffer + ws->sendbuf_payload,
+ buflen - ws->sendbuf_payload,
+ &ws->sendbuf, &result);
+ if(n < 0 && (result != CURLE_AGAIN))
+ goto out;
+ ws->sendbuf_payload += Curl_bufq_len(&ws->sendbuf) - prev_len;
+ }
- while(!result && (buflen || !Curl_bufq_is_empty(&ws->sendbuf))) {
/* flush, blocking when in callback */
result = ws_flush(data, ws, Curl_is_in_callback(data));
if(!result) {
- DEBUGASSERT(payload_added <= buflen);
- /* all buffered data sent. Try sending the rest if there is any. */
- *sent += payload_added;
- buffer = (const char *)buffer + payload_added;
- buflen -= payload_added;
- payload_added = 0;
- if(buflen) {
- n = ws_enc_write_payload(&ws->enc, data,
- buffer, buflen, &ws->sendbuf, &result);
- if(n < 0)
- goto out;
- payload_added = Curl_bufq_len(&ws->sendbuf);
- }
+ *sent += ws->sendbuf_payload;
+ buffer += ws->sendbuf_payload;
+ buflen -= ws->sendbuf_payload;
+ ws->sendbuf_payload = 0;
}
else if(result == CURLE_AGAIN) {
- /* partially sent. how much of the call data has been part of it? what
- * should we report to out caller so it can retry/send the rest? */
- if(payload_added < buflen) {
- /* We did not add everything the caller wanted. Return just
- * the partial write to our buffer. */
- *sent = payload_added;
+ if(ws->sendbuf_payload > Curl_bufq_len(&ws->sendbuf)) {
+ /* blocked, part of payload bytes remain, report length
+ * that we managed to send. */
+ size_t flushed = (ws->sendbuf_payload - Curl_bufq_len(&ws->sendbuf));
+ *sent += flushed;
+ ws->sendbuf_payload -= flushed;
result = CURLE_OK;
goto out;
}
- else if(!buflen) {
- /* We have no payload to report a partial write. EAGAIN would make
- * the caller repeat this and add the frame again.
- * Flush blocking seems the only way out of this. */
- *sent = (size_t)n;
- result = ws_flush(data, ws, TRUE);
+ else {
+ /* blocked before sending headers or 1st payload byte. We cannot report
+ * OK on 0-length send (caller counts only payload) and EAGAIN */
+ CURL_TRC_WS(data, "EAGAIN flushing sendbuf, payload_encoded: %zu/%zu",
+ ws->sendbuf_payload, buflen);
+ DEBUGASSERT(*sent == 0);
+ result = CURLE_AGAIN;
goto out;
}
- /* We added the complete data to our sendbuf. Report one byte less as
- * sent. This partial success should make the caller invoke us again
- * with the last byte. */
- *sent = payload_added - 1;
- result = Curl_bufq_unwrite(&ws->sendbuf, 1);
- if(!result)
- result = CURLE_AGAIN;
}
+ else
+ goto out; /* real error sending the data */
}
out:
@@ -1322,6 +1353,7 @@ const struct Curl_handler Curl_handler_ws = { Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ Curl_http_follow, /* follow */
PORT_HTTP, /* defport */
CURLPROTO_WS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -1348,6 +1380,7 @@ const struct Curl_handler Curl_handler_wss = { Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ Curl_http_follow, /* follow */
PORT_HTTPS, /* defport */
CURLPROTO_WSS, /* protocol */
CURLPROTO_HTTP, /* family */
diff --git a/libs/libcurl/src/ws.h b/libs/libcurl/src/ws.h index 1f14d4ec4d..7a8c17895a 100644 --- a/libs/libcurl/src/ws.h +++ b/libs/libcurl/src/ws.h @@ -27,12 +27,6 @@ #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
-#ifdef USE_HYPER
-#define REQTYPE void
-#else
-#define REQTYPE struct dynbuf
-#endif
-
/* a client-side WS frame decoder, parsing frame headers and
* payload, keeping track of current position and stats */
enum ws_dec_state {
@@ -59,7 +53,7 @@ struct ws_encoder { unsigned int xori; /* xor index */
unsigned char mask[4]; /* 32-bit mask for this connection */
unsigned char firstbyte; /* first byte of frame we encode */
- bool contfragment; /* set TRUE if the previous fragment sent was not final */
+ BIT(contfragment); /* set TRUE if the previous fragment sent was not final */
};
/* A websocket connection with en- and decoder that treat frames
@@ -71,9 +65,10 @@ struct websocket { struct bufq recvbuf; /* raw data from the server */
struct bufq sendbuf; /* raw data to be sent to the server */
struct curl_ws_frame frame; /* the current WS FRAME received */
+ size_t sendbuf_payload; /* number of payload bytes in sendbuf */
};
-CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
+CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req);
CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len);
extern const struct Curl_handler Curl_handler_ws;
|
