diff options
Diffstat (limited to 'libs/libcurl/src')
99 files changed, 4495 insertions, 1920 deletions
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt index a9c90b6650..e73efb90af 100644 --- a/libs/libcurl/src/CMakeLists.txt +++ b/libs/libcurl/src/CMakeLists.txt @@ -96,6 +96,12 @@ endif() set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") +if(CURL_HAS_LTO) + set_target_properties(${LIB_NAME} PROPERTIES + INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE + INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE) +endif() + if(WIN32) if(BUILD_SHARED_LIBS) # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index 9259841744..3fc95847d4 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -21,7 +21,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2020, 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 @@ -229,7 +229,8 @@ am__objects_1 = libcurl_la-file.lo libcurl_la-timeval.lo \ libcurl_la-curl_path.lo libcurl_la-curl_ctype.lo \ libcurl_la-curl_range.lo libcurl_la-psl.lo libcurl_la-doh.lo \ libcurl_la-urlapi.lo libcurl_la-curl_get_line.lo \ - libcurl_la-altsvc.lo libcurl_la-socketpair.lo + libcurl_la-altsvc.lo libcurl_la-socketpair.lo \ + libcurl_la-rename.lo am__dirstamp = $(am__leading_dot)dirstamp am__objects_2 = vauth/libcurl_la-vauth.lo \ vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \ @@ -240,15 +241,15 @@ am__objects_2 = vauth/libcurl_la-vauth.lo \ vauth/libcurl_la-spnego_sspi.lo am__objects_3 = vtls/libcurl_la-openssl.lo vtls/libcurl_la-gtls.lo \ vtls/libcurl_la-vtls.lo vtls/libcurl_la-nss.lo \ - vtls/libcurl_la-polarssl.lo \ - vtls/libcurl_la-polarssl_threadlock.lo \ + vtls/libcurl_la-mbedtls_threadlock.lo \ vtls/libcurl_la-wolfssl.lo vtls/libcurl_la-schannel.lo \ vtls/libcurl_la-schannel_verify.lo \ vtls/libcurl_la-sectransp.lo vtls/libcurl_la-gskit.lo \ vtls/libcurl_la-mbedtls.lo vtls/libcurl_la-mesalink.lo \ vtls/libcurl_la-bearssl.lo am__objects_4 = vquic/libcurl_la-ngtcp2.lo vquic/libcurl_la-quiche.lo -am__objects_5 = vssh/libcurl_la-libssh2.lo vssh/libcurl_la-libssh.lo +am__objects_5 = vssh/libcurl_la-libssh2.lo vssh/libcurl_la-libssh.lo \ + vssh/libcurl_la-wolfssh.lo am__objects_6 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) $(am__objects_5) am__objects_7 = @@ -317,7 +318,7 @@ am__objects_9 = libcurlu_la-file.lo libcurlu_la-timeval.lo \ libcurlu_la-curl_ctype.lo libcurlu_la-curl_range.lo \ libcurlu_la-psl.lo libcurlu_la-doh.lo libcurlu_la-urlapi.lo \ libcurlu_la-curl_get_line.lo libcurlu_la-altsvc.lo \ - libcurlu_la-socketpair.lo + libcurlu_la-socketpair.lo libcurlu_la-rename.lo am__objects_10 = vauth/libcurlu_la-vauth.lo \ vauth/libcurlu_la-cleartext.lo vauth/libcurlu_la-cram.lo \ vauth/libcurlu_la-digest.lo vauth/libcurlu_la-digest_sspi.lo \ @@ -328,8 +329,7 @@ am__objects_10 = vauth/libcurlu_la-vauth.lo \ vauth/libcurlu_la-spnego_sspi.lo am__objects_11 = vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-gtls.lo \ vtls/libcurlu_la-vtls.lo vtls/libcurlu_la-nss.lo \ - vtls/libcurlu_la-polarssl.lo \ - vtls/libcurlu_la-polarssl_threadlock.lo \ + vtls/libcurlu_la-mbedtls_threadlock.lo \ vtls/libcurlu_la-wolfssl.lo vtls/libcurlu_la-schannel.lo \ vtls/libcurlu_la-schannel_verify.lo \ vtls/libcurlu_la-sectransp.lo vtls/libcurlu_la-gskit.lo \ @@ -338,7 +338,7 @@ am__objects_11 = vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-gtls.lo \ am__objects_12 = vquic/libcurlu_la-ngtcp2.lo \ vquic/libcurlu_la-quiche.lo am__objects_13 = vssh/libcurlu_la-libssh2.lo \ - vssh/libcurlu_la-libssh.lo + vssh/libcurlu_la-libssh.lo vssh/libcurlu_la-wolfssh.lo am__objects_14 = $(am__objects_9) $(am__objects_10) $(am__objects_11) \ $(am__objects_12) $(am__objects_13) am_libcurlu_la_OBJECTS = $(am__objects_14) $(am__objects_8) @@ -438,6 +438,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-pop3.Plo \ ./$(DEPDIR)/libcurl_la-progress.Plo \ ./$(DEPDIR)/libcurl_la-psl.Plo ./$(DEPDIR)/libcurl_la-rand.Plo \ + ./$(DEPDIR)/libcurl_la-rename.Plo \ ./$(DEPDIR)/libcurl_la-rtsp.Plo \ ./$(DEPDIR)/libcurl_la-security.Plo \ ./$(DEPDIR)/libcurl_la-select.Plo \ @@ -548,6 +549,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-progress.Plo \ ./$(DEPDIR)/libcurlu_la-psl.Plo \ ./$(DEPDIR)/libcurlu_la-rand.Plo \ + ./$(DEPDIR)/libcurlu_la-rename.Plo \ ./$(DEPDIR)/libcurlu_la-rtsp.Plo \ ./$(DEPDIR)/libcurlu_la-security.Plo \ ./$(DEPDIR)/libcurlu_la-select.Plo \ @@ -610,17 +612,18 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ vquic/$(DEPDIR)/libcurlu_la-quiche.Plo \ vssh/$(DEPDIR)/libcurl_la-libssh.Plo \ vssh/$(DEPDIR)/libcurl_la-libssh2.Plo \ + vssh/$(DEPDIR)/libcurl_la-wolfssh.Plo \ vssh/$(DEPDIR)/libcurlu_la-libssh.Plo \ vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo \ + vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo \ vtls/$(DEPDIR)/libcurl_la-bearssl.Plo \ vtls/$(DEPDIR)/libcurl_la-gskit.Plo \ vtls/$(DEPDIR)/libcurl_la-gtls.Plo \ vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo \ + vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo \ vtls/$(DEPDIR)/libcurl_la-mesalink.Plo \ vtls/$(DEPDIR)/libcurl_la-nss.Plo \ vtls/$(DEPDIR)/libcurl_la-openssl.Plo \ - vtls/$(DEPDIR)/libcurl_la-polarssl.Plo \ - vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo \ vtls/$(DEPDIR)/libcurl_la-schannel.Plo \ vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo \ vtls/$(DEPDIR)/libcurl_la-sectransp.Plo \ @@ -630,11 +633,10 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ vtls/$(DEPDIR)/libcurlu_la-gskit.Plo \ vtls/$(DEPDIR)/libcurlu_la-gtls.Plo \ vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo \ + vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo \ vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo \ vtls/$(DEPDIR)/libcurlu_la-nss.Plo \ vtls/$(DEPDIR)/libcurlu_la-openssl.Plo \ - vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo \ - vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo \ vtls/$(DEPDIR)/libcurlu_la-schannel.Plo \ vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo \ vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo \ @@ -838,6 +840,7 @@ USE_SCHANNEL = @USE_SCHANNEL@ USE_SECTRANSP = @USE_SECTRANSP@ USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSH = @USE_WOLFSSH@ USE_WOLFSSL = @USE_WOLFSSL@ VERSION = @VERSION@ VERSIONNUM = @VERSIONNUM@ @@ -978,19 +981,18 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ - vtls/polarssl.c vtls/polarssl_threadlock.c \ - vtls/wolfssl.c vtls/schannel.c vtls/schannel_verify.c \ - vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c \ - vtls/bearssl.c + vtls/mbedtls_threadlock.c vtls/wolfssl.c vtls/schannel.c \ + vtls/schannel_verify.c vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c \ + vtls/mesalink.c vtls/bearssl.c -LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ - vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ - vtls/wolfssl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ - vtls/mbedtls.h vtls/mesalink.h vtls/bearssl.h +LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h vtls/nssg.h \ + vtls/mbedtls_threadlock.h vtls/wolfssl.h vtls/schannel.h \ + vtls/sectransp.h vtls/gskit.h vtls/mbedtls.h vtls/mesalink.h \ + vtls/bearssl.h LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h -LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c +LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c vssh/wolfssh.c LIB_VSSH_HFILES = vssh/ssh.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ @@ -1010,7 +1012,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ - doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c + doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c rename.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -1031,7 +1033,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ - curl_get_line.h altsvc.h quic.h socketpair.h + curl_get_line.h altsvc.h quic.h socketpair.h rename.h LIB_RCFILES = libcurl.rc CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \ @@ -1194,9 +1196,7 @@ vtls/libcurl_la-vtls.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurl_la-nss.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurl_la-polarssl.lo: vtls/$(am__dirstamp) \ - vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurl_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \ +vtls/libcurl_la-mbedtls_threadlock.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurl_la-wolfssl.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -1234,6 +1234,8 @@ vssh/libcurl_la-libssh2.lo: vssh/$(am__dirstamp) \ vssh/$(DEPDIR)/$(am__dirstamp) vssh/libcurl_la-libssh.lo: vssh/$(am__dirstamp) \ vssh/$(DEPDIR)/$(am__dirstamp) +vssh/libcurl_la-wolfssh.lo: vssh/$(am__dirstamp) \ + vssh/$(DEPDIR)/$(am__dirstamp) libcurl.la: $(libcurl_la_OBJECTS) $(libcurl_la_DEPENDENCIES) $(EXTRA_libcurl_la_DEPENDENCIES) $(AM_V_CCLD)$(libcurl_la_LINK) -rpath $(libdir) $(libcurl_la_OBJECTS) $(libcurl_la_LIBADD) $(LIBS) @@ -1269,9 +1271,7 @@ vtls/libcurlu_la-vtls.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurlu_la-nss.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurlu_la-polarssl.lo: vtls/$(am__dirstamp) \ - vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurlu_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \ +vtls/libcurlu_la-mbedtls_threadlock.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurlu_la-wolfssl.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -1297,6 +1297,8 @@ vssh/libcurlu_la-libssh2.lo: vssh/$(am__dirstamp) \ vssh/$(DEPDIR)/$(am__dirstamp) vssh/libcurlu_la-libssh.lo: vssh/$(am__dirstamp) \ vssh/$(DEPDIR)/$(am__dirstamp) +vssh/libcurlu_la-wolfssh.lo: vssh/$(am__dirstamp) \ + vssh/$(DEPDIR)/$(am__dirstamp) libcurlu.la: $(libcurlu_la_OBJECTS) $(libcurlu_la_DEPENDENCIES) $(EXTRA_libcurlu_la_DEPENDENCIES) $(AM_V_CCLD)$(libcurlu_la_LINK) $(am_libcurlu_la_rpath) $(libcurlu_la_OBJECTS) $(libcurlu_la_LIBADD) $(LIBS) @@ -1394,6 +1396,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-progress.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-psl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-rand.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-rename.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-rtsp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-security.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-select.Plo@am__quote@ # am--include-marker @@ -1505,6 +1508,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-progress.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-psl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-rand.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-rename.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-rtsp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-security.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-select.Plo@am__quote@ # am--include-marker @@ -1567,17 +1571,18 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@vquic/$(DEPDIR)/libcurlu_la-quiche.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurl_la-libssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurl_la-libssh2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurl_la-wolfssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurlu_la-libssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-bearssl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gskit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mesalink.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-nss.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-openssl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel.Plo@am__quote@ # am--include-marker @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 @@ -1587,11 +1592,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gskit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-nss.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-openssl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel.Plo@am__quote@ # am--include-marker @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 @@ -2405,6 +2409,13 @@ libcurl_la-socketpair.lo: socketpair.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-socketpair.lo `test -f 'socketpair.c' || echo '$(srcdir)/'`socketpair.c +libcurl_la-rename.lo: rename.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-rename.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rename.Tpo -c -o libcurl_la-rename.lo `test -f 'rename.c' || echo '$(srcdir)/'`rename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rename.Tpo $(DEPDIR)/libcurl_la-rename.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rename.c' object='libcurl_la-rename.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-rename.lo `test -f 'rename.c' || echo '$(srcdir)/'`rename.c + vauth/libcurl_la-vauth.lo: vauth/vauth.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 vauth/libcurl_la-vauth.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-vauth.Tpo -c -o vauth/libcurl_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-vauth.Tpo vauth/$(DEPDIR)/libcurl_la-vauth.Plo @@ -2517,19 +2528,12 @@ vtls/libcurl_la-nss.lo: vtls/nss.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-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c -vtls/libcurl_la-polarssl.lo: vtls/polarssl.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-polarssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-polarssl.Tpo -c -o vtls/libcurl_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-polarssl.Tpo vtls/$(DEPDIR)/libcurl_la-polarssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl.c' object='vtls/libcurl_la-polarssl.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-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c - -vtls/libcurl_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.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-polarssl_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Tpo -c -o vtls/libcurl_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Tpo vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl_threadlock.c' object='vtls/libcurl_la-polarssl_threadlock.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurl_la-mbedtls_threadlock.lo: vtls/mbedtls_threadlock.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-mbedtls_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Tpo -c -o vtls/libcurl_la-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Tpo vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mbedtls_threadlock.c' object='vtls/libcurl_la-mbedtls_threadlock.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-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c +@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-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.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 @@ -2615,6 +2619,13 @@ vssh/libcurl_la-libssh.lo: vssh/libssh.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 vssh/libcurl_la-libssh.lo `test -f 'vssh/libssh.c' || echo '$(srcdir)/'`vssh/libssh.c +vssh/libcurl_la-wolfssh.lo: vssh/wolfssh.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 vssh/libcurl_la-wolfssh.lo -MD -MP -MF vssh/$(DEPDIR)/libcurl_la-wolfssh.Tpo -c -o vssh/libcurl_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vssh/$(DEPDIR)/libcurl_la-wolfssh.Tpo vssh/$(DEPDIR)/libcurl_la-wolfssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vssh/wolfssh.c' object='vssh/libcurl_la-wolfssh.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 vssh/libcurl_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c + libcurlu_la-file.lo: file.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-file.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-file.Tpo -c -o libcurlu_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-file.Tpo $(DEPDIR)/libcurlu_la-file.Plo @@ -3392,6 +3403,13 @@ libcurlu_la-socketpair.lo: socketpair.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-socketpair.lo `test -f 'socketpair.c' || echo '$(srcdir)/'`socketpair.c +libcurlu_la-rename.lo: rename.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-rename.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rename.Tpo -c -o libcurlu_la-rename.lo `test -f 'rename.c' || echo '$(srcdir)/'`rename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rename.Tpo $(DEPDIR)/libcurlu_la-rename.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rename.c' object='libcurlu_la-rename.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-rename.lo `test -f 'rename.c' || echo '$(srcdir)/'`rename.c + vauth/libcurlu_la-vauth.lo: vauth/vauth.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 vauth/libcurlu_la-vauth.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-vauth.Tpo -c -o vauth/libcurlu_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-vauth.Tpo vauth/$(DEPDIR)/libcurlu_la-vauth.Plo @@ -3504,19 +3522,12 @@ vtls/libcurlu_la-nss.lo: vtls/nss.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-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c -vtls/libcurlu_la-polarssl.lo: vtls/polarssl.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-polarssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-polarssl.Tpo -c -o vtls/libcurlu_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-polarssl.Tpo vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl.c' object='vtls/libcurlu_la-polarssl.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurlu_la-mbedtls_threadlock.lo: vtls/mbedtls_threadlock.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-mbedtls_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Tpo -c -o vtls/libcurlu_la-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Tpo vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mbedtls_threadlock.c' object='vtls/libcurlu_la-mbedtls_threadlock.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-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c - -vtls/libcurlu_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.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-polarssl_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Tpo -c -o vtls/libcurlu_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Tpo vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl_threadlock.c' object='vtls/libcurlu_la-polarssl_threadlock.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-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c +@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-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.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 @@ -3602,6 +3613,13 @@ vssh/libcurlu_la-libssh.lo: vssh/libssh.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 vssh/libcurlu_la-libssh.lo `test -f 'vssh/libssh.c' || echo '$(srcdir)/'`vssh/libssh.c +vssh/libcurlu_la-wolfssh.lo: vssh/wolfssh.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 vssh/libcurlu_la-wolfssh.lo -MD -MP -MF vssh/$(DEPDIR)/libcurlu_la-wolfssh.Tpo -c -o vssh/libcurlu_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vssh/$(DEPDIR)/libcurlu_la-wolfssh.Tpo vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vssh/wolfssh.c' object='vssh/libcurlu_la-wolfssh.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 vssh/libcurlu_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c + mostlyclean-libtool: -rm -f *.lo @@ -3828,6 +3846,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-progress.Plo -rm -f ./$(DEPDIR)/libcurl_la-psl.Plo -rm -f ./$(DEPDIR)/libcurl_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rename.Plo -rm -f ./$(DEPDIR)/libcurl_la-rtsp.Plo -rm -f ./$(DEPDIR)/libcurl_la-security.Plo -rm -f ./$(DEPDIR)/libcurl_la-select.Plo @@ -3939,6 +3958,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-progress.Plo -rm -f ./$(DEPDIR)/libcurlu_la-psl.Plo -rm -f ./$(DEPDIR)/libcurlu_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rename.Plo -rm -f ./$(DEPDIR)/libcurlu_la-rtsp.Plo -rm -f ./$(DEPDIR)/libcurlu_la-security.Plo -rm -f ./$(DEPDIR)/libcurlu_la-select.Plo @@ -4001,17 +4021,18 @@ distclean: distclean-am -rm -f vquic/$(DEPDIR)/libcurlu_la-quiche.Plo -rm -f vssh/$(DEPDIR)/libcurl_la-libssh.Plo -rm -f vssh/$(DEPDIR)/libcurl_la-libssh2.Plo + -rm -f vssh/$(DEPDIR)/libcurl_la-wolfssh.Plo -rm -f vssh/$(DEPDIR)/libcurlu_la-libssh.Plo -rm -f vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo + -rm -f vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-bearssl.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-mesalink.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo @@ -4021,11 +4042,10 @@ distclean: distclean-am -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo @@ -4155,6 +4175,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-progress.Plo -rm -f ./$(DEPDIR)/libcurl_la-psl.Plo -rm -f ./$(DEPDIR)/libcurl_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rename.Plo -rm -f ./$(DEPDIR)/libcurl_la-rtsp.Plo -rm -f ./$(DEPDIR)/libcurl_la-security.Plo -rm -f ./$(DEPDIR)/libcurl_la-select.Plo @@ -4266,6 +4287,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-progress.Plo -rm -f ./$(DEPDIR)/libcurlu_la-psl.Plo -rm -f ./$(DEPDIR)/libcurlu_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rename.Plo -rm -f ./$(DEPDIR)/libcurlu_la-rtsp.Plo -rm -f ./$(DEPDIR)/libcurlu_la-security.Plo -rm -f ./$(DEPDIR)/libcurlu_la-select.Plo @@ -4328,17 +4350,18 @@ maintainer-clean: maintainer-clean-am -rm -f vquic/$(DEPDIR)/libcurlu_la-quiche.Plo -rm -f vssh/$(DEPDIR)/libcurl_la-libssh.Plo -rm -f vssh/$(DEPDIR)/libcurl_la-libssh2.Plo + -rm -f vssh/$(DEPDIR)/libcurl_la-wolfssh.Plo -rm -f vssh/$(DEPDIR)/libcurlu_la-libssh.Plo -rm -f vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo + -rm -f vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-bearssl.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-mesalink.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo @@ -4348,11 +4371,10 @@ maintainer-clean: maintainer-clean-am -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc index 6c90c26752..46ded90bb6 100644 --- a/libs/libcurl/src/Makefile.inc +++ b/libs/libcurl/src/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2020, 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 @@ -28,21 +28,20 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ - vtls/polarssl.c vtls/polarssl_threadlock.c \ - vtls/wolfssl.c vtls/schannel.c vtls/schannel_verify.c \ - vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c \ - vtls/bearssl.c + vtls/mbedtls_threadlock.c vtls/wolfssl.c vtls/schannel.c \ + vtls/schannel_verify.c vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c \ + vtls/mesalink.c vtls/bearssl.c -LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ - vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ - vtls/wolfssl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ - vtls/mbedtls.h vtls/mesalink.h vtls/bearssl.h +LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h vtls/nssg.h \ + vtls/mbedtls_threadlock.h vtls/wolfssl.h vtls/schannel.h \ + vtls/sectransp.h vtls/gskit.h vtls/mbedtls.h vtls/mesalink.h \ + vtls/bearssl.h LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h -LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c +LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c vssh/wolfssh.c LIB_VSSH_HFILES = vssh/ssh.h @@ -64,7 +63,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ - doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c + doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c rename.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -85,7 +84,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ - curl_get_line.h altsvc.h quic.h socketpair.h + curl_get_line.h altsvc.h quic.h socketpair.h rename.h LIB_RCFILES = libcurl.rc diff --git a/libs/libcurl/src/Makefile.m32 b/libs/libcurl/src/Makefile.m32 index b6ef0a5cbd..ac6b3de631 100644 --- a/libs/libcurl/src/Makefile.m32 +++ b/libs/libcurl/src/Makefile.m32 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1999 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1999 - 2020, 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 @@ -270,7 +270,7 @@ ifdef SSL OPENSSL_LIBS += -lgdi32 -lcrypt32 endif INCLUDES += -I"$(OPENSSL_INCLUDE)" - CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \ + CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_PKCS12_H \ -DOPENSSL_NO_KRB5 DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS) ifdef SRP diff --git a/libs/libcurl/src/Makefile.netware b/libs/libcurl/src/Makefile.netware index a40534684d..752d3d6fba 100644 --- a/libs/libcurl/src/Makefile.netware +++ b/libs/libcurl/src/Makefile.netware @@ -6,7 +6,7 @@ # \___|\___/|_| \_\_____| # # Copyright (C) 2004 - 2015, Guenter Knauf -# Copyright (C) 2001 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 2001 - 2020, 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 @@ -639,7 +639,6 @@ ifdef WITH_SSL @echo $(DL)#define HAVE_OPENSSL_PEM_H 1$(DL) >> $@ @echo $(DL)#define HAVE_OPENSSL_ERR_H 1$(DL) >> $@ @echo $(DL)#define HAVE_OPENSSL_CRYPTO_H 1$(DL) >> $@ - @echo $(DL)#define HAVE_OPENSSL_ENGINE_H 1$(DL) >> $@ @echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@ ifdef WITH_SRP @echo $(DL)#define USE_TLS_SRP 1$(DL) >> $@ diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c index bf869c37a5..c39d86eaff 100644 --- a/libs/libcurl/src/altsvc.c +++ b/libs/libcurl/src/altsvc.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2019 - 2020, 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 @@ -34,6 +34,8 @@ #include "parsedate.h" #include "sendf.h" #include "warnless.h" +#include "rand.h" +#include "rename.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -48,19 +50,20 @@ #define MAX_ALTSVC_ALPNLENSTR "10" #define MAX_ALTSVC_ALPNLEN 10 +#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS) +#define H3VERSION "h3-27" +#else +#define H3VERSION "h3" +#endif + static enum alpnid alpn2alpnid(char *name) { if(strcasecompare(name, "h1")) return ALPN_h1; if(strcasecompare(name, "h2")) return ALPN_h2; -#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS) - if(strcasecompare(name, "h3-24")) - return ALPN_h3; -#else - if(strcasecompare(name, "h3")) + if(strcasecompare(name, H3VERSION)) return ALPN_h3; -#endif return ALPN_none; /* unknown, probably rubbish input */ } @@ -73,11 +76,7 @@ const char *Curl_alpnid2str(enum alpnid id) case ALPN_h2: return "h2"; case ALPN_h3: -#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS) - return "h3-24"; -#else - return "h3"; -#endif + return H3VERSION; default: return ""; /* bad */ } @@ -188,7 +187,16 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) { CURLcode result = CURLE_OK; char *line = NULL; - FILE *fp = fopen(file, FOPEN_READTEXT); + FILE *fp; + + /* we need a private copy of the file name so that the altsvc cache file + name survives an easy handle reset */ + free(asi->filename); + asi->filename = strdup(file); + if(!asi->filename) + return CURLE_OUT_OF_MEMORY; + + fp = fopen(file, FOPEN_READTEXT); if(fp) { line = malloc(MAX_ALTSVC_LINE); if(!line) @@ -209,6 +217,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) return result; fail: + Curl_safefree(asi->filename); free(line); fclose(fp); return CURLE_OUT_OF_MEMORY; @@ -302,6 +311,7 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) n = e->next; altsvc_free(as); } + free(altsvc->filename); free(altsvc); } } @@ -309,34 +319,57 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) /* * Curl_altsvc_save() writes the altsvc cache to a file. */ -CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) +CURLcode Curl_altsvc_save(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *file) { struct curl_llist_element *e; struct curl_llist_element *n; CURLcode result = CURLE_OK; FILE *out; + char *tempstore; + unsigned char randsuffix[9]; if(!altsvc) /* no cache activated */ return CURLE_OK; + /* if not new name is given, use the one we stored from the load */ + if(!file && altsvc->filename) + file = altsvc->filename; + if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0]) /* marked as read-only, no file or zero length file name */ return CURLE_OK; - out = fopen(file, FOPEN_WRITETEXT); + + if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) + return CURLE_FAILED_INIT; + + tempstore = aprintf("%s.%s.tmp", file, randsuffix); + if(!tempstore) + return CURLE_OUT_OF_MEMORY; + + out = fopen(tempstore, FOPEN_WRITETEXT); if(!out) - return CURLE_WRITE_ERROR; - fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" - "# This file was generated by libcurl! Edit at your own risk.\n", - out); - for(e = altsvc->list.head; e; e = n) { - struct altsvc *as = e->ptr; - n = e->next; - result = altsvc_out(as, out); + result = CURLE_WRITE_ERROR; + else { + fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n", + out); + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + result = altsvc_out(as, out); + if(result) + break; + } + fclose(out); + if(!result && Curl_rename(tempstore, file)) + result = CURLE_WRITE_ERROR; + if(result) - break; + unlink(tempstore); } - fclose(out); + free(tempstore); return result; } @@ -351,12 +384,12 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen) while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '=')) p++; len = p - protop; + *ptr = p; if(!len || (len >= buflen)) return CURLE_BAD_FUNCTION_ARGUMENT; memcpy(alpnbuf, protop, len); alpnbuf[len] = 0; - *ptr = p; return CURLE_OK; } @@ -402,6 +435,10 @@ static time_t debugtime(void *unused) * * 'value' points to the header *value*. That's contents to the right of the * header name. + * + * Currently this function rejects invalid data without returning an error. + * Invalid host name, port number will result in the specific alternative + * being rejected. Unknown protocols are skipped. */ CURLcode Curl_altsvc_parse(struct Curl_easy *data, struct altsvcinfo *asi, const char *value, @@ -415,12 +452,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, char alpnbuf[MAX_ALTSVC_ALPNLEN] = ""; struct altsvc *as; unsigned short dstport = srcport; /* the same by default */ - const char *semip; - time_t maxage = 24 * 3600; /* default is 24 hours */ - bool persist = FALSE; CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); - if(result) - return result; + if(result) { + infof(data, "Excessive alt-svc header, ignoring...\n"); + return CURLE_OK; + } DEBUGASSERT(asi); @@ -432,57 +468,20 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, return CURLE_OK; } - /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives - but are set after the list on the line. Scan for the semicolons and get - those fields first! */ - semip = p; - do { - semip = strchr(semip, ';'); - if(semip) { - char option[32]; - unsigned long num; - char *end_ptr; - bool quoted = FALSE; - semip++; /* pass the semicolon */ - result = getalnum(&semip, option, sizeof(option)); - if(result) - break; - while(*semip && ISBLANK(*semip)) - semip++; - if(*semip != '=') - continue; - semip++; - while(*semip && ISBLANK(*semip)) - semip++; - if(*semip == '\"') { - /* quoted value */ - semip++; - quoted = TRUE; - } - num = strtoul(semip, &end_ptr, 10); - if((end_ptr != semip) && num && (num < ULONG_MAX)) { - if(strcasecompare("ma", option)) - maxage = num; - else if(strcasecompare("persist", option) && (num == 1)) - persist = TRUE; - if(quoted && (*end_ptr == '\"')) - end_ptr++; - } - semip = end_ptr; - } - } while(semip); - do { if(*p == '=') { /* [protocol]="[host][:port]" */ dstalpnid = alpn2alpnid(alpnbuf); - if(!dstalpnid) { - infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf); - return CURLE_OK; - } p++; if(*p == '\"') { const char *dsthost; + const char *value_ptr; + char option[32]; + unsigned long num; + char *end_ptr; + bool quoted = FALSE; + time_t maxage = 24 * 3600; /* default is 24 hours */ + bool persist = FALSE; p++; if(*p != ':') { /* host name starts here */ @@ -490,11 +489,15 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) p++; len = p - hostp; - if(!len || (len >= MAX_ALTSVC_HOSTLEN)) - return CURLE_BAD_FUNCTION_ARGUMENT; - memcpy(namebuf, hostp, len); - namebuf[len] = 0; - dsthost = namebuf; + if(!len || (len >= MAX_ALTSVC_HOSTLEN)) { + infof(data, "Excessive alt-svc host name, ignoring...\n"); + dstalpnid = ALPN_none; + } + else { + memcpy(namebuf, hostp, len); + namebuf[len] = 0; + dsthost = namebuf; + } } else { /* no destination name, use source host */ @@ -502,31 +505,86 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, } if(*p == ':') { /* a port number */ - char *end_ptr; unsigned long port = strtoul(++p, &end_ptr, 10); if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { infof(data, "Unknown alt-svc port number, ignoring...\n"); - return CURLE_OK; + dstalpnid = ALPN_none; } p = end_ptr; dstport = curlx_ultous(port); } if(*p++ != '\"') - return CURLE_BAD_FUNCTION_ARGUMENT; - as = altsvc_createid(srchost, dsthost, - 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); - as->persist = persist; - Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); - asi->num++; /* one more entry */ - infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, - Curl_alpnid2str(dstalpnid)); + break; + /* Handle the optional 'ma' and 'persist' flags. Unknown flags + are skipped. */ + for(;;) { + while(*p && ISBLANK(*p) && *p != ';' && *p != ',') + p++; + if(!*p || *p == ',') + break; + p++; /* pass the semicolon */ + if(!*p) + break; + result = getalnum(&p, option, sizeof(option)); + if(result) { + /* skip option if name is too long */ + option[0] = '\0'; + } + while(*p && ISBLANK(*p)) + p++; + if(*p != '=') + return CURLE_OK; + p++; + while(*p && ISBLANK(*p)) + p++; + if(!*p) + return CURLE_OK; + if(*p == '\"') { + /* quoted value */ + p++; + quoted = TRUE; + } + value_ptr = p; + if(quoted) { + while(*p && *p != '\"') + p++; + if(!*p++) + return CURLE_OK; + } + else { + while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',') + p++; + } + num = strtoul(value_ptr, &end_ptr, 10); + if((end_ptr != value_ptr) && (num < ULONG_MAX)) { + if(strcasecompare("ma", option)) + maxage = num; + else if(strcasecompare("persist", option) && (num == 1)) + persist = TRUE; + } + } + if(dstalpnid) { + as = altsvc_createid(srchost, dsthost, + 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); + as->persist = persist; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, + Curl_alpnid2str(dstalpnid)); + } + } + else { + infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n", + alpnbuf); } } + else + break; /* after the double quote there can be a comma if there's another string or a semicolon if no more */ if(*p == ',') { @@ -534,11 +592,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, p++; result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); if(result) - /* failed to parse, but since we already did at least one host we - return OK */ - return CURLE_OK; + break; } } + else + break; } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); return CURLE_OK; diff --git a/libs/libcurl/src/altsvc.h b/libs/libcurl/src/altsvc.h index 99d0499af7..248e71eef8 100644 --- a/libs/libcurl/src/altsvc.h +++ b/libs/libcurl/src/altsvc.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2019 - 2020, 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 @@ -59,7 +59,8 @@ struct altsvcinfo { const char *Curl_alpnid2str(enum alpnid id); struct altsvcinfo *Curl_altsvc_init(void); CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); -CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_save(struct Curl_easy *data, + struct altsvcinfo *asi, const char *file); CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); CURLcode Curl_altsvc_parse(struct Curl_easy *data, @@ -70,9 +71,9 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi, enum alpnid srcalpnid, const char *srchost, int srcport, struct altsvc **dstentry, - int versions); /* one or more CURLALTSVC_H* bits */ + const int versions); /* CURLALTSVC_H* bits */ #else /* disabled */ -#define Curl_altsvc_save(a,b) +#define Curl_altsvc_save(a,b,c) #endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ #endif /* HEADER_CURL_ALTSVC_H */ diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index 835cfa48fa..b76e66548e 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -626,26 +626,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, { char *bufp; struct Curl_easy *data = conn->data; - struct in_addr in; int family = PF_INET; -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ - struct in6_addr in6; -#endif /* CURLRES_IPV6 */ *waitp = 0; /* default to synchronous response */ - /* First check if this is an IPv4 address string */ - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - } - #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ - /* Otherwise, check if this is an IPv6 address string */ - if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) - /* This must be an IPv6 address literal. */ - return Curl_ip2addr(AF_INET6, &in6, hostname, port); - switch(conn->ip_version) { default: #if ARES_VERSION >= 0x010601 @@ -684,7 +669,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, res->last_status = ARES_ENOTFOUND; #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ if(family == PF_UNSPEC) { - if(Curl_ipv6works()) { + if(Curl_ipv6works(conn)) { res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index b08497aaa0..68dcbb3ecd 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -71,7 +71,6 @@ #include "strerror.h" #include "url.h" #include "multiif.h" -#include "inet_pton.h" #include "inet_ntop.h" #include "curl_threads.h" #include "connect.h" @@ -692,26 +691,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, int port, int *waitp) { - struct in_addr in; struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.resolver; *waitp = 0; /* default to synchronous response */ -#ifdef ENABLE_IPV6 - { - struct in6_addr in6; - /* check if this is an IPv6 address string */ - if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) - /* This is an IPv6 address literal */ - return Curl_ip2addr(AF_INET6, &in6, hostname, port); - } -#endif /* ENABLE_IPV6 */ - - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - reslv->start = Curl_now(); /* fire up a new resolver thread! */ @@ -736,32 +720,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, int *waitp) { struct addrinfo hints; - char sbuf[12]; int pf = PF_INET; struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.resolver; *waitp = 0; /* default to synchronous response */ -#ifndef USE_RESOLVE_ON_IPS - { - struct in_addr in; - /* First check if this is an IPv4 address string */ - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - } -#ifdef ENABLE_IPV6 - { - struct in6_addr in6; - /* check if this is an IPv6 address string */ - if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) - /* This is an IPv6 address literal */ - return Curl_ip2addr(AF_INET6, &in6, hostname, port); - } -#endif /* ENABLE_IPV6 */ -#endif /* !USE_RESOLVE_ON_IPS */ - #ifdef CURLRES_IPV6 /* * Check if a limited name resolve has been requested. @@ -778,7 +742,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works()) + if((pf != PF_INET) && !Curl_ipv6works(conn)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; #endif /* CURLRES_IPV6 */ @@ -788,8 +752,6 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, hints.ai_socktype = (conn->transport == TRNSPRT_TCP)? SOCK_STREAM : SOCK_DGRAM; - msnprintf(sbuf, sizeof(sbuf), "%d", port); - reslv->start = Curl_now(); /* fire up a new resolver thread! */ if(init_resolve_thread(conn, hostname, port, &hints)) { diff --git a/libs/libcurl/src/config-dos.h b/libs/libcurl/src/config-dos.h index 25f751eb56..aa83c4be55 100644 --- a/libs/libcurl/src/config-dos.h +++ b/libs/libcurl/src/config-dos.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -138,7 +138,6 @@ /* USE_OPENSSL on cmd-line */ #ifdef USE_OPENSSL #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 - #define HAVE_OPENSSL_ENGINE_H 1 #define OPENSSL_NO_KRB5 1 #endif diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h index 4063d4bbd6..41440a14ec 100644 --- a/libs/libcurl/src/config-plan9.h +++ b/libs/libcurl/src/config-plan9.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -138,7 +138,6 @@ #define USE_OPENSSL 1 #define HAVE_OPENSSL_CRYPTO_H 1 -#define HAVE_OPENSSL_ENGINE_H 1 #define HAVE_OPENSSL_ERR_H 1 #define HAVE_OPENSSL_PEM_H 1 #define HAVE_OPENSSL_PKCS12_H 1 diff --git a/libs/libcurl/src/config-symbian.h b/libs/libcurl/src/config-symbian.h index c01e1bfab8..82a27bfefa 100644 --- a/libs/libcurl/src/config-symbian.h +++ b/libs/libcurl/src/config-symbian.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -358,9 +358,6 @@ /* Define to 1 if you have the <openssl/crypto.h> header file. */ /*#define HAVE_OPENSSL_CRYPTO_H 1*/ -/* Define to 1 if you have the <openssl/engine.h> header file. */ -/*#define HAVE_OPENSSL_ENGINE_H 1*/ - /* Define to 1 if you have the <openssl/err.h> header file. */ /*#define HAVE_OPENSSL_ERR_H 1*/ diff --git a/libs/libcurl/src/config-tpf.h b/libs/libcurl/src/config-tpf.h index 85b634f9d4..a79afae6d3 100644 --- a/libs/libcurl/src/config-tpf.h +++ b/libs/libcurl/src/config-tpf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -316,10 +316,6 @@ /* #undef HAVE_OPENSSL_CRYPTO_H */ #define HAVE_OPENSSL_CRYPTO_H 1 -/* Define to 1 if you have the <openssl/engine.h> header file. */ -/* #undef HAVE_OPENSSL_ENGINE_H */ -#define HAVE_OPENSSL_ENGINE_H 1 - /* Define to 1 if you have the <openssl/err.h> header file. */ /* #undef HAVE_OPENSSL_ERR_H */ #define HAVE_OPENSSL_ERR_H 1 diff --git a/libs/libcurl/src/config-vxworks.h b/libs/libcurl/src/config-vxworks.h index 004fd4e800..2769cdfd94 100644 --- a/libs/libcurl/src/config-vxworks.h +++ b/libs/libcurl/src/config-vxworks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -418,9 +418,6 @@ /* Define to 1 if you have the <openssl/crypto.h> header file. */ #define HAVE_OPENSSL_CRYPTO_H 1 -/* Define to 1 if you have the <openssl/engine.h> header file. */ -#define HAVE_OPENSSL_ENGINE_H 1 - /* Define to 1 if you have the <openssl/err.h> header file. */ #define HAVE_OPENSSL_ERR_H 1 diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 9abdb9fe6c..8b488c1c1c 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -246,10 +246,6 @@ /* Define if you have the socket function. */ #define HAVE_SOCKET 1 -/* Define if libSSH2 is in use */ -#define USE_LIBSSH2 1 -#define HAVE_LIBSSH2_H 1 - /* Define if you have the strcasecmp function. */ /* #define HAVE_STRCASECMP 1 */ @@ -717,11 +713,10 @@ Vista # define CURL_DISABLE_LDAP 1 #endif -/* if SSL is enabled */ -#define USE_OPENSSL 1 - /* Define to use the Windows crypto library. */ +#if !defined(CURL_WINDOWS_APP) #define USE_WIN32_CRYPTO +#endif /* Define to use Unix sockets. */ #if defined(_MSC_VER) && (_MSC_VER >= 1500) diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c index 28044644bf..cbd3bb1bb3 100644 --- a/libs/libcurl/src/conncache.c +++ b/libs/libcurl/src/conncache.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se> - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, 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 @@ -179,18 +179,6 @@ size_t Curl_conncache_size(struct Curl_easy *data) return num; } -/* Returns number of connections currently held in the connections's bundle - Locks/unlocks the cache itself! -*/ -size_t Curl_conncache_bundle_size(struct connectdata *conn) -{ - size_t num; - CONN_LOCK(conn->data); - num = conn->bundle->num_connections; - CONN_UNLOCK(conn->data); - return num; -} - /* Look up the bundle with all the connections to the same host this connectdata struct is setup to use. diff --git a/libs/libcurl/src/conncache.h b/libs/libcurl/src/conncache.h index 5fe80b4c8d..e3e4c9c282 100644 --- a/libs/libcurl/src/conncache.h +++ b/libs/libcurl/src/conncache.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se> * * This software is licensed as described in the file COPYING, which @@ -80,7 +80,6 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, void Curl_conncache_unlock(struct Curl_easy *data); /* returns number of connections currently held in the connection cache */ size_t Curl_conncache_size(struct Curl_easy *data); -size_t Curl_conncache_bundle_size(struct connectdata *conn); bool Curl_conncache_return_conn(struct Curl_easy *data, struct connectdata *conn); diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index 611d6d2f02..0a7475cb6a 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -745,13 +745,15 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) Curl_persistconninfo(conn); } -/* after a TCP connection to the proxy has been verified, this function does - the next magic step. +/* After a TCP connection to the proxy has been verified, this function does + the next magic steps. If 'done' isn't set TRUE, it is not done yet and + must be called again. Note: this function's sub-functions call failf() */ -static CURLcode connected_proxy(struct connectdata *conn, int sockindex) +static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex, + bool *done) { CURLcode result = CURLE_OK; @@ -760,44 +762,63 @@ static CURLcode connected_proxy(struct connectdata *conn, int sockindex) /* for the secondary socket (FTP), use the "connect to host" * but ignore the "connect to port" (use the secondary port) */ - const char * const host = conn->bits.httpproxy ? - conn->http_proxy.host.name : - conn->bits.conn_to_host ? - conn->conn_to_host.name : - sockindex == SECONDARYSOCKET ? - conn->secondaryhostname : conn->host.name; - const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port : - sockindex == SECONDARYSOCKET ? conn->secondary_port : - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port; - conn->bits.socksproxy_connecting = TRUE; + const char * const host = + conn->bits.httpproxy ? + conn->http_proxy.host.name : + conn->bits.conn_to_host ? + conn->conn_to_host.name : + sockindex == SECONDARYSOCKET ? + conn->secondaryhostname : conn->host.name; + const int port = + conn->bits.httpproxy ? (int)conn->http_proxy.port : + sockindex == SECONDARYSOCKET ? conn->secondary_port : + conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; switch(conn->socks_proxy.proxytype) { case CURLPROXY_SOCKS5: case CURLPROXY_SOCKS5_HOSTNAME: result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd, - host, port, sockindex, conn); + host, port, sockindex, conn, done); break; case CURLPROXY_SOCKS4: case CURLPROXY_SOCKS4A: result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, - conn); + conn, done); break; default: failf(conn->data, "unknown proxytype option given"); result = CURLE_COULDNT_CONNECT; } /* switch proxytype */ - conn->bits.socksproxy_connecting = FALSE; #else (void)sockindex; #endif /* CURL_DISABLE_PROXY */ } + else + *done = TRUE; /* no SOCKS proxy, so consider us connected */ return result; } /* + * post_SOCKS() is called after a successful connect to the peer, which + * *could* be a SOCKS proxy + */ +static void post_SOCKS(struct connectdata *conn, + int sockindex, + bool *connected) +{ + conn->bits.tcpconnect[sockindex] = TRUE; + + *connected = TRUE; + if(sockindex == FIRSTSOCKET) + Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */ + Curl_updateconninfo(conn, conn->sock[sockindex]); + Curl_verboseconnect(conn); +} + +/* * Curl_is_connected() checks if the socket has connected. */ @@ -834,6 +855,14 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } + if(SOCKS_STATE(conn->cnnct.state)) { + /* still doing SOCKS */ + result = connect_SOCKS(conn, sockindex, connected); + if(!result && *connected) + post_SOCKS(conn, sockindex, connected); + return result; + } + for(i = 0; i<2; i++) { const int other = i ^ 1; if(conn->tempsock[i] == CURL_SOCKET_BAD) @@ -900,18 +929,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, conn->tempsock[other] = CURL_SOCKET_BAD; } - /* see if we need to do any proxy magic first once we connected */ - result = connected_proxy(conn, sockindex); - if(result) + /* see if we need to kick off any SOCKS proxy magic once we + connected */ + result = connect_SOCKS(conn, sockindex, connected); + if(result || !*connected) return result; - conn->bits.tcpconnect[sockindex] = TRUE; - - *connected = TRUE; - if(sockindex == FIRSTSOCKET) - Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ - Curl_updateconninfo(conn, conn->sock[sockindex]); - Curl_verboseconnect(conn); + post_SOCKS(conn, sockindex, connected); return CURLE_OK; } @@ -1007,8 +1031,6 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); - else - infof(data, "TCP_NODELAY set\n"); #else (void)conn; (void)sockfd; @@ -1216,8 +1238,6 @@ static CURLcode singleipconnect(struct connectdata *conn, if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, (void *)&optval, sizeof(optval)) < 0) infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd); - else - infof(data, "TCP_FASTOPEN_CONNECT set\n"); rc = connect(sockfd, &addr.sa_addr, addr.addrlen); #elif defined(MSG_FASTOPEN) /* old Linux */ @@ -1428,12 +1448,11 @@ int Curl_closesocket(struct connectdata *conn, curl_socket_t sock) { if(conn && conn->fclosesocket) { - if((sock == conn->sock[SECONDARYSOCKET]) && - conn->sock_accepted[SECONDARYSOCKET]) + if((sock == conn->sock[SECONDARYSOCKET]) && conn->sock_accepted) /* if this socket matches the second socket, and that was created with accept, then we MUST NOT call the callback but clear the accepted status */ - conn->sock_accepted[SECONDARYSOCKET] = FALSE; + conn->sock_accepted = FALSE; else { int rc; Curl_multi_closed(conn->data, sock); diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index 0091132aa3..69bc04260a 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -97,6 +97,8 @@ Example set of cookies: #include "curl_memrchr.h" #include "inet_pton.h" #include "parsedate.h" +#include "rand.h" +#include "rename.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -537,9 +539,9 @@ Curl_cookie_add(struct Curl_easy *data, * only test for names where that can possibly be true. */ if(nlen > 3 && name[0] == '_' && name[1] == '_') { - if(strncasecompare("__Secure-", name, 9)) + if(!strncmp("__Secure-", name, 9)) co->prefix |= COOKIE_PREFIX__SECURE; - else if(strncasecompare("__Host-", name, 7)) + else if(!strncmp("__Host-", name, 7)) co->prefix |= COOKIE_PREFIX__HOST; } @@ -1046,7 +1048,7 @@ Curl_cookie_add(struct Curl_easy *data, *clist = *co; /* then store all the new data */ - free(co); /* free the newly alloced memory */ + free(co); /* free the newly allocated memory */ co = clist; /* point to the previous struct instead */ /* We have replaced a cookie, now skip the rest of the list but @@ -1501,11 +1503,14 @@ static char *get_netscape_format(const struct Cookie *co) * * The function returns non-zero on write failure. */ -static int cookie_output(struct CookieInfo *c, const char *dumphere) +static int cookie_output(struct Curl_easy *data, + struct CookieInfo *c, const char *filename) { struct Cookie *co; - FILE *out; + FILE *out = NULL; bool use_stdout = FALSE; + char *tempstore = NULL; + bool error = false; if(!c) /* no cookie engine alive */ @@ -1514,16 +1519,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) /* at first, remove expired cookies */ remove_expired(c); - if(!strcmp("-", dumphere)) { + if(!strcmp("-", filename)) { /* use stdout */ out = stdout; use_stdout = TRUE; } else { - out = fopen(dumphere, FOPEN_WRITETEXT); - if(!out) { - return 1; /* failure */ - } + unsigned char randsuffix[9]; + + if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) + return 2; + + tempstore = aprintf("%s.%s.tmp", filename, randsuffix); + if(!tempstore) + return 1; + + out = fopen(tempstore, FOPEN_WRITETEXT); + if(!out) + goto error; } fputs("# Netscape HTTP Cookie File\n" @@ -1538,9 +1551,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) array = calloc(1, sizeof(struct Cookie *) * c->numcookies); if(!array) { - if(!use_stdout) - fclose(out); - return 1; + goto error; } /* only sort the cookies with a domain property */ @@ -1559,9 +1570,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) if(format_ptr == NULL) { fprintf(out, "#\n# Fatal libcurl error\n"); free(array); - if(!use_stdout) - fclose(out); - return 1; + goto error; } fprintf(out, "%s\n", format_ptr); free(format_ptr); @@ -1569,10 +1578,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) free(array); } - if(!use_stdout) + + if(!use_stdout) { fclose(out); + out = NULL; + if(Curl_rename(tempstore, filename)) { + unlink(tempstore); + goto error; + } + } - return 0; + goto cleanup; +error: + error = true; +cleanup: + if(out && !use_stdout) + fclose(out); + free(tempstore); + return error ? 1 : 0; } static struct curl_slist *cookie_list(struct Curl_easy *data) @@ -1631,7 +1654,7 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); /* if we have a destination file for all the cookies to get dumped to */ - if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) + if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR])) infof(data, "WARNING: failed to save cookies in %s\n", data->set.str[STRING_COOKIEJAR]); } diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index 2c3b6562d4..98cdf51454 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -73,6 +73,9 @@ #define CURL_EXTERN_SYMBOL #endif +/* Allow SMB to work on Windows */ +#cmakedefine USE_WIN32_CRYPTO + /* Use Windows LDAP implementation */ #cmakedefine USE_WIN32_LDAP 1 @@ -452,9 +455,6 @@ /* Define to 1 if you have the <openssl/crypto.h> header file. */ #cmakedefine HAVE_OPENSSL_CRYPTO_H 1 -/* Define to 1 if you have the <openssl/engine.h> header file. */ -#cmakedefine HAVE_OPENSSL_ENGINE_H 1 - /* Define to 1 if you have the <openssl/err.h> header file. */ #cmakedefine HAVE_OPENSSL_ERR_H 1 @@ -936,9 +936,6 @@ ${SIZEOF_TIME_T_CODE} /* if GnuTLS is enabled */ #cmakedefine USE_GNUTLS 1 -/* if PolarSSL is enabled */ -#cmakedefine USE_POLARSSL 1 - /* if Secure Transport is enabled */ #cmakedefine USE_SECTRANSP 1 diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index bb7f4e3402..8f29f51c11 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -435,6 +435,9 @@ /* Define to 1 if you have the `ssl' library (-lssl). */ #undef HAVE_LIBSSL +/* Define to 1 if you have the `wolfssh' library (-lwolfssh). */ +#undef HAVE_LIBWOLFSSH + /* if zlib is available */ #undef HAVE_LIBZ @@ -787,6 +790,9 @@ /* Define to 1 if you have the winsock.h header file. */ #undef HAVE_WINSOCK_H +/* Define to 1 if you have the <wolfssh/ssh.h> header file. */ +#undef HAVE_WOLFSSH_SSH_H + /* Define to 1 if you have the `wolfSSLv3_client_method' function. */ #undef HAVE_WOLFSSLV3_CLIENT_METHOD @@ -1050,6 +1056,9 @@ /* to enable SSPI support */ #undef USE_WINDOWS_SSPI +/* if wolfSSH is in use */ +#undef USE_WOLFSSH + /* if wolfSSL is enabled */ #undef USE_WOLFSSL diff --git a/libs/libcurl/src/curl_hmac.h b/libs/libcurl/src/curl_hmac.h index 756dc9e4cd..3ff799bbda 100644 --- a/libs/libcurl/src/curl_hmac.h +++ b/libs/libcurl/src/curl_hmac.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -24,6 +24,8 @@ #ifndef CURL_DISABLE_CRYPTO_AUTH +#define HMAC_MD5_LENGTH 16 + typedef void (* HMAC_hinit_func)(void *context); typedef void (* HMAC_hupdate_func)(void *context, const unsigned char *data, @@ -62,6 +64,11 @@ int Curl_HMAC_update(HMAC_context *context, unsigned int len); int Curl_HMAC_final(HMAC_context *context, unsigned char *result); +CURLcode Curl_hmacit(const HMAC_params *hashparams, + const unsigned char *key, const size_t keylen, + const unsigned char *data, const size_t datalen, + unsigned char *output); + #endif #endif /* HEADER_CURL_HMAC_H */ diff --git a/libs/libcurl/src/curl_md4.h b/libs/libcurl/src/curl_md4.h index 82df708cee..c7bb209815 100644 --- a/libs/libcurl/src/curl_md4.h +++ b/libs/libcurl/src/curl_md4.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -28,7 +28,8 @@ #define MD4_DIGEST_LENGTH 16 -void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); +void Curl_md4it(unsigned char *output, const unsigned char *input, + const size_t len); #endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */ diff --git a/libs/libcurl/src/curl_md5.h b/libs/libcurl/src/curl_md5.h index aaf25f61bb..dd464416a2 100644 --- a/libs/libcurl/src/curl_md5.h +++ b/libs/libcurl/src/curl_md5.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -49,8 +49,8 @@ typedef struct { extern const MD5_params Curl_DIGEST_MD5[1]; extern const HMAC_params Curl_HMAC_MD5[1]; -void Curl_md5it(unsigned char *output, - const unsigned char *input); +void Curl_md5it(unsigned char *output, const unsigned char *input, + const size_t len); MD5_context * Curl_MD5_init(const MD5_params *md5params); CURLcode Curl_MD5_update(MD5_context *context, diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c index 19f9b61d87..f9b823b4f6 100644 --- a/libs/libcurl/src/curl_ntlm_core.c +++ b/libs/libcurl/src/curl_ntlm_core.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -120,7 +120,6 @@ #include "curl_memory.h" #include "memdebug.h" -#define NTLM_HMAC_MD5_LEN (16) #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) @@ -567,25 +566,6 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) -/* This returns the HMAC MD5 digest */ -static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen, - const unsigned char *data, unsigned int datalen, - unsigned char *output) -{ - HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); - - if(!ctxt) - return CURLE_OUT_OF_MEMORY; - - /* Update the digest with the given challenge */ - Curl_HMAC_update(ctxt, data, datalen); - - /* Finalise the digest */ - Curl_HMAC_final(ctxt, output); - - return CURLE_OK; -} - /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ @@ -615,8 +595,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); - result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), - ntlmv2hash); + result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len, + ntlmv2hash); free(identity); return result; @@ -662,7 +642,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned int len = 0; unsigned char *ptr = NULL; - unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; + unsigned char hmac_output[HMAC_MD5_LENGTH]; curl_off_t tw; CURLcode result = CURLE_OK; @@ -681,7 +661,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; /* Calculate the response len */ - len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; + len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN; /* Allocate the response */ ptr = calloc(1, len); @@ -689,7 +669,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, return CURLE_OUT_OF_MEMORY; /* Create the BLOB structure */ - msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, + msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN, "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ "%c%c%c%c", /* Reserved = 0 */ NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], @@ -702,7 +682,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ memcpy(ptr + 8, &ntlm->nonce[0], 8); - result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8, NTLMv2_BLOB_LEN + 8, hmac_output); if(result) { free(ptr); @@ -710,7 +690,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, } /* Concatenate the HMAC MD5 output with the BLOB */ - memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); + memcpy(ptr, hmac_output, HMAC_MD5_LENGTH); /* Return the response */ *ntresp = ptr; @@ -745,7 +725,8 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, memcpy(&data[0], challenge_server, 8); memcpy(&data[8], challenge_client, 8); - result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16, + hmac_output); if(result) return result; diff --git a/libs/libcurl/src/curl_ntlm_core.h b/libs/libcurl/src/curl_ntlm_core.h index 392a1b81de..e1643d6277 100644 --- a/libs/libcurl/src/curl_ntlm_core.h +++ b/libs/libcurl/src/curl_ntlm_core.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -46,11 +46,9 @@ #define USE_NTRESPONSES /* Define USE_NTLM2SESSION in order to make the type-3 message include the - NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a - Crypto engine that we have curl_ssl_md5sum() for. */ -#if defined(USE_NTRESPONSES) && \ - (!defined(USE_WIN32_CRYPTO) || \ - (defined(USE_SSL) && !defined(CURL_DISABLE_CRYPTO_AUTH))) + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and + MD5 support */ +#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH) #define USE_NTLM2SESSION #endif diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index 30b54de444..f820b842e8 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -76,22 +76,22 @@ # define sclose_nolog(x) close((x)) #endif -void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn) +static void ntlm_wb_cleanup(struct ntlmdata *ntlm) { - if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { - sclose(conn->ntlm_auth_hlpr_socket); - conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { + sclose(ntlm->ntlm_auth_hlpr_socket); + ntlm->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; } - if(conn->ntlm_auth_hlpr_pid) { + if(ntlm->ntlm_auth_hlpr_pid) { int i; for(i = 0; i < 4; i++) { - pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); - if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) + pid_t ret = waitpid(ntlm->ntlm_auth_hlpr_pid, NULL, WNOHANG); + if(ret == ntlm->ntlm_auth_hlpr_pid || errno == ECHILD) break; switch(i) { case 0: - kill(conn->ntlm_auth_hlpr_pid, SIGTERM); + kill(ntlm->ntlm_auth_hlpr_pid, SIGTERM); break; case 1: /* Give the process another moment to shut down cleanly before @@ -99,20 +99,21 @@ void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn) Curl_wait_ms(1); break; case 2: - kill(conn->ntlm_auth_hlpr_pid, SIGKILL); + kill(ntlm->ntlm_auth_hlpr_pid, SIGKILL); break; case 3: break; } } - conn->ntlm_auth_hlpr_pid = 0; + ntlm->ntlm_auth_hlpr_pid = 0; } - Curl_safefree(conn->challenge_header); - Curl_safefree(conn->response_header); + Curl_safefree(ntlm->challenge); + Curl_safefree(ntlm->response); } -static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) +static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm, + const char *userp) { curl_socket_t sockfds[2]; pid_t child_pid; @@ -126,9 +127,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) #endif char buffer[STRERROR_LEN]; +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + /* Return if communication with ntlm_auth already set up */ - if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || - conn->ntlm_auth_hlpr_pid) + if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || + ntlm->ntlm_auth_hlpr_pid) return CURLE_OK; username = userp; @@ -179,13 +184,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) ntlm_auth = NTLM_WB_FILE; if(access(ntlm_auth, X_OK) != 0) { - failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", + failf(data, "Could not access ntlm_auth: %s errno %d: %s", ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } - if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { - failf(conn->data, "Could not open socket pair. errno %d: %s", + if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { + failf(data, "Could not open socket pair. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } @@ -194,7 +199,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) if(child_pid == -1) { sclose(sockfds[0]); sclose(sockfds[1]); - failf(conn->data, "Could not fork. errno %d: %s", + failf(data, "Could not fork. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } @@ -206,13 +211,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) /* Don't use sclose in the child since it fools the socket leak detector */ sclose_nolog(sockfds[0]); if(dup2(sockfds[1], STDIN_FILENO) == -1) { - failf(conn->data, "Could not redirect child stdin. errno %d: %s", + failf(data, "Could not redirect child stdin. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } if(dup2(sockfds[1], STDOUT_FILENO) == -1) { - failf(conn->data, "Could not redirect child stdout. errno %d: %s", + failf(data, "Could not redirect child stdout. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } @@ -232,14 +237,14 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) NULL); sclose_nolog(sockfds[1]); - failf(conn->data, "Could not execl(). errno %d: %s", + failf(data, "Could not execl(). errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } sclose(sockfds[1]); - conn->ntlm_auth_hlpr_socket = sockfds[0]; - conn->ntlm_auth_hlpr_pid = child_pid; + ntlm->ntlm_auth_hlpr_socket = sockfds[0]; + ntlm->ntlm_auth_hlpr_pid = child_pid; free(domain); free(ntlm_auth_alloc); return CURLE_OK; @@ -253,17 +258,21 @@ done: /* if larger than this, something is seriously wrong */ #define MAX_NTLM_WB_RESPONSE 100000 -static CURLcode ntlm_wb_response(struct connectdata *conn, +static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm, const char *input, curlntlm state) { char *buf = malloc(NTLM_BUFSIZE); size_t len_in = strlen(input), len_out = 0; +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + if(!buf) return CURLE_OUT_OF_MEMORY; while(len_in > 0) { - ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); + ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in); if(written == -1) { /* Interrupted by a signal, retry it */ if(errno == EINTR) @@ -279,7 +288,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, ssize_t size; char *newbuf; - size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); + size = sread(ntlm->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); if(size == -1) { if(errno == EINTR) continue; @@ -295,7 +304,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, } if(len_out > MAX_NTLM_WB_RESPONSE) { - failf(conn->data, "too large ntlm_wb response!"); + failf(data, "too large ntlm_wb response!"); free(buf); return CURLE_OUT_OF_MEMORY; } @@ -323,9 +332,9 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) goto done; - conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3); + ntlm->response = aprintf("%.*s", len_out - 4, buf + 3); free(buf); - if(!conn->response_header) + if(!ntlm->response) return CURLE_OUT_OF_MEMORY; return CURLE_OK; done: @@ -337,6 +346,7 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy, const char *header) { + struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; if(!checkprefix("NTLM", header)) @@ -347,8 +357,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn, header++; if(*header) { - conn->challenge_header = strdup(header); - if(!conn->challenge_header) + ntlm->challenge = strdup(header); + if(!ntlm->challenge) return CURLE_OUT_OF_MEMORY; *state = NTLMSTATE_TYPE2; /* We got a type-2 message */ @@ -387,6 +397,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, char **allocuserpwd; /* point to the name and password for this */ const char *userp; + struct ntlmdata *ntlm; curlntlm *state; struct auth *authp; @@ -398,12 +409,14 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; userp = conn->http_proxy.user; + ntlm = &conn->proxyntlm; state = &conn->proxy_ntlm_state; authp = &conn->data->state.authproxy; } else { allocuserpwd = &conn->allocptr.userpwd; userp = conn->user; + ntlm = &conn->ntlm; state = &conn->http_ntlm_state; authp = &conn->data->state.authhost; } @@ -429,36 +442,36 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, * request handling process. */ /* Create communication with ntlm_auth */ - res = ntlm_wb_init(conn, userp); + res = ntlm_wb_init(conn->data, ntlm, userp); if(res) return res; - res = ntlm_wb_response(conn, "YR\n", *state); + res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state); if(res) return res; free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "", - conn->response_header); + ntlm->response); DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); - Curl_safefree(conn->response_header); + Curl_safefree(ntlm->response); if(!*allocuserpwd) return CURLE_OUT_OF_MEMORY; break; case NTLMSTATE_TYPE2: { - char *input = aprintf("TT %s\n", conn->challenge_header); + char *input = aprintf("TT %s\n", ntlm->challenge); if(!input) return CURLE_OUT_OF_MEMORY; - res = ntlm_wb_response(conn, input, *state); + res = ntlm_wb_response(conn->data, ntlm, input, *state); free(input); if(res) return res; free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "", - conn->response_header); + ntlm->response); DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); *state = NTLMSTATE_TYPE3; /* we sent a type-3 */ authp->done = TRUE; @@ -481,4 +494,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, return CURLE_OK; } +void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn) +{ + ntlm_wb_cleanup(&conn->ntlm); + ntlm_wb_cleanup(&conn->proxyntlm); +} + #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c index 0aa1f5bb7a..8c1c86623d 100644 --- a/libs/libcurl/src/curl_sasl.c +++ b/libs/libcurl/src/curl_sasl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, 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 @@ -272,6 +272,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, data->set.str[STRING_SERVICE_NAME] : sasl->params->service; #endif + const char *oauth_bearer = data->set.str[STRING_BEARER]; sasl->force_ir = force_ir; /* Latch for future use */ sasl->authused = 0; /* No mechanism used yet */ @@ -341,7 +342,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, } else #endif - if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) { + if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) { mech = SASL_MECH_STRING_OAUTHBEARER; state1 = SASL_OAUTH2; state2 = SASL_OAUTH2_RESP; @@ -351,17 +352,17 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, result = Curl_auth_create_oauth_bearer_message(data, conn->user, hostname, port, - conn->oauth_bearer, + oauth_bearer, &resp, &len); } - else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) { + else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) { mech = SASL_MECH_STRING_XOAUTH2; state1 = SASL_OAUTH2; sasl->authused = SASL_MECH_XOAUTH2; if(force_ir || data->set.sasl_ir) result = Curl_auth_create_xoauth_bearer_message(data, conn->user, - conn->oauth_bearer, + oauth_bearer, &resp, &len); } else if(enabledmechs & SASL_MECH_PLAIN) { @@ -431,6 +432,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, char *serverdata; #endif size_t len = 0; + const char *oauth_bearer = data->set.str[STRING_BEARER]; *progress = SASL_INPROGRESS; @@ -558,7 +560,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, result = Curl_auth_create_oauth_bearer_message(data, conn->user, hostname, port, - conn->oauth_bearer, + oauth_bearer, &resp, &len); /* Failures maybe sent by the server as continuations for OAUTHBEARER */ @@ -566,7 +568,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, } else result = Curl_auth_create_xoauth_bearer_message(data, conn->user, - conn->oauth_bearer, + oauth_bearer, &resp, &len); break; diff --git a/libs/libcurl/src/curl_sha256.h b/libs/libcurl/src/curl_sha256.h index 14b6414ea0..35d286cebd 100644 --- a/libs/libcurl/src/curl_sha256.h +++ b/libs/libcurl/src/curl_sha256.h @@ -7,7 +7,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Florin Petriuc, <petriuc.florin@gmail.com> + * Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com> + * Copyright (C) 2018 - 2020, 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 @@ -24,8 +25,10 @@ #ifndef CURL_DISABLE_CRYPTO_AUTH -void Curl_sha256it(unsigned char *outbuffer, - const unsigned char *input); +#define SHA256_DIGEST_LENGTH 32 + +void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input, + const size_t len); #endif diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index 7f4eee5d81..aaa8f15ca6 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2018 - 2020, 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 @@ -548,7 +548,7 @@ static DOHcode store_cname(unsigned char *doh, if((index + 1) >= dohlen) return DOH_DNS_OUT_OF_RANGE; - /* move to the the new index */ + /* move to the new index */ newpos = (length & 0x3f) << 8 | doh[index + 1]; index = newpos; continue; diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 6382cee3d5..1a6912748e 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -76,6 +76,7 @@ #include "setopt.h" #include "http_digest.h" #include "system_win32.h" +#include "http2.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -185,16 +186,18 @@ static CURLcode global_init(long flags, bool memoryfuncs) goto fail; } - (void)Curl_ipv6works(); - #if defined(USE_SSH) if(Curl_ssh_init()) { goto fail; } #endif - if(flags & CURL_GLOBAL_ACK_EINTR) - Curl_ack_eintr = 1; +#ifdef USE_WOLFSSH + if(WS_SUCCESS != wolfSSH_Init()) { + DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); + return CURLE_FAILED_INIT; + } +#endif init_flags = flags; @@ -272,6 +275,10 @@ void curl_global_cleanup(void) Curl_ssh_cleanup(); +#ifdef USE_WOLFSSH + (void)wolfSSH_Cleanup(); +#endif + init_flags = 0; } @@ -684,10 +691,6 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) sigpipe_ignore(data, &pipe_st); - /* assign this after curl_multi_add_handle() since that function checks for - it and rejects this handle otherwise */ - data->multi = multi; - /* run the transfer */ result = events ? easy_events(multi) : easy_transfer(multi); @@ -983,49 +986,54 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) /* put it back in the keepon */ k->keepon = newstate; - if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { - /* there are buffers for sending that can be delivered as the receive - pausing is lifted! */ - unsigned int i; - unsigned int count = data->state.tempcount; - struct tempbuf writebuf[3]; /* there can only be three */ - struct connectdata *conn = data->conn; - struct Curl_easy *saved_data = NULL; - - /* copy the structs to allow for immediate re-pausing */ - for(i = 0; i < data->state.tempcount; i++) { - writebuf[i] = data->state.tempwrite[i]; - data->state.tempwrite[i].buf = NULL; - } - data->state.tempcount = 0; + if(!(newstate & KEEP_RECV_PAUSE)) { + Curl_http2_stream_pause(data, FALSE); + + if(data->state.tempcount) { + /* there are buffers for sending that can be delivered as the receive + pausing is lifted! */ + unsigned int i; + unsigned int count = data->state.tempcount; + struct tempbuf writebuf[3]; /* there can only be three */ + struct connectdata *conn = data->conn; + struct Curl_easy *saved_data = NULL; + + /* copy the structs to allow for immediate re-pausing */ + for(i = 0; i < data->state.tempcount; i++) { + writebuf[i] = data->state.tempwrite[i]; + data->state.tempwrite[i].buf = NULL; + } + data->state.tempcount = 0; - /* set the connection's current owner */ - if(conn->data != data) { - saved_data = conn->data; - conn->data = data; - } + /* set the connection's current owner */ + if(conn->data != data) { + saved_data = conn->data; + conn->data = data; + } - for(i = 0; i < count; i++) { - /* even if one function returns error, this loops through and frees all - buffers */ - if(!result) - result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, - writebuf[i].len); - free(writebuf[i].buf); - } + for(i = 0; i < count; i++) { + /* even if one function returns error, this loops through and frees + all buffers */ + if(!result) + result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, + writebuf[i].len); + free(writebuf[i].buf); + } - /* recover previous owner of the connection */ - if(saved_data) - conn->data = saved_data; + /* recover previous owner of the connection */ + if(saved_data) + conn->data = saved_data; - if(result) - return result; + if(result) + return result; + } } /* if there's no error and we're not pausing both directions, we want to have this handle checked soon */ if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) { + data->state.drain++; Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ if(data->multi) Curl_update_timer(data->multi); diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c index 429d479da5..50a37e0e74 100644 --- a/libs/libcurl/src/formdata.c +++ b/libs/libcurl/src/formdata.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index 469096f0f6..57b22ade97 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -55,7 +55,6 @@ #include "transfer.h" #include "escape.h" #include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" #include "ftp.h" #include "fileinfo.h" #include "ftplistparser.h" @@ -78,6 +77,7 @@ #include "warnless.h" #include "http_proxy.h" #include "non-ascii.h" +#include "socks.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -253,18 +253,6 @@ static void freedirs(struct ftp_conn *ftpc) Curl_safefree(ftpc->newhost); } -/* Returns non-zero if the given string contains CR (\r) or LF (\n), - which are not allowed within RFC 959 <string>. - Note: The input string is in the client's encoding which might - not be ASCII, so escape sequences \r & \n must be used instead - of hex values 0x0d & 0x0a. -*/ -static bool isBadFtpString(const char *string) -{ - return ((NULL != strchr(string, '\r')) || - (NULL != strchr(string, '\n'))) ? TRUE : FALSE; -} - /*********************************************************************** * * AcceptServerConnect() @@ -303,7 +291,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) conn->sock[SECONDARYSOCKET] = s; (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ - conn->sock_accepted[SECONDARYSOCKET] = TRUE; + conn->sock_accepted = TRUE; if(data->set.fsockopt) { int error = 0; @@ -785,9 +773,8 @@ static void _state(struct connectdata *conn, static CURLcode ftp_state_user(struct connectdata *conn) { CURLcode result; - struct FTP *ftp = conn->data->req.protop; /* send USER */ - PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); + PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:""); state(conn, FTP_USER); conn->data->state.ftp_trying_alternative = FALSE; @@ -823,6 +810,9 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks) * handle ordinary commands. */ + if(SOCKS_STATE(conn->cnnct.state)) + return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET); + if(FTP_STOP == ftpc->state) { int bits = GETSOCK_READSOCK(0); @@ -920,7 +910,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, struct ftp_conn *ftpc = &conn->proto.ftpc; struct Curl_easy *data = conn->data; curl_socket_t portsock = CURL_SOCKET_BAD; - char myhost[256] = ""; + char myhost[MAX_IPADR_LEN + 1] = ""; struct Curl_sockaddr_storage ss; Curl_addrinfo *res, *ai; @@ -931,9 +921,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, #ifdef ENABLE_IPV6 struct sockaddr_in6 * const sa6 = (void *)sa; #endif - char tmp[1024]; static const char mode[][5] = { "EPRT", "PORT" }; - int rc; + enum resolve_t rc; int error; char *host = NULL; char *string_ftpport = data->set.str[STRING_FTPPORT]; @@ -1246,8 +1235,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, break; } if(PORT == fcmd) { + /* large enough for [IP address],[num],[num] */ + char target[sizeof(myhost) + 20]; char *source = myhost; - char *dest = tmp; + char *dest = target; /* translate x.x.x.x to x,x,x,x */ while(source && *source) { @@ -1261,7 +1252,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, *dest = 0; msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); - result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); + result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target); if(result) { failf(data, "Failure sending PORT command: %s", curl_easy_strerror(result)); @@ -1806,7 +1797,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, CURLcode result; struct Curl_easy *data = conn->data; struct Curl_dns_entry *addr = NULL; - int rc; + enum resolve_t rc; unsigned short connectport; /* the local port connect() should use! */ char *str = &data->state.buffer[4]; /* start on the first letter */ @@ -2528,7 +2519,6 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; struct ftp_conn *ftpc = &conn->proto.ftpc; (void)instate; /* no use for this yet */ @@ -2536,7 +2526,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, if((ftpcode == 331) && (ftpc->state == FTP_USER)) { /* 331 Password required for ... (the server requires to send the user's password too) */ - PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); + PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:""); state(conn, FTP_PASS); } else if(ftpcode/100 == 2) { @@ -4369,18 +4359,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) /* get some initial data into the ftp struct */ ftp->transfer = FTPTRANSFER_BODY; ftp->downloadsize = 0; - - /* No need to duplicate user+password, the connectdata struct won't change - during a session, but we re-init them here since on subsequent inits - since the conn struct may have changed or been replaced. - */ - ftp->user = conn->user; - ftp->passwd = conn->passwd; - if(isBadFtpString(ftp->user)) - return CURLE_URL_MALFORMAT; - if(isBadFtpString(ftp->passwd)) - return CURLE_URL_MALFORMAT; - conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ return CURLE_OK; diff --git a/libs/libcurl/src/ftp.h b/libs/libcurl/src/ftp.h index 2c88d568c1..984347f2a3 100644 --- a/libs/libcurl/src/ftp.h +++ b/libs/libcurl/src/ftp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -102,8 +102,6 @@ typedef enum { perhaps the Curl_easy is changed between the times the connection is used. */ struct FTP { - char *user; /* user name string */ - char *passwd; /* password string */ char *path; /* points to the urlpieces struct field */ char *pathalloc; /* if non-NULL a pointer to an allocated path */ diff --git a/libs/libcurl/src/getenv.c b/libs/libcurl/src/getenv.c index e444a6a3ad..9385b8f677 100644 --- a/libs/libcurl/src/getenv.c +++ b/libs/libcurl/src/getenv.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -27,25 +27,48 @@ #include "memdebug.h" -static -char *GetEnv(const char *variable) +static char *GetEnv(const char *variable) { #if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) (void)variable; return NULL; -#else -#ifdef WIN32 - char env[4096]; - char *temp = getenv(variable); - env[0] = '\0'; - if(temp != NULL) - ExpandEnvironmentStringsA(temp, env, sizeof(env)); - return (env[0] != '\0')?strdup(env):NULL; +#elif defined(WIN32) + /* This uses Windows API instead of C runtime getenv() to get the environment + variable since some changes aren't always visible to the latter. #4774 */ + char *buf = NULL; + char *tmp; + DWORD bufsize; + DWORD rc = 1; + const DWORD max = 32768; /* max env var size from MSCRT source */ + + for(;;) { + tmp = realloc(buf, rc); + if(!tmp) { + free(buf); + return NULL; + } + + buf = tmp; + bufsize = rc; + + /* It's possible for rc to be 0 if the variable was found but empty. + Since getenv doesn't make that distinction we ignore it as well. */ + rc = GetEnvironmentVariableA(variable, buf, bufsize); + if(!rc || rc == bufsize || rc > max) { + free(buf); + return NULL; + } + + /* if rc < bufsize then rc is bytes written not including null */ + if(rc < bufsize) + return buf; + + /* else rc is bytes needed, try again */ + } #else char *env = getenv(variable); return (env && env[0])?strdup(env):NULL; #endif -#endif } char *curl_getenv(const char *v) diff --git a/libs/libcurl/src/hmac.c b/libs/libcurl/src/hmac.c index bf49ebec54..ae68827bea 100644 --- a/libs/libcurl/src/hmac.c +++ b/libs/libcurl/src/hmac.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -30,6 +30,7 @@ #include "curl_hmac.h" #include "curl_memory.h" +#include "warnless.h" /* The last #include file should be: */ #include "memdebug.h" @@ -129,4 +130,40 @@ int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) return 0; } +/* + * Curl_hmacit() + * + * This is used to generate a HMAC hash, for the specified input data, given + * the specified hash function and key. + * + * Parameters: + * + * hashparams [in] - The hash function (Curl_HMAC_MD5). + * key [in] - The key to use. + * keylen [in] - The length of the key. + * data [in] - The data to encrypt. + * datalen [in] - The length of the data. + * output [in/out] - The output buffer. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_hmacit(const HMAC_params *hashparams, + const unsigned char *key, const size_t keylen, + const unsigned char *data, const size_t datalen, + unsigned char *output) +{ + HMAC_context *ctxt = Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen)); + + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + Curl_HMAC_update(ctxt, data, curlx_uztoui(datalen)); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, output); + + return CURLE_OK; +} + #endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index b434b390a2..c0feb79fb3 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -59,6 +59,7 @@ #include "strerror.h" #include "url.h" #include "inet_ntop.h" +#include "inet_pton.h" #include "multiif.h" #include "doh.h" #include "warnless.h" @@ -482,16 +483,16 @@ Curl_cache_addr(struct Curl_easy *data, * CURLRESOLV_PENDING (1) = waiting for response, no pointer */ -int Curl_resolv(struct connectdata *conn, - const char *hostname, - int port, - bool allowDOH, - struct Curl_dns_entry **entry) +enum resolve_t Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **entry) { struct Curl_dns_entry *dns = NULL; struct Curl_easy *data = conn->data; CURLcode result; - int rc = CURLRESOLV_ERROR; /* default to failure */ + enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */ *entry = NULL; @@ -512,13 +513,11 @@ int Curl_resolv(struct connectdata *conn, if(!dns) { /* The entry was not in the cache. Resolve it to IP address */ - Curl_addrinfo *addr; + Curl_addrinfo *addr = NULL; int respwait = 0; - - /* Check what IP specifics the app has requested and if we can provide it. - * If not, bail out. */ - if(!Curl_ipvalid(conn)) - return CURLRESOLV_ERROR; +#ifndef USE_RESOLVE_ON_IPS + struct in_addr in; +#endif /* notify the resolver start callback */ if(data->set.resolver_start) { @@ -531,20 +530,43 @@ int Curl_resolv(struct connectdata *conn, return CURLRESOLV_ERROR; } - if(allowDOH && data->set.doh) { - addr = Curl_doh(conn, hostname, port, &respwait); +#ifndef USE_RESOLVE_ON_IPS + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + addr = Curl_ip2addr(AF_INET, &in, hostname, port); +#ifdef ENABLE_IPV6 + if(!addr) { + struct in6_addr in6; + /* check if this is an IPv6 address string */ + if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) + /* This is an IPv6 address literal */ + addr = Curl_ip2addr(AF_INET6, &in6, hostname, port); } - else { - /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a - non-zero value indicating that we need to wait for the response to the - resolve call */ - addr = Curl_getaddrinfo(conn, +#endif /* ENABLE_IPV6 */ +#endif /* !USE_RESOLVE_ON_IPS */ + + if(!addr) { + /* Check what IP specifics the app has requested and if we can provide + * it. If not, bail out. */ + if(!Curl_ipvalid(conn)) + return CURLRESOLV_ERROR; + + if(allowDOH && data->set.doh) { + addr = Curl_doh(conn, hostname, port, &respwait); + } + else { + /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a + non-zero value indicating that we need to wait for the response to + the resolve call */ + addr = Curl_getaddrinfo(conn, #ifdef DEBUGBUILD - (data->set.str[STRING_DEVICE] - && !strcmp(data->set.str[STRING_DEVICE], - "LocalHost"))?"localhost": + (data->set.str[STRING_DEVICE] + && !strcmp(data->set.str[STRING_DEVICE], + "LocalHost"))?"localhost": #endif - hostname, port, &respwait); + hostname, port, &respwait); + } } if(!addr) { if(respwait) { @@ -620,11 +642,11 @@ RETSIGTYPE alarmfunc(int sig) * CURLRESOLV_PENDING (1) = waiting for response, no pointer */ -int Curl_resolv_timeout(struct connectdata *conn, - const char *hostname, - int port, - struct Curl_dns_entry **entry, - timediff_t timeoutms) +enum resolve_t Curl_resolv_timeout(struct connectdata *conn, + const char *hostname, + int port, + struct Curl_dns_entry **entry, + timediff_t timeoutms) { #ifdef USE_ALARM_TIMEOUT #ifdef HAVE_SIGACTION @@ -640,7 +662,7 @@ int Curl_resolv_timeout(struct connectdata *conn, volatile unsigned int prev_alarm = 0; struct Curl_easy *data = conn->data; #endif /* USE_ALARM_TIMEOUT */ - int rc; + enum resolve_t rc; *entry = NULL; diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index e0597ea96a..baf1e5860a 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -79,26 +79,29 @@ struct Curl_dns_entry { * use, or we'll leak memory! */ /* return codes */ -#define CURLRESOLV_TIMEDOUT -2 -#define CURLRESOLV_ERROR -1 -#define CURLRESOLV_RESOLVED 0 -#define CURLRESOLV_PENDING 1 -int Curl_resolv(struct connectdata *conn, - const char *hostname, - int port, - bool allowDOH, - struct Curl_dns_entry **dnsentry); -int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, - int port, struct Curl_dns_entry **dnsentry, - timediff_t timeoutms); +enum resolve_t { + CURLRESOLV_TIMEDOUT = -2, + CURLRESOLV_ERROR = -1, + CURLRESOLV_RESOLVED = 0, + CURLRESOLV_PENDING = 1 +}; +enum resolve_t Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **dnsentry); +enum resolve_t Curl_resolv_timeout(struct connectdata *conn, + const char *hostname, int port, + struct Curl_dns_entry **dnsentry, + timediff_t timeoutms); #ifdef CURLRES_IPV6 /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(void); +bool Curl_ipv6works(struct connectdata *conn); #else -#define Curl_ipv6works() FALSE +#define Curl_ipv6works(x) FALSE #endif /* diff --git a/libs/libcurl/src/hostip4.c b/libs/libcurl/src/hostip4.c index 2636851e68..d5009a3efb 100644 --- a/libs/libcurl/src/hostip4.c +++ b/libs/libcurl/src/hostip4.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -52,7 +52,6 @@ #include "share.h" #include "strerror.h" #include "url.h" -#include "inet_pton.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -128,38 +127,22 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, #endif Curl_addrinfo *ai = NULL; struct hostent *h = NULL; - struct in_addr in; struct hostent *buf = NULL; -#ifdef ENABLE_IPV6 - { - struct in6_addr in6; - /* check if this is an IPv6 address string */ - if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) - /* This is an IPv6 address literal */ - return Curl_ip2addr(AF_INET6, &in6, hostname, port); - } -#endif /* ENABLE_IPV6 */ - - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - #if defined(HAVE_GETADDRINFO_THREADSAFE) - else { - struct addrinfo hints; - char sbuf[12]; - char *sbufptr = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - if(port) { - msnprintf(sbuf, sizeof(sbuf), "%d", port); - sbufptr = sbuf; - } + struct addrinfo hints; + char sbuf[12]; + char *sbufptr = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + if(port) { + msnprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } - (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); + (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); #elif defined(HAVE_GETHOSTBYNAME_R) /* @@ -167,144 +150,141 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, * Since there are three different versions of it, the following code is * somewhat #ifdef-ridden. */ - else { - int h_errnop; - - buf = calloc(1, CURL_HOSTENT_SIZE); - if(!buf) - return NULL; /* major failure */ - /* - * The clearing of the buffer is a workaround for a gethostbyname_r bug in - * qnx nto and it is also _required_ for some of these functions on some - * platforms. - */ + int h_errnop; + + buf = calloc(1, CURL_HOSTENT_SIZE); + if(!buf) + return NULL; /* major failure */ + /* + * The clearing of the buffer is a workaround for a gethostbyname_r bug in + * qnx nto and it is also _required_ for some of these functions on some + * platforms. + */ #if defined(HAVE_GETHOSTBYNAME_R_5) - /* Solaris, IRIX and more */ - h = gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_HOSTENT_SIZE - sizeof(struct hostent), - &h_errnop); - - /* If the buffer is too small, it returns NULL and sets errno to - * ERANGE. The errno is thread safe if this is compiled with - * -D_REENTRANT as then the 'errno' variable is a macro defined to get - * used properly for threads. - */ + /* Solaris, IRIX and more */ + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h_errnop); + + /* If the buffer is too small, it returns NULL and sets errno to + * ERANGE. The errno is thread safe if this is compiled with + * -D_REENTRANT as then the 'errno' variable is a macro defined to get + * used properly for threads. + */ - if(h) { - ; - } - else + if(h) { + ; + } + else #elif defined(HAVE_GETHOSTBYNAME_R_6) - /* Linux */ - - (void)gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_HOSTENT_SIZE - sizeof(struct hostent), - &h, /* DIFFERENCE */ - &h_errnop); - /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a - * sudden this function returns EAGAIN if the given buffer size is too - * small. Previous versions are known to return ERANGE for the same - * problem. - * - * This wouldn't be such a big problem if older versions wouldn't - * sometimes return EAGAIN on a common failure case. Alas, we can't - * assume that EAGAIN *or* ERANGE means ERANGE for any given version of - * glibc. - * - * For now, we do that and thus we may call the function repeatedly and - * fail for older glibc versions that return EAGAIN, until we run out of - * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). - * - * If anyone has a better fix, please tell us! - * - * ------------------------------------------------------------------- - * - * On October 23rd 2003, Dan C dug up more details on the mysteries of - * gethostbyname_r() in glibc: - * - * In glibc 2.2.5 the interface is different (this has also been - * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't - * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 - * (shipped/upgraded by Redhat 7.2) don't show this behavior! - * - * In this "buggy" version, the return code is -1 on error and 'errno' - * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a - * thread-safe variable. - */ + /* Linux */ + + (void)gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + * sudden this function returns EAGAIN if the given buffer size is too + * small. Previous versions are known to return ERANGE for the same + * problem. + * + * This wouldn't be such a big problem if older versions wouldn't + * sometimes return EAGAIN on a common failure case. Alas, we can't + * assume that EAGAIN *or* ERANGE means ERANGE for any given version of + * glibc. + * + * For now, we do that and thus we may call the function repeatedly and + * fail for older glibc versions that return EAGAIN, until we run out of + * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). + * + * If anyone has a better fix, please tell us! + * + * ------------------------------------------------------------------- + * + * On October 23rd 2003, Dan C dug up more details on the mysteries of + * gethostbyname_r() in glibc: + * + * In glibc 2.2.5 the interface is different (this has also been + * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't + * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 + * (shipped/upgraded by Redhat 7.2) don't show this behavior! + * + * In this "buggy" version, the return code is -1 on error and 'errno' + * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a + * thread-safe variable. + */ - if(!h) /* failure */ + if(!h) /* failure */ #elif defined(HAVE_GETHOSTBYNAME_R_3) - /* AIX, Digital Unix/Tru64, HPUX 10, more? */ - - /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of - * the plain fact that it does not return unique full buffers on each - * call, but instead several of the pointers in the hostent structs will - * point to the same actual data! This have the unfortunate down-side that - * our caching system breaks down horribly. Luckily for us though, AIX 4.3 - * and more recent versions have a "completely thread-safe"[*] libc where - * all the data is stored in thread-specific memory areas making calls to - * the plain old gethostbyname() work fine even for multi-threaded - * programs. - * - * This AIX 4.3 or later detection is all made in the configure script. - * - * Troels Walsted Hansen helped us work this out on March 3rd, 2003. - * - * [*] = much later we've found out that it isn't at all "completely - * thread-safe", but at least the gethostbyname() function is. + /* AIX, Digital Unix/Tru64, HPUX 10, more? */ + + /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of + * the plain fact that it does not return unique full buffers on each + * call, but instead several of the pointers in the hostent structs will + * point to the same actual data! This have the unfortunate down-side that + * our caching system breaks down horribly. Luckily for us though, AIX 4.3 + * and more recent versions have a "completely thread-safe"[*] libc where + * all the data is stored in thread-specific memory areas making calls to + * the plain old gethostbyname() work fine even for multi-threaded + * programs. + * + * This AIX 4.3 or later detection is all made in the configure script. + * + * Troels Walsted Hansen helped us work this out on March 3rd, 2003. + * + * [*] = much later we've found out that it isn't at all "completely + * thread-safe", but at least the gethostbyname() function is. + */ + + if(CURL_HOSTENT_SIZE >= + (sizeof(struct hostent) + sizeof(struct hostent_data))) { + + /* August 22nd, 2000: Albert Chin-A-Young brought an updated version + * that should work! September 20: Richard Prescott worked on the buffer + * size dilemma. */ - if(CURL_HOSTENT_SIZE >= - (sizeof(struct hostent) + sizeof(struct hostent_data))) { - - /* August 22nd, 2000: Albert Chin-A-Young brought an updated version - * that should work! September 20: Richard Prescott worked on the buffer - * size dilemma. - */ - - res = gethostbyname_r(hostname, - (struct hostent *)buf, - (struct hostent_data *)((char *)buf + - sizeof(struct hostent))); - h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ - } - else - res = -1; /* failure, too smallish buffer size */ - - if(!res) { /* success */ - - h = buf; /* result expected in h */ - - /* This is the worst kind of the different gethostbyname_r() interfaces. - * Since we don't know how big buffer this particular lookup required, - * we can't realloc down the huge alloc without doing closer analysis of - * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every - * name lookup. Fixing this would require an extra malloc() and then - * calling Curl_addrinfo_copy() that subsequent realloc()s down the new - * memory area to the actually used amount. - */ - } - else + res = gethostbyname_r(hostname, + (struct hostent *)buf, + (struct hostent_data *)((char *)buf + + sizeof(struct hostent))); + h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ + } + else + res = -1; /* failure, too smallish buffer size */ + + if(!res) { /* success */ + + h = buf; /* result expected in h */ + + /* This is the worst kind of the different gethostbyname_r() interfaces. + * Since we don't know how big buffer this particular lookup required, + * we can't realloc down the huge alloc without doing closer analysis of + * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every + * name lookup. Fixing this would require an extra malloc() and then + * calling Curl_addrinfo_copy() that subsequent realloc()s down the new + * memory area to the actually used amount. + */ + } + else #endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ - { - h = NULL; /* set return code to NULL */ - free(buf); - } + { + h = NULL; /* set return code to NULL */ + free(buf); + } #else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ - /* - * Here is code for platforms that don't have a thread safe - * getaddrinfo() nor gethostbyname_r() function or for which - * gethostbyname() is the preferred one. - */ - else { - h = gethostbyname((void *)hostname); + /* + * Here is code for platforms that don't have a thread safe + * getaddrinfo() nor gethostbyname_r() function or for which + * gethostbyname() is the preferred one. + */ + h = gethostbyname((void *)hostname); #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ - } if(h) { ai = Curl_he2ai(h, port); diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index e0e0c58dfa..41ff986964 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -62,13 +62,19 @@ /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(void) +bool Curl_ipv6works(struct connectdata *conn) { - /* the nature of most system is that IPv6 status doesn't come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast re-use */ - static int ipv6_works = -1; - if(-1 == ipv6_works) { + if(conn) { + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + DEBUGASSERT(conn->data->multi); + return conn->data->multi->ipv6_works; + } + else { + int ipv6_works = -1; /* probe to see if we have a working IPv6 stack */ curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); if(s == CURL_SOCKET_BAD) @@ -78,8 +84,8 @@ bool Curl_ipv6works(void) ipv6_works = 1; Curl_closesocket(NULL, s); } + return (ipv6_works>0)?TRUE:FALSE; } - return (ipv6_works>0)?TRUE:FALSE; } /* @@ -89,7 +95,7 @@ bool Curl_ipv6works(void) bool Curl_ipvalid(struct connectdata *conn) { if(conn->ip_version == CURL_IPRESOLVE_V6) - return Curl_ipv6works(); + return Curl_ipv6works(conn); return TRUE; } @@ -159,7 +165,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works()) + if((pf != PF_INET) && !Curl_ipv6works(conn)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index 837f53c415..bff3adc170 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -344,7 +344,7 @@ static CURLcode http_output_bearer(struct connectdata *conn) userp = &conn->allocptr.userpwd; free(*userp); *userp = aprintf("Authorization: Bearer %s\r\n", - conn->oauth_bearer); + conn->data->set.str[STRING_BEARER]); if(!*userp) { result = CURLE_OUT_OF_MEMORY; @@ -555,7 +555,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) CURLcode result = CURLE_OK; unsigned long authmask = ~0ul; - if(!conn->oauth_bearer) + if(!data->set.str[STRING_BEARER]) authmask &= (unsigned long)~CURLAUTH_BEARER; if(100 <= data->req.httpcode && 199 >= data->req.httpcode) @@ -565,7 +565,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(data->state.authproblem) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; - if((conn->bits.user_passwd || conn->oauth_bearer) && + if((conn->bits.user_passwd || data->set.str[STRING_BEARER]) && ((data->req.httpcode == 401) || (conn->bits.authneg && data->req.httpcode < 300))) { pickhost = pickoneauth(&data->state.authhost, authmask); @@ -641,9 +641,7 @@ output_auth_headers(struct connectdata *conn, { const char *auth = NULL; CURLcode result = CURLE_OK; -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) struct Curl_easy *data = conn->data; -#endif #ifdef CURL_DISABLE_CRYPTO_AUTH (void)request; @@ -707,7 +705,7 @@ output_auth_headers(struct connectdata *conn, } if(authstatus->picked == CURLAUTH_BEARER) { /* Bearer */ - if((!proxy && conn->oauth_bearer && + if((!proxy && data->set.str[STRING_BEARER] && !Curl_checkheaders(conn, "Authorization:"))) { auth = "Bearer"; result = http_output_bearer(conn); @@ -765,7 +763,7 @@ Curl_http_output_auth(struct connectdata *conn, authproxy = &data->state.authproxy; if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || - conn->bits.user_passwd || conn->oauth_bearer) + conn->bits.user_passwd || data->set.str[STRING_BEARER]) /* continue please */; else { authhost->done = TRUE; @@ -1691,7 +1689,7 @@ static CURLcode expect100(struct Curl_easy *data, CURLcode result = CURLE_OK; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if(use_http_1_1plus(data, conn) && + if(!data->state.disableexpect && use_http_1_1plus(data, conn) && (conn->httpversion < 20)) { /* 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 @@ -2390,7 +2388,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } } - /* Extract the the URL to use in the request. Store in STRING_TEMP_URL for + /* Extract the URL to use in the request. Store in STRING_TEMP_URL for clean-up reasons if the function returns before the free() further down. */ uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0); @@ -3046,6 +3044,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } if(result) return result; + if(!postsize) + data->req.upload_done = TRUE; if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted @@ -3545,7 +3545,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, */ Curl_expire_done(data, EXPIRE_100_TIMEOUT); if(!k->upload_done) { - if(data->set.http_keep_sending_on_error) { + if((k->httpcode == 417) && data->state.expect100header) { + /* 417 Expectation Failed - try again without the Expect + header */ + infof(data, "Got 417 while waiting for a 100\n"); + data->state.disableexpect = TRUE; + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(conn->data->change.url); + Curl_done_sending(conn, k); + } + else if(data->set.http_keep_sending_on_error) { infof(data, "HTTP error before end of send, keep sending\n"); if(k->exp100 > EXP100_SEND_DATA) { k->exp100 = EXP100_SEND_DATA; diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index 70d5dccec6..4c1825f60f 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -116,7 +116,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn); * */ #ifndef EXPECT_100_THRESHOLD -#define EXPECT_100_THRESHOLD 1024 +#define EXPECT_100_THRESHOLD (1024*1024) #endif #endif /* CURL_DISABLE_HTTP */ diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index 65f3513ee5..72b38a3f66 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -43,19 +43,11 @@ #define H2_BUFSIZE 32768 -#if (NGHTTP2_VERSION_NUM < 0x010000) +#if (NGHTTP2_VERSION_NUM < 0x010c00) #error too old nghttp2 version, upgrade! #endif -#if (NGHTTP2_VERSION_NUM > 0x010800) -#define NGHTTP2_HAS_HTTP2_STRERROR 1 -#endif - -#if (NGHTTP2_VERSION_NUM >= 0x010900) -/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or - later */ -#define NGHTTP2_HAS_ERROR_CALLBACK 1 -#else +#ifdef CURL_DISABLE_VERBOSE_STRINGS #define nghttp2_session_callbacks_set_error_callback(x,y) #endif @@ -63,7 +55,7 @@ #define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1 #endif -#define HTTP2_HUGE_WINDOW_SIZE (1 << 30) +#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */ #ifdef DEBUG_HTTP2 #define H2BUGF(x) x @@ -344,35 +336,6 @@ int Curl_http2_ver(char *p, size_t len) return msnprintf(p, len, " nghttp2/%s", h2->version_str); } -/* HTTP/2 error code to name based on the Error Code Registry. -https://tools.ietf.org/html/rfc7540#page-77 -nghttp2_error_code enums are identical. -*/ -static const char *http2_strerror(uint32_t err) -{ -#ifndef NGHTTP2_HAS_HTTP2_STRERROR - const char *str[] = { - "NO_ERROR", /* 0x0 */ - "PROTOCOL_ERROR", /* 0x1 */ - "INTERNAL_ERROR", /* 0x2 */ - "FLOW_CONTROL_ERROR", /* 0x3 */ - "SETTINGS_TIMEOUT", /* 0x4 */ - "STREAM_CLOSED", /* 0x5 */ - "FRAME_SIZE_ERROR", /* 0x6 */ - "REFUSED_STREAM", /* 0x7 */ - "CANCEL", /* 0x8 */ - "COMPRESSION_ERROR", /* 0x9 */ - "CONNECT_ERROR", /* 0xA */ - "ENHANCE_YOUR_CALM", /* 0xB */ - "INADEQUATE_SECURITY", /* 0xC */ - "HTTP_1_1_REQUIRED" /* 0xD */ - }; - return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown"; -#else - return nghttp2_http2_strerror(err); -#endif -} - /* * The implementation of nghttp2_send_callback type. Here we write |data| with * size |length| to the network and return the number of bytes actually @@ -838,7 +801,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, return 0; } H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", - http2_strerror(error_code), error_code, stream_id)); + nghttp2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1138,8 +1101,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session, return nread; } -#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \ - !defined(CURL_DISABLE_VERBOSE_STRINGS) +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) static int error_callback(nghttp2_session *session, const char *msg, size_t len, @@ -1156,9 +1118,10 @@ static void populate_settings(struct connectdata *conn, struct http_conn *httpc) { nghttp2_settings_entry *iv = httpc->local_settings; + DEBUGASSERT(conn->data); iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = (uint32_t)Curl_multi_max_concurrent_streams(conn->data->multi); + iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi); iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; iv[1].value = HTTP2_HUGE_WINDOW_SIZE; @@ -1257,9 +1220,7 @@ static CURLcode http2_init(struct connectdata *conn) /* nghttp2_on_header_callback */ nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header); -#ifndef CURL_DISABLE_VERBOSE_STRINGS nghttp2_session_callbacks_set_error_callback(callbacks, error_callback); -#endif /* The nghttp2 session is not yet setup, do it */ rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); @@ -1457,7 +1418,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, } else if(httpc->error_code != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, http2_strerror(httpc->error_code), + stream->stream_id, nghttp2_strerror(httpc->error_code), httpc->error_code); *err = CURLE_HTTP2_STREAM; return -1; @@ -1594,8 +1555,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, return ncopy; } - H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n", - data, stream->stream_id)); + H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n", + data, stream->stream_id, + nghttp2_session_get_local_window_size(httpc->h2), + nghttp2_session_get_stream_local_window_size(httpc->h2, + stream->stream_id) + )); if((data->state.drain) && stream->memlen) { H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", @@ -1626,7 +1591,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, stream->pausedata += nread; stream->pauselen -= nread; - infof(data, "%zd data bytes written\n", nread); if(stream->pauselen == 0) { H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); @@ -2264,7 +2228,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn, } } -#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, HTTP2_HUGE_WINDOW_SIZE); if(rv != 0) { @@ -2272,7 +2235,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn, nghttp2_strerror(rv), rv); return CURLE_HTTP2; } -#endif /* we are going to copy mem to httpc->inbuf. This is required since mem is part of buffer pointed by stream->mem, and callbacks @@ -2330,6 +2292,51 @@ CURLcode Curl_http2_switched(struct connectdata *conn, return CURLE_OK; } +CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) +{ + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + /* if it isn't HTTP/2, we're done */ + if(!data->conn->proto.httpc.h2) + return CURLE_OK; +#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + else { + struct HTTP *stream = data->req.protop; + struct http_conn *httpc = &data->conn->proto.httpc; + uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE; + int rv = nghttp2_session_set_local_window_size(httpc->h2, + NGHTTP2_FLAG_NONE, + stream->stream_id, + window); + if(rv) { + failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + /* make sure the window update gets sent */ + rv = h2_session_send(data, httpc->h2); + if(rv) + return CURLE_SEND_ERROR; + + DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n", + window, stream->stream_id)); + +#ifdef DEBUGBUILD + { + /* read out the stream local window again */ + uint32_t window2 = + nghttp2_session_get_stream_local_window_size(httpc->h2, + stream->stream_id); + DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n", + window2, stream->stream_id)); + } +#endif + } +#endif + return CURLE_OK; +} + CURLcode Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, bool exclusive) diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h index 12d36eef9b..1989aff826 100644 --- a/libs/libcurl/src/http2.h +++ b/libs/libcurl/src/http2.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -58,6 +58,7 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent, void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child); void Curl_http2_cleanup_dependencies(struct Curl_easy *data); +CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause); /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ bool Curl_h2_http_1_1_error(struct connectdata *conn); @@ -74,6 +75,7 @@ bool Curl_h2_http_1_1_error(struct connectdata *conn); #define Curl_http2_add_child(x, y, z) #define Curl_http2_remove_child(x, y) #define Curl_http2_cleanup_dependencies(x) +#define Curl_http2_stream_pause(x, y) #define Curl_h2_http_1_1_error(x) 0 #endif diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index 236ec4279b..f0001fee06 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ <string>se.haxx.curl.libcurl</string> <key>CFBundleVersion</key> - <string>7.68.0</string> + <string>7.69.0</string> <key>CFBundleName</key> <string>libcurl</string> @@ -27,9 +27,9 @@ <string>????</string> <key>CFBundleShortVersionString</key> - <string>libcurl 7.68.0</string> + <string>libcurl 7.69.0</string> <key>CFBundleGetInfoString</key> - <string>libcurl.plist 7.68.0</string> + <string>libcurl.plist 7.69.0</string> </dict> </plist> diff --git a/libs/libcurl/src/llist.c b/libs/libcurl/src/llist.c index f8769c2af8..e7c6f51dc7 100644 --- a/libs/libcurl/src/llist.c +++ b/libs/libcurl/src/llist.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -144,54 +144,3 @@ Curl_llist_count(struct curl_llist *list) { return list->size; } - -/* - * @unittest: 1300 - */ -void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, - struct curl_llist *to_list, - struct curl_llist_element *to_e) -{ - /* Remove element from list */ - if(e == NULL || list->size == 0) - return; - - if(e == list->head) { - list->head = e->next; - - if(list->head == NULL) - list->tail = NULL; - else - e->next->prev = NULL; - } - else { - e->prev->next = e->next; - if(!e->next) - list->tail = e->prev; - else - e->next->prev = e->prev; - } - - --list->size; - - /* Add element to to_list after to_e */ - if(to_list->size == 0) { - to_list->head = e; - to_list->head->prev = NULL; - to_list->head->next = NULL; - to_list->tail = e; - } - else { - e->next = to_e->next; - e->prev = to_e; - if(to_e->next) { - to_e->next->prev = e; - } - else { - to_list->tail = e; - } - to_e->next = e; - } - - ++to_list->size; -} diff --git a/libs/libcurl/src/llist.h b/libs/libcurl/src/llist.h index a5e2ecbfb4..0178c42598 100644 --- a/libs/libcurl/src/llist.h +++ b/libs/libcurl/src/llist.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -47,7 +47,4 @@ void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, void *); size_t Curl_llist_count(struct curl_llist *); void Curl_llist_destroy(struct curl_llist *, void *); -void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, - struct curl_llist *, struct curl_llist_element *); - #endif /* HEADER_CURL_LLIST_H */ diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c index bbf8975081..38f1b2bc96 100644 --- a/libs/libcurl/src/md4.c +++ b/libs/libcurl/src/md4.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -29,10 +29,16 @@ #ifdef USE_OPENSSL #include <openssl/opensslconf.h> -#endif +#endif /* USE_OPENSSL */ + #ifdef USE_MBEDTLS #include <mbedtls/config.h> +#include <mbedtls/version.h> + +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) + #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS #endif +#endif /* USE_MBEDTLS */ #if defined(USE_GNUTLS_NETTLE) @@ -65,10 +71,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) #include <gcrypt.h> #include "curl_memory.h" + /* The last #include file should be: */ #include "memdebug.h" -typedef struct gcry_md_hd_t MD4_CTX; +typedef gcry_md_hd_t MD4_CTX; static void MD4_Init(MD4_CTX *ctx) { @@ -82,52 +89,41 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) static void MD4_Final(unsigned char *result, MD4_CTX *ctx) { - memcpy(result, gcry_md_read(ctx, 0), MD4_DIGEST_LENGTH); - gcry_md_close(ctx); + memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH); + gcry_md_close(*ctx); } #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4) /* When OpenSSL is available we use the MD4-functions from OpenSSL */ #include <openssl/md4.h> -#elif defined(USE_SECTRANSP) +#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) #include <CommonCrypto/CommonDigest.h> #include "curl_memory.h" + /* The last #include file should be: */ #include "memdebug.h" -typedef struct { - void *data; - unsigned long size; -} MD4_CTX; +typedef CC_MD4_CTX MD4_CTX; static void MD4_Init(MD4_CTX *ctx) { - ctx->data = NULL; - ctx->size = 0; + (void)CC_MD4_Init(ctx); } static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) { - if(ctx->data == NULL) { - ctx->data = malloc(size); - if(ctx->data != NULL) { - memcpy(ctx->data, data, size); - ctx->size = size; - } - } + (void)CC_MD4_Update(ctx, data, (CC_LONG)size); } static void MD4_Final(unsigned char *result, MD4_CTX *ctx) { - if(ctx->data != NULL) { - (void)CC_MD4(ctx->data, (CC_LONG) ctx->size, result); - - Curl_safefree(ctx->data); - ctx->size = 0; - } + (void)CC_MD4_Final(result, ctx); } #elif defined(USE_WIN32_CRYPTO) @@ -135,7 +131,8 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) #include <wincrypt.h> #include "curl_memory.h" - /* The last #include file should be: */ + +/* The last #include file should be: */ #include "memdebug.h" typedef struct { @@ -156,7 +153,7 @@ static void MD4_Init(MD4_CTX *ctx) static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) { - CryptHashData(ctx->hHash, data, (unsigned int) size, 0); + CryptHashData(ctx->hHash, (BYTE *)data, (unsigned int) size, 0); } static void MD4_Final(unsigned char *result, MD4_CTX *ctx) @@ -179,6 +176,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) #include <mbedtls/md4.h> #include "curl_memory.h" + /* The last #include file should be: */ #include "memdebug.h" @@ -207,7 +205,11 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) static void MD4_Final(unsigned char *result, MD4_CTX *ctx) { if(ctx->data != NULL) { +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) mbedtls_md4(ctx->data, ctx->size, result); +#else + (void) mbedtls_md4_ret(ctx->data, ctx->size, result); +#endif Curl_safefree(ctx->data); ctx->size = 0; @@ -505,9 +507,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) #endif /* CRYPTO LIBS */ -void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) +void Curl_md4it(unsigned char *output, const unsigned char *input, + const size_t len) { MD4_CTX ctx; + MD4_Init(&ctx); MD4_Update(&ctx, input, curlx_uztoui(len)); MD4_Final(output, &ctx); diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c index 2b81ca455a..3f601b3a42 100644 --- a/libs/libcurl/src/md5.c +++ b/libs/libcurl/src/md5.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -30,6 +30,14 @@ #include "curl_hmac.h" #include "warnless.h" +#ifdef USE_MBEDTLS +#include <mbedtls/version.h> + +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) + #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS +#endif +#endif /* USE_MBEDTLS */ + #if defined(USE_GNUTLS_NETTLE) #include <nettle/md5.h> @@ -51,7 +59,7 @@ static void MD5_Update(MD5_CTX *ctx, md5_update(ctx, inputLen, input); } -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { md5_digest(ctx, 16, digest); } @@ -77,7 +85,7 @@ static void MD5_Update(MD5_CTX *ctx, gcry_md_write(*ctx, input, inputLen); } -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { memcpy(digest, gcry_md_read(*ctx, 0), 16); gcry_md_close(*ctx); @@ -90,6 +98,46 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) /* The last #include file should be: */ #include "memdebug.h" +#elif defined(USE_MBEDTLS) + +#include <mbedtls/md5.h> + +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +typedef mbedtls_md5_context MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_md5_starts(ctx); +#else + (void) mbedtls_md5_starts_ret(ctx); +#endif +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *data, + unsigned int length) +{ +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_md5_update(ctx, data, length); +#else + (void) mbedtls_md5_update_ret(ctx, data, length); +#endif +} + +static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) +{ +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_md5_finish(ctx, digest); +#else + (void) mbedtls_md5_finish_ret(ctx, digest); +#endif +} + #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ @@ -119,12 +167,12 @@ static void MD5_Update(MD5_CTX *ctx, CC_MD5_Update(ctx, input, inputLen); } -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { CC_MD5_Final(digest, ctx); } -#elif defined(WIN32) && !defined(CURL_WINDOWS_APP) +#elif defined(USE_WIN32_CRYPTO) #include <wincrypt.h> #include "curl_memory.h" @@ -151,7 +199,7 @@ static void MD5_Update(MD5_CTX *ctx, CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); } -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { unsigned long length = 0; CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); @@ -164,7 +212,9 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) } #else + /* When no other crypto library is available we use this code segment */ + /* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). @@ -513,12 +563,13 @@ const MD5_params Curl_DIGEST_MD5[] = { /* * @unittest: 1601 */ -void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ - const unsigned char *input) +void Curl_md5it(unsigned char *outbuffer, const unsigned char *input, + const size_t len) { MD5_CTX ctx; + MD5_Init(&ctx); - MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + MD5_Update(&ctx, input, curlx_uztoui(len)); MD5_Final(outbuffer, &ctx); } diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index 081e51e508..2571287c6a 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 diff --git a/libs/libcurl/src/mime.h b/libs/libcurl/src/mime.h index 3241fdc1f7..4312125796 100644 --- a/libs/libcurl/src/mime.h +++ b/libs/libcurl/src/mime.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 diff --git a/libs/libcurl/src/mk-ca-bundle.pl b/libs/libcurl/src/mk-ca-bundle.pl index 33977f3226..09e8e5b9bb 100644 --- a/libs/libcurl/src/mk-ca-bundle.pl +++ b/libs/libcurl/src/mk-ca-bundle.pl @@ -6,7 +6,7 @@ # * | (__| |_| | _ <| |___ # * \___|\___/|_| \_\_____| # * -# * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. +# * Copyright (C) 1998 - 2020, 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 @@ -38,6 +38,7 @@ use warnings; use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w); use List::Util; use Text::Wrap; +use Time::Local; my $MOD_SHA = "Digest::SHA"; eval "require $MOD_SHA"; if ($@) { @@ -421,6 +422,8 @@ my $certnum = 0; my $skipnum = 0; my $start_of_cert = 0; my @precert; +my $cka_value; +my $valid = 1; open(TXT,"$txt") or die "Couldn't open $txt: $!\n"; while (<TXT>) { @@ -435,6 +438,7 @@ while (<TXT>) { } elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After |Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) { push @precert, $_; + $valid = 1; next; } elsif(/^#|^\s*$/) { @@ -443,6 +447,49 @@ while (<TXT>) { } chomp; + # Example: + # CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL + # \062\060\060\066\061\067\060\060\060\060\060\060\132 + # END + + if (/^CKA_NSS_SERVER_DISTRUST_AFTER (CK_BBOOL CK_FALSE|MULTILINE_OCTAL)/) { + if($1 eq "MULTILINE_OCTAL") { + my @timestamp; + while (<TXT>) { + last if (/^END/); + chomp; + my @octets = split(/\\/); + shift @octets; + for (@octets) { + push @timestamp, chr(oct); + } + } + # A trailing Z in the timestamp signifies UTC + if($timestamp[12] ne "Z") { + report "distrust date stamp is not using UTC"; + } + # Example date: 200617000000Z + # Means 2020-06-17 00:00:00 UTC + my $distrustat = + timegm($timestamp[10] . $timestamp[11], # second + $timestamp[8] . $timestamp[9], # minute + $timestamp[6] . $timestamp[7], # hour + $timestamp[4] . $timestamp[5], # day + ($timestamp[2] . $timestamp[3]) - 1, # month + "20" . $timestamp[0] . $timestamp[1]); # year + if(time >= $distrustat) { + # not trusted anymore + $skipnum++; + report "Skipping: $caname is not trusted anymore" if ($opt_v); + $valid = 0; + } + else { + # still trusted + } + } + next; + } + # this is a match for the start of a certificate if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) { $start_of_cert = 1 @@ -452,21 +499,18 @@ while (<TXT>) { } my %trust_purposes_by_level; if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) { - my $data; + $cka_value=""; while (<TXT>) { last if (/^END/); chomp; my @octets = split(/\\/); shift @octets; for (@octets) { - $data .= chr(oct); + $cka_value .= chr(oct); } } - # scan forwards until the trust part - while (<TXT>) { - last if (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/); - chomp; - } + } + if(/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/ && $valid) { # now scan the trust part to determine how we should trust this cert while (<TXT>) { last if (/^#/); @@ -485,6 +529,8 @@ while (<TXT>) { $skipnum ++; report "Skipping: $caname" if ($opt_v); } else { + my $data = $cka_value; + $cka_value = ""; my $encoded = MIME::Base64::encode_base64($data, ''); $encoded =~ s/(.{1,${opt_w}})/$1\n/g; my $pem = "-----BEGIN CERTIFICATE-----\n" diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index 6d819b4aaa..cef2805c8e 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -47,6 +47,7 @@ #include "http_proxy.h" #include "http2.h" #include "socketpair.h" +#include "socks.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -369,6 +370,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ /* -1 means it not set by user, use the default value */ multi->maxconnects = -1; + multi->max_concurrent_streams = 100; + multi->ipv6_works = Curl_ipv6works(NULL); #ifdef ENABLE_WAKEUP if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) { @@ -590,6 +593,9 @@ static CURLcode multi_done(struct Curl_easy *data, detach_connnection(data); if(CONN_INUSE(conn)) { /* Stop if still used. */ + /* conn->data must not remain pointing to this transfer since it is going + away! Find another to own it! */ + conn->data = conn->easyq.head->ptr; CONN_UNLOCK(data); DEBUGF(infof(data, "Connection still in use %zu, " "no more multi_done now!\n", @@ -725,8 +731,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, we don't leave a half-baked one around */ if(easy_owns_conn) { - /* multi_done() clears the conn->data field to lose the association - between the easy handle and the connection + /* multi_done() clears the association between the easy handle and the + connection. Note that this ignores the return code simply because there's nothing really useful to do with it anyway! */ @@ -851,6 +857,9 @@ static int waitconnect_getsock(struct connectdata *conn, return Curl_ssl_getsock(conn, sock); #endif + if(SOCKS_STATE(conn->cnnct.state)) + return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET); + for(i = 0; i<2; i++) { if(conn->tempsock[i] != CURL_SOCKET_BAD) { sock[s] = conn->tempsock[i]; @@ -1048,6 +1057,9 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi, if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; + if(timeout_ms < 0) + return CURLM_BAD_FUNCTION_ARGUMENT; + /* Count up how many fds we have from the multi handle */ data = multi->easyp; while(data) { @@ -1187,7 +1199,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi, data from it until it receives an error (except EINTR). In normal cases it will get EAGAIN or EWOULDBLOCK when there is no more data, breaking the loop. */ - if(sread(multi->wakeup_pair[0], buf, sizeof(buf)) < 0) { + if(sread(multi->wakeup_pair[0], buf, sizeof(buf)) <= 0) { #ifndef USE_WINSOCK if(EINTR == SOCKERRNO) continue; @@ -2183,8 +2195,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } } } - else if(comeback) - rc = CURLM_CALL_MULTI_PERFORM; + else if(comeback) { + /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer + won't get stuck on this transfer at the expense of other concurrent + transfers */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + rc = CURLM_OK; + } break; } @@ -2897,8 +2914,8 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, if(streams < 1) streams = 100; multi->max_concurrent_streams = - (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)? - (long)INITIAL_MAX_CONCURRENT_STREAMS : streams; + (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)? + INITIAL_MAX_CONCURRENT_STREAMS : (unsigned int)streams; } break; default: @@ -3340,8 +3357,8 @@ void Curl_multi_dump(struct Curl_multi *multi) } #endif -size_t Curl_multi_max_concurrent_streams(struct Curl_multi *multi) +unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi) { - return multi ? ((size_t)multi->max_concurrent_streams ? - (size_t)multi->max_concurrent_streams : 100) : 0; + DEBUGASSERT(multi); + return multi->max_concurrent_streams; } diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h index 0bf09e6bb5..91eca16c4a 100644 --- a/libs/libcurl/src/multihandle.h +++ b/libs/libcurl/src/multihandle.h @@ -119,11 +119,6 @@ struct Curl_multi { same actual socket) */ struct curl_hash sockhash; - /* multiplexing wanted */ - bool multiplexing; - - bool recheckstate; /* see Curl_multi_connchanged */ - /* Shared connection cache (bundles)*/ struct conncache conn_cache; @@ -141,13 +136,17 @@ struct Curl_multi { void *timer_userp; struct curltime timer_lastcall; /* the fixed time for the timeout for the previous callback */ - bool in_callback; /* true while executing a callback */ - long max_concurrent_streams; /* max concurrent streams client to support */ + unsigned int max_concurrent_streams; #ifdef ENABLE_WAKEUP curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup 0 is used for read, 1 is used for write */ #endif + /* multiplexing wanted */ + bool multiplexing; + bool recheckstate; /* see Curl_multi_connchanged */ + bool in_callback; /* true while executing a callback */ + bool ipv6_works; }; #endif /* HEADER_CURL_MULTIHANDLE_H */ diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h index 75025232c4..bde755ee0f 100644 --- a/libs/libcurl/src/multiif.h +++ b/libs/libcurl/src/multiif.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -90,9 +90,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, struct connectdata *conn); -/* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option - * If not specified or 0, default would be 100 - */ -size_t Curl_multi_max_concurrent_streams(struct Curl_multi *multi); +/* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */ +unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi); #endif /* HEADER_CURL_MULTIIF_H */ diff --git a/libs/libcurl/src/rename.c b/libs/libcurl/src/rename.c new file mode 100644 index 0000000000..bb170d3cc7 --- /dev/null +++ b/libs/libcurl/src/rename.c @@ -0,0 +1,62 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2020, 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. + * + ***************************************************************************/ + +#include "rename.h" + +#include "curl_setup.h" + +#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \ + defined(USE_ALTSVC) + +#include "timeval.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* return 0 on success, 1 on error */ +int Curl_rename(const char *oldpath, const char *newpath) +{ +#ifdef WIN32 + /* rename() on Windows doesn't overwrite, so we can't use it here. + MoveFileExA() will overwrite and is usually atomic, however it fails + when there are open handles to the file. */ + const int max_wait_ms = 1000; + struct curltime start = Curl_now(); + for(;;) { + timediff_t diff; + if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) + break; + diff = Curl_timediff(Curl_now(), start); + if(diff < 0 || diff > max_wait_ms) + return 1; + Sleep(1); + } +#else + if(rename(oldpath, newpath)) + return 1; +#endif + return 0; +} + +#endif diff --git a/libs/libcurl/src/rename.h b/libs/libcurl/src/rename.h new file mode 100644 index 0000000000..d7442c8447 --- /dev/null +++ b/libs/libcurl/src/rename.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CURL_RENAME_H +#define HEADER_CURL_RENAME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2020, 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. + * + ***************************************************************************/ + +int Curl_rename(const char *oldpath, const char *newpath); + +#endif /* HEADER_CURL_RENAME_H */ diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index 2de503d370..b372efff10 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -53,9 +53,6 @@ /* Convenience local macros */ #define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv) -int Curl_ack_eintr = 0; -#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR) - /* * Internal function used for waiting a specific amount of ms * in Curl_socket_check() and Curl_poll() when no file descriptor @@ -74,13 +71,6 @@ int Curl_ack_eintr = 0; */ int Curl_wait_ms(int timeout_ms) { -#if !defined(MSDOS) && !defined(USE_WINSOCK) -#ifndef HAVE_POLL_FINE - struct timeval pending_tv; -#endif - struct curltime initial_tv; - int pending_ms; -#endif int r = 0; if(!timeout_ms) @@ -94,28 +84,16 @@ int Curl_wait_ms(int timeout_ms) #elif defined(USE_WINSOCK) Sleep(timeout_ms); #else - pending_ms = timeout_ms; - initial_tv = Curl_now(); - do { - int error; #if defined(HAVE_POLL_FINE) - r = poll(NULL, 0, pending_ms); + r = poll(NULL, 0, timeout_ms); #else - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; + { + struct timeval pending_tv; + pending_tv.tv_sec = timeout_ms / 1000; + pending_tv.tv_usec = (timeout_ms % 1000) * 1000; r = select(0, NULL, NULL, NULL, &pending_tv); + } #endif /* HAVE_POLL_FINE */ - if(r != -1) - break; - error = SOCKERRNO; - if(error && ERROR_NOT_EINTR(error)) - break; - pending_ms = timeout_ms - ELAPSED_MS(); - if(pending_ms <= 0) { - r = 0; /* Simulate a "call timed out" case */ - break; - } - } while(r == -1); #endif /* USE_WINSOCK */ if(r) r = -1; @@ -158,7 +136,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ fd_set fds_err; curl_socket_t maxfd; #endif - struct curltime initial_tv = {0, 0}; int pending_ms = 0; int r; int ret; @@ -183,7 +160,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ if(timeout_ms > 0) { pending_ms = (int)timeout_ms; - initial_tv = Curl_now(); } #ifdef HAVE_POLL_FINE @@ -208,26 +184,11 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ num++; } - do { - int error; - if(timeout_ms < 0) - pending_ms = -1; - else if(!timeout_ms) - pending_ms = 0; - r = poll(pfd, num, pending_ms); - if(r != -1) - break; - error = SOCKERRNO; - if(error && ERROR_NOT_EINTR(error)) - break; - if(timeout_ms > 0) { - pending_ms = (int)(timeout_ms - ELAPSED_MS()); - if(pending_ms <= 0) { - r = 0; /* Simulate a "call timed out" case */ - break; - } - } - } while(r == -1); + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(pfd, num, pending_ms); if(r < 0) return -1; @@ -290,61 +251,45 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; - do { - int error; - if(timeout_ms > 0) { - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; - } - else if(!timeout_ms) { - pending_tv.tv_sec = 0; - pending_tv.tv_usec = 0; - } + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } - /* WinSock select() must not be called with an fd_set that contains zero - fd flags, or it will return WSAEINVAL. But, it also can't be called - with no fd_sets at all! From the documentation: + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: - Any two of the parameters, readfds, writefds, or exceptfds, can be - given as null. At least one must be non-null, and any non-null - descriptor set must contain at least one handle to a socket. + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. - We know that we have at least one bit set in at least two fd_sets in - this case, but we may have no bits set in either fds_read or fd_write, - so check for that and handle it. Luckily, with WinSock, we can _also_ - ask how many bits are set on an fd_set. + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. - It is unclear why WinSock doesn't just handle this for us instead of - calling this an error. + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. - Note also that WinSock ignores the first argument, so we don't worry - about the fact that maxfd is computed incorrectly with WinSock (since - curl_socket_t is unsigned in such cases and thus -1 is the largest - value). - */ + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ #ifdef USE_WINSOCK - r = select((int)maxfd + 1, - fds_read.fd_count ? &fds_read : NULL, - fds_write.fd_count ? &fds_write : NULL, - &fds_err, ptimeout); + r = select((int)maxfd + 1, + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + &fds_err, ptimeout); #else - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); #endif - if(r != -1) - break; - error = SOCKERRNO; - if(error && ERROR_NOT_EINTR(error)) - break; - if(timeout_ms > 0) { - pending_ms = (int)(timeout_ms - ELAPSED_MS()); - if(pending_ms <= 0) { - r = 0; /* Simulate a "call timed out" case */ - break; - } - } - } while(r == -1); - if(r < 0) return -1; if(r == 0) @@ -399,7 +344,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) fd_set fds_err; curl_socket_t maxfd; #endif - struct curltime initial_tv = {0, 0}; bool fds_none = TRUE; unsigned int i; int pending_ms = 0; @@ -425,31 +369,15 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) if(timeout_ms > 0) { pending_ms = timeout_ms; - initial_tv = Curl_now(); } #ifdef HAVE_POLL_FINE - do { - int error; - if(timeout_ms < 0) - pending_ms = -1; - else if(!timeout_ms) - pending_ms = 0; - r = poll(ufds, nfds, pending_ms); - if(r != -1) - break; - error = SOCKERRNO; - if(error && ERROR_NOT_EINTR(error)) - break; - if(timeout_ms > 0) { - pending_ms = (int)(timeout_ms - ELAPSED_MS()); - if(pending_ms <= 0) { - r = 0; /* Simulate a "call timed out" case */ - break; - } - } - } while(r == -1); + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(ufds, nfds, pending_ms); if(r < 0) return -1; @@ -502,42 +430,27 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; - do { - int error; - if(timeout_ms > 0) { - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; - } - else if(!timeout_ms) { - pending_tv.tv_sec = 0; - pending_tv.tv_usec = 0; - } + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } #ifdef USE_WINSOCK - r = select((int)maxfd + 1, - /* WinSock select() can't handle fd_sets with zero bits set, so - don't give it such arguments. See the comment about this in - Curl_check_socket(). - */ - fds_read.fd_count ? &fds_read : NULL, - fds_write.fd_count ? &fds_write : NULL, - fds_err.fd_count ? &fds_err : NULL, ptimeout); + r = select((int)maxfd + 1, + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, ptimeout); #else - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); #endif - if(r != -1) - break; - error = SOCKERRNO; - if(error && ERROR_NOT_EINTR(error)) - break; - if(timeout_ms > 0) { - pending_ms = timeout_ms - ELAPSED_MS(); - if(pending_ms <= 0) { - r = 0; /* Simulate a "call timed out" case */ - break; - } - } - } while(r == -1); if(r < 0) return -1; diff --git a/libs/libcurl/src/select.h b/libs/libcurl/src/select.h index 687ab164c4..ec3021aac2 100644 --- a/libs/libcurl/src/select.h +++ b/libs/libcurl/src/select.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -75,20 +75,12 @@ struct pollfd int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, time_t timeout_ms); - #define SOCKET_READABLE(x,z) \ Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, (time_t)z) #define SOCKET_WRITABLE(x,z) \ Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, (time_t)z) int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); - -/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, - * EINTR condition is honored and function might exit early without - * awaiting full timeout. Otherwise EINTR will be ignored and full - * timeout will elapse. */ -extern int Curl_ack_eintr; - int Curl_wait_ms(int timeout_ms); #ifdef TPF diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index 6c38b04b23..6ef47aa801 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -43,6 +43,7 @@ #include "strerror.h" #include "select.h" #include "strdup.h" +#include "http2.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -501,6 +502,9 @@ static CURLcode pausewrite(struct Curl_easy *data, unsigned int i; bool newtype = TRUE; + /* If this transfers over HTTP/2, pause the stream! */ + Curl_http2_stream_pause(data, TRUE); + if(s->tempcount) { for(i = 0; i< s->tempcount; i++) { if(s->tempwrite[i].type == type) { @@ -529,6 +533,8 @@ static CURLcode pausewrite(struct Curl_easy *data, /* update the pointer and the size */ s->tempwrite[i].buf = newptr; s->tempwrite[i].len = newlen; + + len = newlen; /* for the debug output below */ } else { dupl = Curl_memdup(ptr, len); @@ -692,19 +698,20 @@ CURLcode Curl_read_plain(curl_socket_t sockfd, ssize_t nread = sread(sockfd, buf, bytesfromsocket); if(-1 == nread) { - int err = SOCKERRNO; - int return_error; + const int err = SOCKERRNO; + const bool return_error = #ifdef USE_WINSOCK - return_error = WSAEWOULDBLOCK == err; + WSAEWOULDBLOCK == err #else - return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err; + EWOULDBLOCK == err || EAGAIN == err || EINTR == err #endif + ; + *n = 0; /* no data returned */ if(return_error) return CURLE_AGAIN; return CURLE_RECV_ERROR; } - /* we only return number of bytes read when we return OK */ *n = nread; return CURLE_OK; } diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 5f88ad3afd..2e494a6df9 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -2288,7 +2288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSH_KEYFUNCTION: /* setting to NULL is fine since the ssh.c functions themselves will - then rever to use the internal default */ + then revert to use the internal default */ data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); break; @@ -2391,6 +2391,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* Set the list of mail recipients */ data->set.mail_rcpt = va_arg(param, struct curl_slist *); break; + case CURLOPT_MAIL_RCPT_ALLLOWFAILS: + /* allow RCPT TO command to fail for some recipients */ + data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; #endif case CURLOPT_SASL_AUTHZID: diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c index bcaaeae308..97214182be 100644 --- a/libs/libcurl/src/sha256.c +++ b/libs/libcurl/src/sha256.c @@ -5,7 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Florin Petriuc, <petriuc.florin@gmail.com> + * Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com> + * Copyright (C) 2018 - 2020, 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 @@ -35,16 +36,135 @@ #define USE_OPENSSL_SHA256 #endif +#endif /* USE_OPENSSL */ + +#ifdef USE_MBEDTLS +#include <mbedtls/version.h> + +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) + #define HAS_RESULT_CODE_BASED_FUNCTIONS #endif +#endif /* USE_MBEDTLS */ + +/* Please keep the SSL backend-specific #if branches in this order: + * + * 1. USE_OPENSSL + * 2. USE_GNUTLS_NETTLE + * 3. USE_GNUTLS + * 4. USE_MBEDTLS + * 5. USE_COMMON_CRYPTO + * 6. USE_WIN32_CRYPTO + * + * This ensures that the same SSL branch gets activated throughout this source + * file even if multiple backends are enabled at the same time. + */ + +#if defined(USE_OPENSSL_SHA256) -#ifdef USE_OPENSSL_SHA256 /* When OpenSSL is available we use the SHA256-function from OpenSSL */ #include <openssl/sha.h> + +#elif defined(USE_GNUTLS_NETTLE) + +#include <nettle/sha.h> + +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct sha256_ctx SHA256_CTX; + +static void SHA256_Init(SHA256_CTX *ctx) +{ + sha256_init(ctx); +} + +static void SHA256_Update(SHA256_CTX *ctx, + const unsigned char *data, + unsigned int length) +{ + sha256_update(ctx, length, data); +} + +static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +{ + sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); +} + +#elif defined(USE_GNUTLS) + +#include <gcrypt.h> + +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +typedef gcry_md_hd_t SHA256_CTX; + +static void SHA256_Init(SHA256_CTX *ctx) +{ + gcry_md_open(ctx, GCRY_MD_SHA256, 0); +} + +static void SHA256_Update(SHA256_CTX *ctx, + const unsigned char *data, + unsigned int length) +{ + gcry_md_write(*ctx, data, length); +} + +static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +{ + memcpy(digest, gcry_md_read(*ctx, 0), SHA256_DIGEST_LENGTH); + gcry_md_close(*ctx); +} + +#elif defined(USE_MBEDTLS) + +#include <mbedtls/sha256.h> + +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +typedef mbedtls_sha256_context SHA256_CTX; + +static void SHA256_Init(SHA256_CTX *ctx) +{ +#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_sha256_starts(ctx, 0); +#else + (void) mbedtls_sha256_starts_ret(ctx, 0); +#endif +} + +static void SHA256_Update(SHA256_CTX *ctx, + const unsigned char *data, + unsigned int length) +{ +#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_sha256_update(ctx, data, length); +#else + (void) mbedtls_sha256_update_ret(ctx, data, length); +#endif +} + +static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +{ +#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) + mbedtls_sha256_finish(ctx, digest); +#else + (void) mbedtls_sha256_finish_ret(ctx, digest); +#endif +} + #else /* When no other crypto library is available we use this code segment */ -/* ===== start - public domain SHA256 implementation ===== */ /* This is based on SHA256 implementation in LibTomCrypt that was released into * public domain by Tom St Denis. */ @@ -95,7 +215,8 @@ typedef struct sha256_state { unsigned long state[8], curlen; unsigned char buf[64]; } SHA256_CTX; -/* the K array */ + +/* The K array */ static const unsigned long K[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, @@ -111,6 +232,7 @@ static const unsigned long K[64] = { 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; + /* Various logical functions */ #define RORc(x, y) \ (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ @@ -123,13 +245,15 @@ static const unsigned long K[64] = { #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -/* compress 512-bits */ + +/* Compress 512-bits */ static int sha256_compress(struct sha256_state *md, unsigned char *buf) { unsigned long S[8], W[64]; int i; - /* copy state into S */ + + /* Copy state into S */ for(i = 0; i < 8; i++) { S[i] = md->state[i]; } @@ -141,6 +265,7 @@ static int sha256_compress(struct sha256_state *md, W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } + /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ @@ -153,12 +278,15 @@ static int sha256_compress(struct sha256_state *md, t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; } - /* feedback */ + + /* Feedback */ for(i = 0; i < 8; i++) { md->state[i] = md->state[i] + S[i]; } + return 0; } + /* Initialize the hash state */ static void SHA256_Init(struct sha256_state *md) { @@ -173,7 +301,8 @@ static void SHA256_Init(struct sha256_state *md) md->state[6] = 0x1F83D9ABUL; md->state[7] = 0x5BE0CD19UL; } -/** + +/* Process a block of memory though the hash @param md The hash state @param in The data to hash @@ -185,6 +314,7 @@ static int SHA256_Update(struct sha256_state *md, unsigned long inlen) { unsigned long n; + #define block_size 64 if(md->curlen > sizeof(md->buf)) return -1; @@ -210,9 +340,11 @@ static int SHA256_Update(struct sha256_state *md, } } } + return 0; } -/** + +/* Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (32 bytes) @@ -222,13 +354,17 @@ static int SHA256_Final(unsigned char *out, struct sha256_state *md) { int i; + if(md->curlen >= sizeof(md->buf)) return -1; - /* increase the length of the message */ + + /* Increase the length of the message */ md->length += md->curlen * 8; - /* append the '1' bit */ + + /* Append the '1' bit */ md->buf[md->curlen++] = (unsigned char)0x80; - /* if the length is currently above 56 bytes we append zeros + + /* If the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ @@ -239,29 +375,44 @@ static int SHA256_Final(unsigned char *out, sha256_compress(md, md->buf); md->curlen = 0; } - /* pad up to 56 bytes of zeroes */ + + /* Pad up to 56 bytes of zeroes */ while(md->curlen < 56) { md->buf[md->curlen++] = (unsigned char)0; } - /* store length */ + + /* Store length */ WPA_PUT_BE64(md->buf + 56, md->length); sha256_compress(md, md->buf); - /* copy output */ + + /* Copy output */ for(i = 0; i < 8; i++) WPA_PUT_BE32(out + (4 * i), md->state[i]); + return 0; } -/* ===== end - public domain SHA256 implementation ===== */ -#endif +#endif /* CRYPTO LIBS */ -void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */ - const unsigned char *input) +/* + * Curl_sha256it() + * + * Generates a SHA256 hash for the given input data. + * + * Parameters: + * + * output [in/out] - The output buffer. + * input [in] - The input data. + * length [in] - The input length. + */ +void Curl_sha256it(unsigned char *output, const unsigned char *input, + const size_t length) { SHA256_CTX ctx; + SHA256_Init(&ctx); - SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); - SHA256_Final(outbuffer, &ctx); + SHA256_Update(&ctx, input, curlx_uztoui(length)); + SHA256_Final(output, &ctx); } #endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index 65220b0f68..e1872871dc 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -27,6 +27,9 @@ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism * RFC4954 SMTP Authentication * RFC5321 SMTP protocol + * RFC5890 Internationalized Domain Names for Applications (IDNA) + * RFC6531 SMTP Extension for Internationalized Email + * RFC6532 Internationalized Email Headers * RFC6749 OAuth 2.0 Authorization Framework * RFC8314 Use of TLS for Email Submission and Access * Draft SMTP URL Interface <draft-earhart-url-smtp-00.txt> @@ -101,6 +104,8 @@ static CURLcode smtp_setup_connection(struct connectdata *conn); static CURLcode smtp_parse_url_options(struct connectdata *conn); static CURLcode smtp_parse_url_path(struct connectdata *conn); static CURLcode smtp_parse_custom_request(struct connectdata *conn); +static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, + char **address, struct hostname *host); static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, const char *initresp); static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); @@ -481,13 +486,55 @@ static CURLcode smtp_perform_command(struct connectdata *conn) struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.protop; - /* Send the command */ - if(smtp->rcpt) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s", - smtp->custom && smtp->custom[0] != '\0' ? - smtp->custom : "VRFY", - smtp->rcpt->data); + if(smtp->rcpt) { + /* We notify the server we are sending UTF-8 data if a) it supports the + SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in + either the local address or host name parts. This is regardless of + whether the host name is encoded using IDN ACE */ + bool utf8 = FALSE; + + if((!smtp->custom) || (!smtp->custom[0])) { + char *address = NULL; + struct hostname host = { NULL, NULL, NULL, NULL }; + + /* Parse the mailbox to verify into the local address and host name + parts, converting the host name to an IDN A-label if necessary */ + result = smtp_parse_address(conn, smtp->rcpt->data, + &address, &host); + if(result) + return result; + + /* Establish whether we should report SMTPUTF8 to the server for this + mailbox as per RFC-6531 sect. 3.1 point 6 */ + utf8 = (conn->proto.smtpc.utf8_supported) && + ((host.encalloc) || (!Curl_is_ASCII_name(address)) || + (!Curl_is_ASCII_name(host.name))); + + /* Send the VRFY command (Note: The host name part may be absent when the + host is a local system) */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s", + address, + host.name ? "@" : "", + host.name ? host.name : "", + utf8 ? " SMTPUTF8" : ""); + + Curl_free_idnconverted_hostname(&host); + free(address); + } + else { + /* Establish whether we should report that we support SMTPUTF8 for EXPN + commands to the server as per RFC-6531 sect. 3.1 point 6 */ + utf8 = (conn->proto.smtpc.utf8_supported) && + (!strcmp(smtp->custom, "EXPN")); + + /* Send the custom recipient based command such as the EXPN command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom, + smtp->rcpt->data, + utf8 ? " SMTPUTF8" : ""); + } + } else + /* Send the non-recipient based command such as HELP */ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", smtp->custom && smtp->custom[0] != '\0' ? smtp->custom : "HELP"); @@ -512,22 +559,86 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; + /* We notify the server we are sending UTF-8 data if a) it supports the + SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in + either the local address or host name parts. This is regardless of + whether the host name is encoded using IDN ACE */ + bool utf8 = FALSE; + /* Calculate the FROM parameter */ - if(!data->set.str[STRING_MAIL_FROM]) + if(data->set.str[STRING_MAIL_FROM]) { + char *address = NULL; + struct hostname host = { NULL, NULL, NULL, NULL }; + + /* Parse the FROM mailbox into the local address and host name parts, + converting the host name to an IDN A-label if necessary */ + result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM], + &address, &host); + if(result) + return result; + + /* Establish whether we should report SMTPUTF8 to the server for this + mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */ + utf8 = (conn->proto.smtpc.utf8_supported) && + ((host.encalloc) || (!Curl_is_ASCII_name(address)) || + (!Curl_is_ASCII_name(host.name))); + + if(host.name) { + from = aprintf("<%s@%s>", address, host.name); + + Curl_free_idnconverted_hostname(&host); + } + else + /* An invalid mailbox was provided but we'll simply let the server worry + about that and reply with a 501 error */ + from = aprintf("<%s>", address); + + free(address); + } + else /* Null reverse-path, RFC-5321, sect. 3.6.3 */ from = strdup("<>"); - else if(data->set.str[STRING_MAIL_FROM][0] == '<') - from = aprintf("%s", data->set.str[STRING_MAIL_FROM]); - else - from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]); if(!from) return CURLE_OUT_OF_MEMORY; /* Calculate the optional AUTH parameter */ if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) { - if(data->set.str[STRING_MAIL_AUTH][0] != '\0') - auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); + if(data->set.str[STRING_MAIL_AUTH][0] != '\0') { + char *address = NULL; + struct hostname host = { NULL, NULL, NULL, NULL }; + + /* Parse the AUTH mailbox into the local address and host name parts, + converting the host name to an IDN A-label if necessary */ + result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH], + &address, &host); + if(result) { + free(from); + return result; + } + + /* Establish whether we should report SMTPUTF8 to the server for this + mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */ + if((!utf8) && (conn->proto.smtpc.utf8_supported) && + ((host.encalloc) || (!Curl_is_ASCII_name(address)) || + (!Curl_is_ASCII_name(host.name)))) + utf8 = TRUE; + + if(host.name) { + free(from); + from = aprintf("<%s@%s>", address, host.name); + + Curl_free_idnconverted_hostname(&host); + } + else + /* An invalid mailbox was provided but we'll simply let the server + worry about it */ + auth = aprintf("<%s>", address); + + free(address); + if(!from) + return CURLE_OUT_OF_MEMORY; + } else /* Empty AUTH, RFC-2554, sect. 5 */ auth = strdup("<>"); @@ -561,6 +672,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) if(result) { free(from); free(auth); + return result; } @@ -583,19 +695,33 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) } } + /* If the mailboxes in the FROM and AUTH parameters don't include a UTF-8 + based address then quickly scan through the recipient list and check if + any there do, as we need to correctly identify our support for SMTPUTF8 + in the envelope, as per RFC-6531 sect. 3.4 */ + if(conn->proto.smtpc.utf8_supported && !utf8) { + struct SMTP *smtp = data->req.protop; + struct curl_slist *rcpt = smtp->rcpt; + + while(rcpt && !utf8) { + /* Does the host name contain non-ASCII characters? */ + if(!Curl_is_ASCII_name(rcpt->data)) + utf8 = TRUE; + + rcpt = rcpt->next; + } + } + /* Send the MAIL command */ - if(!auth && !size) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, - "MAIL FROM:%s", from); - else if(auth && !size) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, - "MAIL FROM:%s AUTH=%s", from, auth); - else if(auth && size) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, - "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size); - else - result = Curl_pp_sendf(&conn->proto.smtpc.pp, - "MAIL FROM:%s SIZE=%s", from, size); + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s%s%s%s%s%s", + from, /* Mandatory */ + auth ? " AUTH=" : "", /* Optional on AUTH support */ + auth ? auth : "", /* */ + size ? " SIZE=" : "", /* Optional on SIZE support */ + size ? size : "", /* */ + utf8 ? " SMTPUTF8" /* Internationalised mailbox */ + : ""); /* included in our envelope */ free(from); free(auth); @@ -619,14 +745,28 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.protop; + char *address = NULL; + struct hostname host = { NULL, NULL, NULL, NULL }; + + /* Parse the recipient mailbox into the local address and host name parts, + converting the host name to an IDN A-label if necessary */ + result = smtp_parse_address(conn, smtp->rcpt->data, + &address, &host); + if(result) + return result; /* Send the RCPT TO command */ - if(smtp->rcpt->data[0] == '<') - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", - smtp->rcpt->data); + if(host.name) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address, + host.name); else - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", - smtp->rcpt->data); + /* An invalid mailbox was provided but we'll simply let the server worry + about that and reply with a 501 error */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address); + + Curl_free_idnconverted_hostname(&host); + free(address); + if(!result) state(conn, SMTP_RCPT); @@ -726,6 +866,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, else if(len >= 4 && !memcmp(line, "SIZE", 4)) smtpc->size_supported = TRUE; + /* Does the server support the UTF-8 capability? */ + else if(len >= 8 && !memcmp(line, "SMTPUTF8", 8)) + smtpc->utf8_supported = TRUE; + /* Does the server support authentication? */ else if(len >= 5 && !memcmp(line, "AUTH ", 5)) { smtpc->auth_supported = TRUE; @@ -915,25 +1059,53 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.protop; + bool is_smtp_err = FALSE; + bool is_smtp_blocking_err = FALSE; (void)instate; /* no use for this yet */ - if(smtpcode/100 != 2) { - failf(data, "RCPT failed: %d", smtpcode); - result = CURLE_SEND_ERROR; + is_smtp_err = (smtpcode/100 != 2) ? TRUE : FALSE; + + /* If there's multiple RCPT TO to be issued, it's possible to ignore errors + and proceed with only the valid addresses. */ + is_smtp_blocking_err = + (is_smtp_err && !data->set.mail_rcpt_allowfails) ? TRUE : FALSE; + + if(is_smtp_err) { + /* Remembering the last failure which we can report if all "RCPT TO" have + failed and we cannot proceed. */ + smtp->rcpt_last_error = smtpcode; + + if(is_smtp_blocking_err) { + failf(data, "RCPT failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } } else { + /* Some RCPT TO commands have succeeded. */ + smtp->rcpt_had_ok = TRUE; + } + + if(!is_smtp_blocking_err) { smtp->rcpt = smtp->rcpt->next; if(smtp->rcpt) /* Send the next RCPT TO command */ result = smtp_perform_rcpt_to(conn); else { - /* Send the DATA command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + /* We weren't able to issue a successful RCPT TO command while going + over recipients (potentially multiple). Sending back last error. */ + if(!smtp->rcpt_had_ok) { + failf(data, "RCPT failed: %d (last error)", smtp->rcpt_last_error); + result = CURLE_SEND_ERROR; + } + else { + /* Send the DATA command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); - if(!result) - state(conn, SMTP_DATA); + if(!result) + state(conn, SMTP_DATA); + } } } @@ -1287,6 +1459,12 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, /* Store the first recipient (or NULL if not specified) */ smtp->rcpt = data->set.mail_rcpt; + /* Track of whether we've successfully sent at least one RCPT TO command */ + smtp->rcpt_had_ok = FALSE; + + /* Track of the last error we've received by sending RCPT TO command */ + smtp->rcpt_last_error = 0; + /* Initial data character is the first character in line: it is implicitly preceded by a virtual CRLF. */ smtp->trailing_crlf = TRUE; @@ -1537,6 +1715,76 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn) return result; } +/*********************************************************************** + * + * smtp_parse_address() + * + * Parse the fully qualified mailbox address into a local address part and the + * host name, converting the host name to an IDN A-label, as per RFC-5890, if + * necessary. + * + * Parameters: + * + * conn [in] - The connection handle. + * fqma [in] - The fully qualified mailbox address (which may or + * may not contain UTF-8 characters). + * address [in/out] - A new allocated buffer which holds the local + * address part of the mailbox. This buffer must be + * free'ed by the caller. + * host [in/out] - The host name structure that holds the original, + * and optionally encoded, host name. + * Curl_free_idnconverted_hostname() must be called + * once the caller has finished with the structure. + * + * Returns CURLE_OK on success. + * + * Notes: + * + * Should a UTF-8 host name require conversion to IDN ACE and we cannot honor + * that convertion then we shall return success. This allow the caller to send + * the data to the server as a U-label (as per RFC-6531 sect. 3.2). + * + * If an mailbox '@' seperator cannot be located then the mailbox is considered + * to be either a local mailbox or an invalid mailbox (depending on what the + * calling function deems it to be) then the input will simply be returned in + * the address part with the host name being NULL. + */ +static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, + char **address, struct hostname *host) +{ + CURLcode result = CURLE_OK; + size_t length; + + /* Duplicate the fully qualified email address so we can manipulate it, + ensuring it doesn't contain the delimiters if specified */ + char *dup = strdup(fqma[0] == '<' ? fqma + 1 : fqma); + if(!dup) + return CURLE_OUT_OF_MEMORY; + + length = strlen(dup); + if(dup[length - 1] == '>') + dup[length - 1] = '\0'; + + /* Extract the host name from the addresss (if we can) */ + host->name = strpbrk(dup, "@"); + if(host->name) { + *host->name = '\0'; + host->name = host->name + 1; + + /* Attempt to convert the host name to IDN ACE */ + (void) Curl_idnconvert_hostname(conn, host); + + /* If Curl_idnconvert_hostname() fails then we shall attempt to continue + and send the host name using UTF-8 rather than as 7-bit ACE (which is + our preference) */ + } + + /* Extract the local address from the mailbox */ + *address = dup; + + return result; +} + CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) { /* When sending a SMTP payload we must detect CRLF. sequences making sure diff --git a/libs/libcurl/src/smtp.h b/libs/libcurl/src/smtp.h index 20fc081190..164a175d75 100644 --- a/libs/libcurl/src/smtp.h +++ b/libs/libcurl/src/smtp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2009 - 2020, 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 @@ -55,6 +55,9 @@ struct SMTP { curl_pp_transfer transfer; char *custom; /* Custom Request */ struct curl_slist *rcpt; /* Recipient list */ + bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on + total number of recipients) succeeded so far */ + int rcpt_last_error; /* The last error received for RCPT TO command */ size_t eob; /* Number of bytes of the EOB (End Of Body) that have been received so far */ bool trailing_crlf; /* Specifies if the tailing CRLF is present */ @@ -71,6 +74,8 @@ struct smtp_conn { bool tls_supported; /* StartTLS capability supported by server */ bool size_supported; /* If server supports SIZE extension according to RFC 1870 */ + bool utf8_supported; /* If server supports SMTPUTF8 extension according + to RFC 6531 */ bool auth_supported; /* AUTH capability supported by server */ }; diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index 6ae98184d1..0fb97e1e5d 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -37,18 +37,19 @@ #include "connect.h" #include "timeval.h" #include "socks.h" +#include "multiif.h" /* for getsock macros */ /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) /* * Helper read-from-socket functions. Does the same as Curl_read() but it * blocks until all bytes amount of buffersize will be read. No more, no less. * - * This is STUPID BLOCKING behaviour which we frown upon, but right now this - * is what we have... + * This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions. */ int Curl_blockread_all(struct connectdata *conn, /* connection data */ curl_socket_t sockfd, /* read from this socket */ @@ -94,6 +95,81 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ } return result; } +#endif + +#ifndef DEBUGBUILD +#define sxstate(x,y) socksstate(x,y) +#else +#define sxstate(x,y) socksstate(x,y, __LINE__) +#endif + + +/* always use this function to change state, to make debugging easier */ +static void socksstate(struct connectdata *conn, + enum connect_t state +#ifdef DEBUGBUILD + , int lineno +#endif +) +{ + enum connect_t oldstate = conn->cnnct.state; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* synced with the state list in urldata.h */ + static const char * const statename[] = { + "INIT", + "SOCKS_INIT", + "SOCKS_SEND", + "SOCKS_READ_INIT", + "SOCKS_READ", + "GSSAPI_INIT", + "AUTH_INIT", + "AUTH_SEND", + "AUTH_READ", + "REQ_INIT", + "RESOLVING", + "RESOLVED", + "RESOLVE_REMOTE", + "REQ_SEND", + "REQ_SENDING", + "REQ_READ", + "REQ_READ_MORE", + "DONE" + }; +#endif + + if(oldstate == state) + /* don't bother when the new state is the same as the old state */ + return; + + conn->cnnct.state = state; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + infof(conn->data, + "SXSTATE: %s => %s conn %p; line %d\n", + statename[oldstate], statename[conn->cnnct.state], conn, + lineno); +#endif +} + +int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock, + int sockindex) +{ + int rc = 0; + sock[0] = conn->sock[sockindex]; + switch(conn->cnnct.state) { + case CONNECT_RESOLVING: + case CONNECT_SOCKS_READ: + case CONNECT_AUTH_READ: + case CONNECT_REQ_READ: + case CONNECT_REQ_READ_MORE: + rc = GETSOCK_READSOCK(0); + break; + default: + rc = GETSOCK_WRITESOCK(0); + break; + } + return rc; +} /* * This function logs in to a SOCKS4 proxy and sends the specifics to the final @@ -110,62 +186,89 @@ CURLcode Curl_SOCKS4(const char *proxy_user, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn) + struct connectdata *conn, + bool *done) { const bool protocol4a = (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; -#define SOCKS4REQLEN 262 - unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user - id */ - CURLcode code; - curl_socket_t sock = conn->sock[sockindex]; + unsigned char *socksreq = &conn->cnnct.socksreq[0]; + CURLcode result; + curl_socket_t sockfd = conn->sock[sockindex]; struct Curl_easy *data = conn->data; + struct connstate *sx = &conn->cnnct; + struct Curl_dns_entry *dns = NULL; + ssize_t actualread; + ssize_t written; - if(Curl_timeleft(data, NULL, TRUE) < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(conn->bits.httpproxy) - infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", - protocol4a ? "a" : "", hostname, remote_port); - - (void)curlx_nonblock(sock, FALSE); + if(!SOCKS_STATE(sx->state) && !*done) + sxstate(conn, CONNECT_SOCKS_INIT); - infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); + switch(sx->state) { + case CONNECT_SOCKS_INIT: + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + protocol4a ? "a" : "", hostname, remote_port); - /* - * Compose socks4 request - * - * Request format - * - * +----+----+----+----+----+----+----+----+----+----+....+----+ - * | VN | CD | DSTPORT | DSTIP | USERID |NULL| - * +----+----+----+----+----+----+----+----+----+----+....+----+ - * # of bytes: 1 1 2 4 variable 1 - */ + infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); - socksreq[0] = 4; /* version (SOCKS4) */ - socksreq[1] = 1; /* connect */ - socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ - socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ - - /* DNS resolve only for SOCKS4, not SOCKS4a */ - if(!protocol4a) { - struct Curl_dns_entry *dns; - Curl_addrinfo *hp = NULL; - int rc; + /* + * Compose socks4 request + * + * Request format + * + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * | VN | CD | DSTPORT | DSTIP | USERID |NULL| + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * # of bytes: 1 1 2 4 variable 1 + */ - rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + socksreq[0] = 4; /* version (SOCKS4) */ + socksreq[1] = 1; /* connect */ + socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + + /* DNS resolve only for SOCKS4, not SOCKS4a */ + if(!protocol4a) { + enum resolve_t rc = + Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_PROXY; + else if(rc == CURLRESOLV_PENDING) { + sxstate(conn, CONNECT_RESOLVING); + infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname); + return CURLE_OK; + } + sxstate(conn, CONNECT_RESOLVED); + goto CONNECT_RESOLVED; + } - if(rc == CURLRESOLV_ERROR) - return CURLE_COULDNT_RESOLVE_PROXY; + /* socks4a doesn't resolve anything locally */ + sxstate(conn, CONNECT_REQ_INIT); + goto CONNECT_REQ_INIT; - if(rc == CURLRESOLV_PENDING) - /* ignores the return code, but 'dns' remains NULL on failure */ - (void)Curl_resolver_wait_resolv(conn, &dns); + case CONNECT_RESOLVING: + /* check if we have the name resolved by now */ + dns = Curl_fetch_addr(conn, hostname, (int)conn->port); + if(dns) { +#ifdef CURLRES_ASYNCH + conn->async.dns = dns; + conn->async.done = TRUE; +#endif + infof(data, "Hostname '%s' was found\n", hostname); + sxstate(conn, CONNECT_RESOLVED); + } + else { + result = Curl_resolv_check(data->conn, &dns); + /* stay in the state or error out */ + return result; + } + /* FALLTHROUGH */ + CONNECT_RESOLVED: + case CONNECT_RESOLVED: { + Curl_addrinfo *hp = NULL; + char buf[64]; /* * We cannot use 'hostent' as a struct that Curl_resolv() returns. It * returns a Curl_addrinfo pointer that may not always look the same. @@ -173,7 +276,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user, if(dns) hp = dns->addr; if(hp) { - char buf[64]; Curl_printable_address(hp, buf, sizeof(buf)); if(hp->ai_family == AF_INET) { @@ -189,7 +291,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user, } else { hp = NULL; /* fail! */ - failf(data, "SOCKS4 connection to %s not supported\n", buf); } @@ -201,149 +302,166 @@ CURLcode Curl_SOCKS4(const char *proxy_user, return CURLE_COULDNT_RESOLVE_HOST; } } - - /* - * This is currently not supporting "Identification Protocol (RFC1413)". - */ - socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ - if(proxy_user) { - size_t plen = strlen(proxy_user); - if(plen >= sizeof(socksreq) - 8) { - failf(data, "Too long SOCKS proxy name, can't use!\n"); - return CURLE_COULDNT_CONNECT; + /* FALLTHROUGH */ + CONNECT_REQ_INIT: + case CONNECT_REQ_INIT: + /* + * This is currently not supporting "Identification Protocol (RFC1413)". + */ + socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ + if(proxy_user) { + size_t plen = strlen(proxy_user); + if(plen >= sizeof(sx->socksreq) - 8) { + failf(data, "Too long SOCKS proxy name, can't use!\n"); + return CURLE_COULDNT_CONNECT; + } + /* copy the proxy name WITH trailing zero */ + memcpy(socksreq + 8, proxy_user, plen + 1); } - /* copy the proxy name WITH trailing zero */ - memcpy(socksreq + 8, proxy_user, plen + 1); - } - /* - * Make connection - */ - { - int result; - ssize_t actualread; - ssize_t written; - ssize_t hostnamelen = 0; - ssize_t packetsize = 9 + - strlen((char *)socksreq + 8); /* size including NUL */ - - /* If SOCKS4a, set special invalid IP address 0.0.0.x */ - if(protocol4a) { - socksreq[4] = 0; - socksreq[5] = 0; - socksreq[6] = 0; - socksreq[7] = 1; - /* If still enough room in buffer, also append hostname */ - hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ - if(packetsize + hostnamelen <= SOCKS4REQLEN) - strcpy((char *)socksreq + packetsize, hostname); - else - hostnamelen = 0; /* Flag: hostname did not fit in buffer */ + /* + * Make connection + */ + { + ssize_t packetsize = 9 + + strlen((char *)socksreq + 8); /* size including NUL */ + + /* If SOCKS4a, set special invalid IP address 0.0.0.x */ + if(protocol4a) { + ssize_t hostnamelen = 0; + socksreq[4] = 0; + socksreq[5] = 0; + socksreq[6] = 0; + socksreq[7] = 1; + /* append hostname */ + hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ + if(hostnamelen <= 255) + strcpy((char *)socksreq + packetsize, hostname); + else { + failf(data, "SOCKS4: too long host name"); + return CURLE_COULDNT_CONNECT; + } + packetsize += hostnamelen; + } + sx->outp = socksreq; + sx->outstanding = packetsize; + sxstate(conn, CONNECT_REQ_SENDING); } - + /* FALLTHROUGH */ + case CONNECT_REQ_SENDING: /* Send request */ - code = Curl_write_plain(conn, sock, (char *)socksreq, - packetsize + hostnamelen, - &written); - if(code || (written != packetsize + hostnamelen)) { + result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + sx->outstanding, &written); + if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to send SOCKS4 connect request."); return CURLE_COULDNT_CONNECT; } - if(protocol4a && hostnamelen == 0) { - /* SOCKS4a with very long hostname - send that name separately */ - hostnamelen = (ssize_t)strlen(hostname) + 1; - code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen, - &written); - if(code || (written != hostnamelen)) { - failf(data, "Failed to send SOCKS4 connect request."); - return CURLE_COULDNT_CONNECT; - } + if(written != sx->outstanding) { + /* not done, remain in state */ + sx->outstanding -= written; + sx->outp += written; + return CURLE_OK; } - packetsize = 8; /* receive data size */ + /* done sending! */ + sx->outstanding = 8; /* receive data size */ + sx->outp = socksreq; + sxstate(conn, CONNECT_SOCKS_READ); + /* FALLTHROUGH */ + case CONNECT_SOCKS_READ: /* Receive response */ - result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, - &actualread); - if(result || (actualread != packetsize)) { - failf(data, "Failed to receive SOCKS4 connect request ack."); + result = Curl_read_plain(sockfd, (char *)sx->outp, + sx->outstanding, &actualread); + if(result && (CURLE_AGAIN != result)) { + failf(data, "SOCKS4: Failed receiving connect request ack: %s", + curl_easy_strerror(result)); return CURLE_COULDNT_CONNECT; } - - /* - * Response format - * - * +----+----+----+----+----+----+----+----+ - * | VN | CD | DSTPORT | DSTIP | - * +----+----+----+----+----+----+----+----+ - * # of bytes: 1 1 2 4 - * - * VN is the version of the reply code and should be 0. CD is the result - * code with one of the following values: - * - * 90: request granted - * 91: request rejected or failed - * 92: request rejected because SOCKS server cannot connect to - * identd on the client - * 93: request rejected because the client program and identd - * report different user-ids - */ - - /* wrong version ? */ - if(socksreq[0] != 0) { - failf(data, - "SOCKS4 reply has wrong version, version should be 0."); - return CURLE_COULDNT_CONNECT; + else if(actualread != sx->outstanding) { + /* remain in reading state */ + sx->outstanding -= actualread; + sx->outp += actualread; + return CURLE_OK; } + sxstate(conn, CONNECT_DONE); + break; + default: /* lots of unused states in SOCKS4 */ + break; + } - /* Result */ - switch(socksreq[1]) { - case 90: - infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); - break; - case 91: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected or failed.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), - (unsigned char)socksreq[1]); - return CURLE_COULDNT_CONNECT; - case 92: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected because SOCKS server cannot connect to " - "identd on the client.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), - (unsigned char)socksreq[1]); - return CURLE_COULDNT_CONNECT; - case 93: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected because the client program and identd " - "report different user-ids.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), - (unsigned char)socksreq[1]); - return CURLE_COULDNT_CONNECT; - default: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", Unknown.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), - (unsigned char)socksreq[1]); - return CURLE_COULDNT_CONNECT; - } + /* + * Response format + * + * +----+----+----+----+----+----+----+----+ + * | VN | CD | DSTPORT | DSTIP | + * +----+----+----+----+----+----+----+----+ + * # of bytes: 1 1 2 4 + * + * VN is the version of the reply code and should be 0. CD is the result + * code with one of the following values: + * + * 90: request granted + * 91: request rejected or failed + * 92: request rejected because SOCKS server cannot connect to + * identd on the client + * 93: request rejected because the client program and identd + * report different user-ids + */ + + /* wrong version ? */ + if(socksreq[0] != 0) { + failf(data, + "SOCKS4 reply has wrong version, version should be 0."); + return CURLE_COULDNT_CONNECT; } - (void)curlx_nonblock(sock, TRUE); + /* Result */ + switch(socksreq[1]) { + case 90: + infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); + break; + case 91: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected or failed.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 92: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because SOCKS server cannot connect to " + "identd on the client.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 93: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because the client program and identd " + "report different user-ids.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + default: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", Unknown.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + *done = TRUE; return CURLE_OK; /* Proxy was successful! */ } @@ -356,7 +474,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn) + struct connectdata *conn, + bool *done) { /* According to the RFC1928, section "6. Replies". This is what a SOCK5 @@ -374,141 +493,158 @@ CURLcode Curl_SOCKS5(const char *proxy_user, o REP Reply field: o X'00' succeeded */ -#define REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */ - unsigned char socksreq[REQUEST_BUFSIZE]; - char dest[REQUEST_BUFSIZE] = "unknown"; /* printable hostname:port */ + unsigned char *socksreq = &conn->cnnct.socksreq[0]; + char dest[256] = "unknown"; /* printable hostname:port */ int idx; ssize_t actualread; ssize_t written; - int result; - CURLcode code; - curl_socket_t sock = conn->sock[sockindex]; + CURLcode result; + curl_socket_t sockfd = conn->sock[sockindex]; struct Curl_easy *data = conn->data; - timediff_t timeout; bool socks5_resolve_local = (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; const size_t hostname_len = strlen(hostname); ssize_t len = 0; const unsigned long auth = data->set.socks5auth; bool allow_gssapi = FALSE; + struct connstate *sx = &conn->cnnct; + struct Curl_dns_entry *dns = NULL; + + if(!SOCKS_STATE(sx->state) && !*done) + sxstate(conn, CONNECT_SOCKS_INIT); + + switch(sx->state) { + case CONNECT_SOCKS_INIT: + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + hostname, remote_port); + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { + infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + "length > 255 [actual len=%zu]\n", hostname_len); + socks5_resolve_local = TRUE; + } - if(conn->bits.httpproxy) - infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", - hostname, remote_port); - - /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ - if(!socks5_resolve_local && hostname_len > 255) { - infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " - "length > 255 [actual len=%zu]\n", hostname_len); - socks5_resolve_local = TRUE; - } - - /* get timeout */ - timeout = Curl_timeleft(data, NULL, TRUE); - - if(timeout < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - (void)curlx_nonblock(sock, TRUE); - - /* wait until socket gets connected */ - result = SOCKET_WRITABLE(sock, timeout); - - if(-1 == result) { - failf(conn->data, "SOCKS5: no connection here"); - return CURLE_COULDNT_CONNECT; - } - if(0 == result) { - failf(conn->data, "SOCKS5: connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(result & CURL_CSELECT_ERR) { - failf(conn->data, "SOCKS5: error occurred during connection"); - return CURLE_COULDNT_CONNECT; - } - - if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) - infof(conn->data, - "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", - auth); - if(!(auth & CURLAUTH_BASIC)) - /* disable username/password auth */ - proxy_user = NULL; + if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + infof(conn->data, + "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", + auth); + if(!(auth & CURLAUTH_BASIC)) + /* disable username/password auth */ + proxy_user = NULL; #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(auth & CURLAUTH_GSSAPI) - allow_gssapi = TRUE; + if(auth & CURLAUTH_GSSAPI) + allow_gssapi = TRUE; #endif - idx = 0; - socksreq[idx++] = 5; /* version */ - idx++; /* reserve for the number of authentication methods */ - socksreq[idx++] = 0; /* no authentication */ - if(allow_gssapi) - socksreq[idx++] = 1; /* GSS-API */ - if(proxy_user) - socksreq[idx++] = 2; /* username/password */ - /* write the number of authentication methods */ - socksreq[1] = (unsigned char) (idx - 2); - - (void)curlx_nonblock(sock, FALSE); - - infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port); - - code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), - &written); - if(code || (written != (2 + (int)socksreq[1]))) { - failf(data, "Unable to send initial SOCKS5 request."); - return CURLE_COULDNT_CONNECT; - } - - (void)curlx_nonblock(sock, TRUE); - - result = SOCKET_READABLE(sock, timeout); - - if(-1 == result) { - failf(conn->data, "SOCKS5 nothing to read"); - return CURLE_COULDNT_CONNECT; - } - if(0 == result) { - failf(conn->data, "SOCKS5 read timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(result & CURL_CSELECT_ERR) { - failf(conn->data, "SOCKS5 read error occurred"); - return CURLE_RECV_ERROR; - } - - (void)curlx_nonblock(sock, FALSE); - - result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); - if(result || (actualread != 2)) { - failf(data, "Unable to receive initial SOCKS5 response."); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[0] != 5) { - failf(data, "Received invalid version in initial SOCKS5 response."); - return CURLE_COULDNT_CONNECT; - } - if(socksreq[1] == 0) { - /* Nothing to do, no authentication needed */ - ; - } + idx = 0; + socksreq[idx++] = 5; /* version */ + idx++; /* number of authentication methods */ + socksreq[idx++] = 0; /* no authentication */ + if(allow_gssapi) + socksreq[idx++] = 1; /* GSS-API */ + if(proxy_user) + socksreq[idx++] = 2; /* username/password */ + /* write the number of authentication methods */ + socksreq[1] = (unsigned char) (idx - 2); + + result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Unable to send initial SOCKS5 request."); + return CURLE_COULDNT_CONNECT; + } + if(written != idx) { + sxstate(conn, CONNECT_SOCKS_SEND); + sx->outstanding = idx - written; + sx->outp = &socksreq[written]; + return CURLE_OK; + } + sxstate(conn, CONNECT_SOCKS_READ); + goto CONNECT_SOCKS_READ_INIT; + case CONNECT_SOCKS_SEND: + result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + sx->outstanding, &written); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Unable to send initial SOCKS5 request."); + return CURLE_COULDNT_CONNECT; + } + if(written != sx->outstanding) { + /* not done, remain in state */ + sx->outstanding -= written; + sx->outp += written; + return CURLE_OK; + } + /* FALLTHROUGH */ + CONNECT_SOCKS_READ_INIT: + case CONNECT_SOCKS_READ_INIT: + sx->outstanding = 2; /* expect two bytes */ + sx->outp = socksreq; /* store it here */ + /* FALLTHROUGH */ + case CONNECT_SOCKS_READ: + result = Curl_read_plain(sockfd, (char *)sx->outp, + sx->outstanding, &actualread); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Unable to receive initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + else if(actualread != sx->outstanding) { + /* remain in reading state */ + sx->outstanding -= actualread; + sx->outp += actualread; + return CURLE_OK; + } + else if(socksreq[0] != 5) { + failf(data, "Received invalid version in initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + else if(socksreq[1] == 0) { + /* DONE! No authentication needed. Send request. */ + sxstate(conn, CONNECT_REQ_INIT); + goto CONNECT_REQ_INIT; + } + else if(socksreq[1] == 2) { + /* regular name + password authentication */ + sxstate(conn, CONNECT_AUTH_INIT); + goto CONNECT_AUTH_INIT; + } #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - else if(allow_gssapi && (socksreq[1] == 1)) { - code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); - if(code) { - failf(data, "Unable to negotiate SOCKS5 GSS-API context."); + else if(allow_gssapi && (socksreq[1] == 1)) { + sxstate(conn, CONNECT_GSSAPI_INIT); + result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + if(result) { + failf(data, "Unable to negotiate SOCKS5 GSS-API context."); + return CURLE_COULDNT_CONNECT; + } + } +#endif + else { + /* error */ + if(!allow_gssapi && (socksreq[1] == 1)) { + failf(data, + "SOCKS5 GSSAPI per-message authentication is not supported."); + return CURLE_COULDNT_CONNECT; + } + else if(socksreq[1] == 255) { + failf(data, "No authentication method was acceptable."); + return CURLE_COULDNT_CONNECT; + } + failf(data, + "Undocumented SOCKS5 mode attempted to be used by server."); return CURLE_COULDNT_CONNECT; } - } + break; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + case CONNECT_GSSAPI_INIT: + /* GSSAPI stuff done non-blocking */ + break; #endif - else if(socksreq[1] == 2) { + + default: /* do nothing! */ + break; + + CONNECT_AUTH_INIT: + case CONNECT_AUTH_INIT: { /* Needs user name and password */ size_t proxy_user_len, proxy_password_len; if(proxy_user && proxy_password) { @@ -549,18 +685,41 @@ CURLcode Curl_SOCKS5(const char *proxy_user, memcpy(socksreq + len, proxy_password, proxy_password_len); } len += proxy_password_len; - - code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); - if(code || (len != written)) { + sxstate(conn, CONNECT_AUTH_SEND); + sx->outstanding = len; + sx->outp = socksreq; + } + /* FALLTHROUGH */ + case CONNECT_AUTH_SEND: + result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + sx->outstanding, &written); + if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to send SOCKS5 sub-negotiation request."); return CURLE_COULDNT_CONNECT; } - - result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); - if(result || (actualread != 2)) { + if(sx->outstanding != written) { + /* remain in state */ + sx->outstanding -= written; + sx->outp += written; + return CURLE_OK; + } + sx->outp = socksreq; + sx->outstanding = 2; + sxstate(conn, CONNECT_AUTH_READ); + /* FALLTHROUGH */ + case CONNECT_AUTH_READ: + result = Curl_read_plain(sockfd, (char *)sx->outp, + sx->outstanding, &actualread); + if(result && (CURLE_AGAIN != result)) { failf(data, "Unable to receive SOCKS5 sub-negotiation response."); return CURLE_COULDNT_CONNECT; } + if(actualread != sx->outstanding) { + /* remain in state */ + sx->outstanding -= actualread; + sx->outp += actualread; + return CURLE_OK; + } /* ignore the first (VER) byte */ if(socksreq[1] != 0) { /* status */ @@ -570,209 +729,248 @@ CURLcode Curl_SOCKS5(const char *proxy_user, } /* Everything is good so far, user was authenticated! */ - } - else { - /* error */ - if(!allow_gssapi && (socksreq[1] == 1)) { - failf(data, - "SOCKS5 GSSAPI per-message authentication is not supported."); - return CURLE_COULDNT_CONNECT; - } - if(socksreq[1] == 255) { - if(!proxy_user || !*proxy_user) { - failf(data, - "No authentication method was acceptable. (It is quite likely" - " that the SOCKS5 server wanted a username/password, since none" - " was supplied to the server on this connection.)"); + sxstate(conn, CONNECT_REQ_INIT); + /* FALLTHROUGH */ + CONNECT_REQ_INIT: + case CONNECT_REQ_INIT: + if(socks5_resolve_local) { + enum resolve_t rc = Curl_resolv(conn, hostname, remote_port, + FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_HOST; + + if(rc == CURLRESOLV_PENDING) { + sxstate(conn, CONNECT_RESOLVING); + return CURLE_OK; } - else { - failf(data, "No authentication method was acceptable."); - } - return CURLE_COULDNT_CONNECT; + sxstate(conn, CONNECT_RESOLVED); + goto CONNECT_RESOLVED; } - else { - failf(data, - "Undocumented SOCKS5 mode attempted to be used by server."); - return CURLE_COULDNT_CONNECT; - } - } + goto CONNECT_RESOLVE_REMOTE; - /* Authentication is complete, now specify destination to the proxy */ - len = 0; - socksreq[len++] = 5; /* version (SOCKS5) */ - socksreq[len++] = 1; /* connect */ - socksreq[len++] = 0; /* must be zero */ - - if(!socks5_resolve_local) { - socksreq[len++] = 3; /* ATYP: domain name = 3 */ - socksreq[len++] = (char) hostname_len; /* address length */ - memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */ - len += hostname_len; - msnprintf(dest, sizeof(dest), "%s:%d", hostname, remote_port); - infof(data, "SOCKS5 connect to %s (remotely resolved)\n", dest); - } - else { - struct Curl_dns_entry *dns; - Curl_addrinfo *hp = NULL; - int rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); - - if(rc == CURLRESOLV_ERROR) - return CURLE_COULDNT_RESOLVE_HOST; + case CONNECT_RESOLVING: + /* check if we have the name resolved by now */ + dns = Curl_fetch_addr(conn, hostname, (int)conn->port); - if(rc == CURLRESOLV_PENDING) { - /* this requires that we're in "wait for resolve" state */ - code = Curl_resolver_wait_resolv(conn, &dns); - if(code) - return code; + if(dns) { +#ifdef CURLRES_ASYNCH + conn->async.dns = dns; + conn->async.done = TRUE; +#endif + infof(data, "SOCKS5: hostname '%s' found\n", hostname); } - /* - * We cannot use 'hostent' as a struct that Curl_resolv() returns. It - * returns a Curl_addrinfo pointer that may not always look the same. - */ + if(!dns) { + result = Curl_resolv_check(data->conn, &dns); + /* stay in the state or error out */ + return result; + } + /* FALLTHROUGH */ + CONNECT_RESOLVED: + case CONNECT_RESOLVED: { + Curl_addrinfo *hp = NULL; if(dns) hp = dns->addr; - if(hp) { - if(Curl_printable_address(hp, dest, sizeof(dest))) { - size_t destlen = strlen(dest); - msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port); - } - else { - strcpy(dest, "unknown"); - } - - if(hp->ai_family == AF_INET) { - int i; - struct sockaddr_in *saddr_in; - socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ - - saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; - for(i = 0; i < 4; i++) { - socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; - } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } - infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest); - } -#ifdef ENABLE_IPV6 - else if(hp->ai_family == AF_INET6) { - int i; - struct sockaddr_in6 *saddr_in6; - socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ - - saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; - for(i = 0; i < 16; i++) { - socksreq[len++] = - ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; - } + if(Curl_printable_address(hp, dest, sizeof(dest))) { + size_t destlen = strlen(dest); + msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port); + } + else { + strcpy(dest, "unknown"); + } - infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest); + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ + if(hp->ai_family == AF_INET) { + int i; + struct sockaddr_in *saddr_in; + socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ + + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + for(i = 0; i < 4; i++) { + socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; } -#endif - else { - hp = NULL; /* fail! */ - failf(data, "SOCKS5 connection to %s not supported\n", dest); + infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest); + } +#ifdef ENABLE_IPV6 + else if(hp->ai_family == AF_INET6) { + int i; + struct sockaddr_in6 *saddr_in6; + socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ + + saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; + for(i = 0; i < 16; i++) { + socksreq[len++] = + ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; } - Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest); } - if(!hp) { - failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", - hostname); - return CURLE_COULDNT_RESOLVE_HOST; +#endif + else { + hp = NULL; /* fail! */ + failf(data, "SOCKS5 connection to %s not supported\n", dest); } + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + goto CONNECT_REQ_SEND; } + CONNECT_RESOLVE_REMOTE: + case CONNECT_RESOLVE_REMOTE: + /* Authentication is complete, now specify destination to the proxy */ + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ + + if(!socks5_resolve_local) { + socksreq[len++] = 3; /* ATYP: domain name = 3 */ + socksreq[len++] = (char) hostname_len; /* one byte address length */ + memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */ + len += hostname_len; + infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n", + hostname, remote_port); + } + /* FALLTHROUGH */ - socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ - socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + CONNECT_REQ_SEND: + case CONNECT_REQ_SEND: + /* PORT MSB */ + socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); + /* PORT LSB */ + socksreq[len++] = (unsigned char)(remote_port & 0xff); #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(conn->socks5_gssapi_enctype) { - failf(data, "SOCKS5 GSS-API protection not yet implemented."); - } - else + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + return CURLE_COULDNT_CONNECT; + } #endif - code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); - - if(code || (len != written)) { - failf(data, "Failed to send SOCKS5 connect request."); - return CURLE_COULDNT_CONNECT; - } - - len = 10; /* minimum packet size is 10 */ - + sx->outp = socksreq; + sx->outstanding = len; + sxstate(conn, CONNECT_REQ_SENDING); + /* FALLTHROUGH */ + case CONNECT_REQ_SENDING: + result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + sx->outstanding, &written); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Failed to send SOCKS5 connect request."); + return CURLE_COULDNT_CONNECT; + } + if(sx->outstanding != written) { + /* remain in state */ + sx->outstanding -= written; + sx->outp += written; + return CURLE_OK; + } #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(conn->socks5_gssapi_enctype) { - failf(data, "SOCKS5 GSS-API protection not yet implemented."); - } - else + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + return CURLE_COULDNT_CONNECT; + } #endif - result = Curl_blockread_all(conn, sock, (char *)socksreq, - len, &actualread); - - if(result || (len != actualread)) { - failf(data, "Failed to receive SOCKS5 connect request ack."); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[0] != 5) { /* version */ - failf(data, - "SOCKS5 reply has wrong version, version should be 5."); - return CURLE_COULDNT_CONNECT; - } - - /* Fix: in general, returned BND.ADDR is variable length parameter by RFC - 1928, so the reply packet should be read until the end to avoid errors at - subsequent protocol level. - - +----+-----+-------+------+----------+----------+ - |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | - +----+-----+-------+------+----------+----------+ - | 1 | 1 | X'00' | 1 | Variable | 2 | - +----+-----+-------+------+----------+----------+ + sx->outstanding = 10; /* minimum packet size is 10 */ + sx->outp = socksreq; + sxstate(conn, CONNECT_REQ_READ); + /* FALLTHROUGH */ + case CONNECT_REQ_READ: + result = Curl_read_plain(sockfd, (char *)sx->outp, + sx->outstanding, &actualread); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + else if(actualread != sx->outstanding) { + /* remain in state */ + sx->outstanding -= actualread; + sx->outp += actualread; + return CURLE_OK; + } - ATYP: - o IP v4 address: X'01', BND.ADDR = 4 byte - o domain name: X'03', BND.ADDR = [ 1 byte length, string ] - o IP v6 address: X'04', BND.ADDR = 16 byte - */ + if(socksreq[0] != 5) { /* version */ + failf(data, + "SOCKS5 reply has wrong version, version should be 5."); + return CURLE_COULDNT_CONNECT; + } + else if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + failf(data, "Can't complete SOCKS5 connection to %s. (%d)", + hostname, (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + } - /* Calculate real packet size */ - if(socksreq[3] == 3) { - /* domain name */ - int addrlen = (int) socksreq[4]; - len = 5 + addrlen + 2; - } - else if(socksreq[3] == 4) { - /* IPv6 */ - len = 4 + 16 + 2; - } + /* Fix: in general, returned BND.ADDR is variable length parameter by RFC + 1928, so the reply packet should be read until the end to avoid errors + at subsequent protocol level. + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + ATYP: + o IP v4 address: X'01', BND.ADDR = 4 byte + o domain name: X'03', BND.ADDR = [ 1 byte length, string ] + o IP v6 address: X'04', BND.ADDR = 16 byte + */ + + /* Calculate real packet size */ + if(socksreq[3] == 3) { + /* domain name */ + int addrlen = (int) socksreq[4]; + len = 5 + addrlen + 2; + } + else if(socksreq[3] == 4) { + /* IPv6 */ + len = 4 + 16 + 2; + } - /* At this point we already read first 10 bytes */ + /* At this point we already read first 10 bytes */ #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(!conn->socks5_gssapi_enctype) { - /* decrypt_gssapi_blockread already read the whole packet */ + if(!conn->socks5_gssapi_enctype) { + /* decrypt_gssapi_blockread already read the whole packet */ #endif - if(len > 10) { - result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], - len - 10, &actualread); - if(result || ((len - 10) != actualread)) { - failf(data, "Failed to receive SOCKS5 connect request ack."); - return CURLE_COULDNT_CONNECT; + if(len > 10) { + sx->outstanding = len - 10; /* get the rest */ + sx->outp = &socksreq[10]; + sxstate(conn, CONNECT_REQ_READ_MORE); + } + else { + sxstate(conn, CONNECT_DONE); + break; } - } #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - } + } #endif - - if(socksreq[1] != 0) { /* Anything besides 0 is an error */ - failf(data, "Can't complete SOCKS5 connection to %s. (%d)", - dest, (unsigned char)socksreq[1]); - return CURLE_COULDNT_CONNECT; + /* FALLTHROUGH */ + case CONNECT_REQ_READ_MORE: + result = Curl_read_plain(sockfd, (char *)sx->outp, + sx->outstanding, &actualread); + if(result && (CURLE_AGAIN != result)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + if(actualread != sx->outstanding) { + /* remain in state */ + sx->outstanding -= actualread; + sx->outp += actualread; + return CURLE_OK; + } + sxstate(conn, CONNECT_DONE); } infof(data, "SOCKS5 request granted.\n"); - (void)curlx_nonblock(sock, TRUE); + *done = TRUE; return CURLE_OK; /* Proxy was successful! */ } diff --git a/libs/libcurl/src/socks.h b/libs/libcurl/src/socks.h index 3b319a6ef1..64a7563373 100644 --- a/libs/libcurl/src/socks.h +++ b/libs/libcurl/src/socks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -27,13 +27,13 @@ #ifdef CURL_DISABLE_PROXY #define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#define Curl_SOCKS_getsock(x,y,z) 0 #else /* * Helper read-from-socket functions. Does the same as Curl_read() but it * blocks until all bytes amount of buffersize will be read. No more, no less. * - * This is STUPID BLOCKING behaviour which we frown upon, but right now this - * is what we have... + * This is STUPID BLOCKING behavior */ int Curl_blockread_all(struct connectdata *conn, curl_socket_t sockfd, @@ -41,6 +41,9 @@ int Curl_blockread_all(struct connectdata *conn, ssize_t buffersize, ssize_t *n); +int Curl_SOCKS_getsock(struct connectdata *conn, + curl_socket_t *sock, + int sockindex); /* * This function logs in to a SOCKS4(a) proxy and sends the specifics to the * final destination server. @@ -49,7 +52,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn); + struct connectdata *conn, + bool *done); /* * This function logs in to a SOCKS5 proxy and sends the specifics to the @@ -60,7 +64,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn); + struct connectdata *conn, + bool *done); #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) /* diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c index 65294bbebd..97ee7183e0 100644 --- a/libs/libcurl/src/socks_gssapi.c +++ b/libs/libcurl/src/socks_gssapi.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com> - * Copyright (C) 2012 - 2018, 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 @@ -167,6 +167,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } + (void)curlx_nonblock(sock, FALSE); + /* As long as we need to keep sending some context info, and there's no */ /* errors, keep sending it... */ for(;;) { @@ -513,6 +515,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_buffer(&gss_status, &gss_recv_token); } + (void)curlx_nonblock(sock, TRUE); + infof(data, "SOCKS5 access with%s protection granted.\n", (socksreq[0] == 0)?"out GSS-API data": ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c index 57027ef686..d5be64a3c0 100644 --- a/libs/libcurl/src/socks_sspi.c +++ b/libs/libcurl/src/socks_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> * * This software is licensed as described in the file COPYING, which @@ -153,6 +153,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } + (void)curlx_nonblock(sock, FALSE); + /* As long as we need to keep sending some context info, and there's no */ /* errors, keep sending it... */ for(;;) { @@ -587,6 +589,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); } + (void)curlx_nonblock(sock, TRUE); infof(data, "SOCKS5 access with%s protection granted.\n", (socksreq[0] == 0)?"out GSS-API data": diff --git a/libs/libcurl/src/strcase.c b/libs/libcurl/src/strcase.c index a894712254..a309e35291 100644 --- a/libs/libcurl/src/strcase.c +++ b/libs/libcurl/src/strcase.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -26,6 +26,8 @@ #include "strcase.h" +static char raw_tolower(char in); + /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because its behavior is altered by the current locale. */ char Curl_raw_toupper(char in) @@ -96,7 +98,7 @@ char Curl_raw_toupper(char in) /* Portable, consistent tolower (remember EBCDIC). Do not use tolower() because its behavior is altered by the current locale. */ -char Curl_raw_tolower(char in) +static char raw_tolower(char in) { #if !defined(CURL_DOES_CONVERSIONS) if(in >= 'A' && in <= 'Z') @@ -245,7 +247,7 @@ void Curl_strntolower(char *dest, const char *src, size_t n) return; do { - *dest++ = Curl_raw_tolower(*src); + *dest++ = raw_tolower(*src); } while(*src++ && --n); } diff --git a/libs/libcurl/src/strcase.h b/libs/libcurl/src/strcase.h index baa768b2b2..cd4c4191a9 100644 --- a/libs/libcurl/src/strcase.h +++ b/libs/libcurl/src/strcase.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -40,7 +40,6 @@ int Curl_safe_strcasecompare(const char *first, const char *second); int Curl_strncasecompare(const char *first, const char *second, size_t max); char Curl_raw_toupper(char in); -char Curl_raw_tolower(char in); /* checkprefix() is a shorter version of the above, used when the first argument is zero-byte terminated */ diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index 29df5aa55a..1a166bf019 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -317,6 +317,9 @@ curl_easy_strerror(CURLcode error) case CURLE_HTTP3: return "HTTP/3 error"; + case CURLE_QUIC_CONNECT_ERROR: + return "QUIC connection error"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: @@ -392,6 +395,9 @@ curl_multi_strerror(CURLMcode error) case CURLM_WAKEUP_FAILURE: return "Wakeup is unavailable or failed"; + case CURLM_BAD_FUNCTION_ARGUMENT: + return "A libcurl function was given a bad argument"; + case CURLM_LAST: break; } diff --git a/libs/libcurl/src/strerror.h b/libs/libcurl/src/strerror.h index 278c1082f0..bae8f89745 100644 --- a/libs/libcurl/src/strerror.h +++ b/libs/libcurl/src/strerror.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -24,7 +24,7 @@ #include "urldata.h" -#define STRERROR_LEN 128 /* a suitable length */ +#define STRERROR_LEN 256 /* a suitable length */ const char *Curl_strerror(int err, char *buf, size_t buflen); #if defined(WIN32) || defined(_WIN32_WCE) diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index 52a5fd9519..b9587b5f3a 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016 - 2019, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -109,11 +109,11 @@ CURLcode Curl_win32_init(long flags) if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { Curl_isVistaOrGreater = TRUE; - QueryPerformanceFrequency(&Curl_freq); } else Curl_isVistaOrGreater = FALSE; + QueryPerformanceFrequency(&Curl_freq); return CURLE_OK; } diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/timeval.c index 9b05cf0512..e761966a1b 100644 --- a/libs/libcurl/src/timeval.c +++ b/libs/libcurl/src/timeval.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -28,6 +28,7 @@ extern LARGE_INTEGER Curl_freq; extern bool Curl_isVistaOrGreater; +/* In case of bug fix this function has a counterpart in tool_util.c */ struct curltime Curl_now(void) { struct curltime now; diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index ead8b36db9..827076183f 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -1217,7 +1217,8 @@ CURLcode Curl_readwrite(struct connectdata *conn, else fd_write = CURL_SOCKET_BAD; - if(conn->data->state.drain) { + if(data->state.drain) { + data->state.drain--; select_res |= CURL_CSELECT_IN; DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); } diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index 56fb736368..47fc66aedd 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -128,7 +128,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "memdebug.h" static void conn_free(struct connectdata *conn); -static void free_idnconverted_hostname(struct hostname *host); static unsigned int get_protocol_family(unsigned int protocol); /* Some parts of the code (e.g. chunked encoding) assume this buffer has at @@ -187,7 +186,7 @@ static const struct Curl_handler * const protocols[] = { &Curl_handler_tftp, #endif -#if defined(USE_SSH) +#if defined(USE_SSH) && !defined(USE_WOLFSSH) &Curl_handler_scp, #endif @@ -380,7 +379,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.ulbuf); Curl_flush_cookies(data, TRUE); #ifdef USE_ALTSVC - Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]); Curl_altsvc_cleanup(data->asi); data->asi = NULL; #endif @@ -714,14 +713,13 @@ static void conn_free(struct connectdata *conn) if(!conn) return; - free_idnconverted_hostname(&conn->host); - free_idnconverted_hostname(&conn->conn_to_host); - free_idnconverted_hostname(&conn->http_proxy.host); - free_idnconverted_hostname(&conn->socks_proxy.host); + Curl_free_idnconverted_hostname(&conn->host); + Curl_free_idnconverted_hostname(&conn->conn_to_host); + Curl_free_idnconverted_hostname(&conn->http_proxy.host); + Curl_free_idnconverted_hostname(&conn->socks_proxy.host); Curl_safefree(conn->user); Curl_safefree(conn->passwd); - Curl_safefree(conn->oauth_bearer); Curl_safefree(conn->sasl_authzid); Curl_safefree(conn->options); Curl_safefree(conn->http_proxy.user); @@ -883,9 +881,37 @@ proxy_info_matches(const struct proxy_info* data, return FALSE; } + +static bool +socks_proxy_info_matches(const struct proxy_info* data, + const struct proxy_info* needle) +{ + if(!proxy_info_matches(data, needle)) + return FALSE; + + /* the user information is case-sensitive + or at least it is not defined as case-insensitive + see https://tools.ietf.org/html/rfc3986#section-3.2.1 */ + if((data->user == NULL) != (needle->user == NULL)) + return FALSE; + /* curl_strequal does a case insentive comparison, so do not use it here! */ + if(data->user && + needle->user && + strcmp(data->user, needle->user) != 0) + return FALSE; + if((data->passwd == NULL) != (needle->passwd == NULL)) + return FALSE; + /* curl_strequal does a case insentive comparison, so do not use it here! */ + if(data->passwd && + needle->passwd && + strcmp(data->passwd, needle->passwd) != 0) + return FALSE; + return TRUE; +} #else /* disabled, won't get called */ #define proxy_info_matches(x,y) FALSE +#define socks_proxy_info_matches(x,y) FALSE #endif /* A connection has to have been idle for a shorter time than 'maxage_conn' to @@ -1073,7 +1099,7 @@ ConnectionExists(struct Curl_easy *data, curr = bundle->conn_list.head; while(curr) { bool match = FALSE; - size_t multiplexed; + size_t multiplexed = 0; /* * Note that if we use a HTTP proxy in normal mode (no tunneling), we @@ -1086,8 +1112,8 @@ ConnectionExists(struct Curl_easy *data, /* connect-only or to-be-closed connections will not be reused */ continue; - multiplexed = CONN_INUSE(check) && - (bundle->multiuse == BUNDLE_MULTIPLEX); + if(bundle->multiuse == BUNDLE_MULTIPLEX) + multiplexed = CONN_INUSE(check); if(canmultiplex) { ; @@ -1144,8 +1170,9 @@ ConnectionExists(struct Curl_easy *data, needle->bits.socksproxy != check->bits.socksproxy) continue; - if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy, - &check->socks_proxy)) + if(needle->bits.socksproxy && + !socks_proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) continue; if(needle->bits.conn_to_host != check->bits.conn_to_host) @@ -1185,6 +1212,8 @@ ConnectionExists(struct Curl_easy *data, } } + DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data)); + if(!canmultiplex && check->data) /* this request can't be multiplexed but the checked connection is already in use so we skip it */ @@ -1239,7 +1268,7 @@ ConnectionExists(struct Curl_easy *data, needle->conn_to_port == check->conn_to_port) && strcasecompare(needle->host.name, check->host.name) && needle->remote_port == check->remote_port) { - /* The schemes match or the the protocol family is the same and the + /* The schemes match or the protocol family is the same and the previous connection was TLS upgraded, and the hostname and host port match */ if(needle->handler->flags & PROTOPT_SSL) { @@ -1347,6 +1376,13 @@ ConnectionExists(struct Curl_easy *data, multiplexed); continue; } + else if(multiplexed >= + Curl_multi_max_concurrent_streams(needle->data->multi)) { + infof(data, "client side MAX_CONCURRENT_STREAMS reached" + ", skip (%zu)\n", + multiplexed); + continue; + } } #endif /* When not multiplexed, we have a match here! */ @@ -1400,10 +1436,14 @@ void Curl_verboseconnect(struct connectdata *conn) /* * Helpers for IDNA conversions. */ -static bool is_ASCII_name(const char *hostname) +bool Curl_is_ASCII_name(const char *hostname) { + /* get an UNSIGNED local version of the pointer */ const unsigned char *ch = (const unsigned char *)hostname; + if(!hostname) /* bad input, consider it ASCII! */ + return TRUE; + while(*ch) { if(*ch++ & 0x80) return FALSE; @@ -1428,8 +1468,8 @@ static void strip_trailing_dot(struct hostname *host) /* * Perform any necessary IDN conversion of hostname */ -static CURLcode idnconvert_hostname(struct connectdata *conn, - struct hostname *host) +CURLcode Curl_idnconvert_hostname(struct connectdata *conn, + struct hostname *host) { struct Curl_easy *data = conn->data; @@ -1444,7 +1484,7 @@ static CURLcode idnconvert_hostname(struct connectdata *conn, host->dispname = host->name; /* Check name for non-ASCII and convert hostname to ACE form if we can */ - if(!is_ASCII_name(host->name)) { + if(!Curl_is_ASCII_name(host->name)) { #ifdef USE_LIBIDN2 if(idn2_check_version(IDN2_VERSION)) { char *ace_hostname = NULL; @@ -1477,7 +1517,9 @@ static CURLcode idnconvert_hostname(struct connectdata *conn, host->name = host->encalloc; } else { - failf(data, "Failed to convert %s to ACE;\n", host->name); + char buffer[STRERROR_LEN]; + failf(data, "Failed to convert %s to ACE; %s\n", host->name, + Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); return CURLE_URL_MALFORMAT; } #else @@ -1490,7 +1532,7 @@ static CURLcode idnconvert_hostname(struct connectdata *conn, /* * Frees data allocated by idnconvert_hostname() */ -static void free_idnconverted_hostname(struct hostname *host) +void Curl_free_idnconverted_hostname(struct hostname *host) { #if defined(USE_LIBIDN2) if(host->encalloc) { @@ -1615,7 +1657,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ defined(NTLM_WB_ENABLED) - conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; #endif /* Initialize the easy handle list */ @@ -3194,8 +3237,8 @@ static CURLcode resolve_server(struct Curl_easy *data, static void reuse_conn(struct connectdata *old_conn, struct connectdata *conn) { - free_idnconverted_hostname(&old_conn->http_proxy.host); - free_idnconverted_hostname(&old_conn->socks_proxy.host); + Curl_free_idnconverted_hostname(&old_conn->http_proxy.host); + Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host); free(old_conn->http_proxy.host.rawalloc); free(old_conn->socks_proxy.host.rawalloc); @@ -3239,8 +3282,8 @@ static void reuse_conn(struct connectdata *old_conn, /* host can change, when doing keepalive with a proxy or if the case is different this time etc */ - free_idnconverted_hostname(&conn->host); - free_idnconverted_hostname(&conn->conn_to_host); + Curl_free_idnconverted_hostname(&conn->host); + Curl_free_idnconverted_hostname(&conn->conn_to_host); Curl_safefree(conn->host.rawalloc); Curl_safefree(conn->conn_to_host.rawalloc); conn->host = old_conn->host; @@ -3336,14 +3379,6 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) goto out; - if(data->set.str[STRING_BEARER]) { - conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); - if(!conn->oauth_bearer) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - } - if(data->set.str[STRING_SASL_AUTHZID]) { conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]); if(!conn->sasl_authzid) { @@ -3407,21 +3442,21 @@ static CURLcode create_conn(struct Curl_easy *data, /************************************************************* * IDN-convert the hostnames *************************************************************/ - result = idnconvert_hostname(conn, &conn->host); + result = Curl_idnconvert_hostname(conn, &conn->host); if(result) goto out; if(conn->bits.conn_to_host) { - result = idnconvert_hostname(conn, &conn->conn_to_host); + result = Curl_idnconvert_hostname(conn, &conn->conn_to_host); if(result) goto out; } if(conn->bits.httpproxy) { - result = idnconvert_hostname(conn, &conn->http_proxy.host); + result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host); if(result) goto out; } if(conn->bits.socksproxy) { - result = idnconvert_hostname(conn, &conn->socks_proxy.host); + result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host); if(result) goto out; } diff --git a/libs/libcurl/src/url.h b/libs/libcurl/src/url.h index 053fbdffc2..5000c512a8 100644 --- a/libs/libcurl/src/url.h +++ b/libs/libcurl/src/url.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -62,6 +62,11 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, const struct Curl_handler *Curl_builtin_scheme(const char *scheme); +bool Curl_is_ASCII_name(const char *hostname); +CURLcode Curl_idnconvert_hostname(struct connectdata *conn, + struct hostname *host); +void Curl_free_idnconverted_hostname(struct hostname *host); + #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless specified */ diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index fa514bce53..506e244dc4 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -428,7 +428,6 @@ static char *concat_url(const char *base, const char *relurl) * */ static CURLUcode parse_hostname_login(struct Curl_URL *u, - const struct Curl_handler *h, char **hostname, unsigned int flags) { @@ -437,6 +436,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, char *userp = NULL; char *passwdp = NULL; char *optionsp = NULL; + const struct Curl_handler *h = NULL; /* At this point, we're hoping all the other special cases have * been taken care of, so conn->host.name is at most @@ -456,6 +456,10 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, * ftp://user:password@ftp.my.site:8021/README */ *hostname = ++ptr; + /* if this is a known scheme, get some details */ + if(u->scheme) + h = Curl_builtin_scheme(u->scheme); + /* We could use the login information in the URL so extract it. Only parse options if the handler says we should. Note that 'h' might be NULL! */ ccode = Curl_parse_login_details(login, ptr - login - 1, @@ -571,7 +575,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname) } /* scan for byte values < 31 or 127 */ -static CURLUcode junkscan(char *part) +static CURLUcode junkscan(const char *part) { if(part) { static const char badbytes[]={ @@ -668,10 +672,9 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) CURLUcode result; bool url_has_scheme = FALSE; char schemebuf[MAX_SCHEME_LEN + 1]; - char *schemep = NULL; + const char *schemep = NULL; size_t schemelen = 0; size_t urllen; - const struct Curl_handler *h = NULL; if(!url) return CURLUE_MALFORMED_INPUT; @@ -798,7 +801,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) return CURLUE_MALFORMED_INPUT; if(flags & CURLU_DEFAULT_SCHEME) - schemep = (char *) DEFAULT_SCHEME; + schemep = DEFAULT_SCHEME; /* * The URL was badly formatted, let's try without scheme specified. @@ -820,36 +823,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) return CURLUE_MALFORMED_INPUT; } - if((flags & CURLU_GUESS_SCHEME) && !schemep) { - /* legacy curl-style guess based on host name */ - if(checkprefix("ftp.", hostname)) - schemep = (char *)"ftp"; - else if(checkprefix("dict.", hostname)) - schemep = (char *)"dict"; - else if(checkprefix("ldap.", hostname)) - schemep = (char *)"ldap"; - else if(checkprefix("imap.", hostname)) - schemep = (char *)"imap"; - else if(checkprefix("smtp.", hostname)) - schemep = (char *)"smtp"; - else if(checkprefix("pop3.", hostname)) - schemep = (char *)"pop3"; - else - schemep = (char *)"http"; - } - len = strlen(p); memcpy(path, p, len); path[len] = 0; - u->scheme = strdup(schemep); - if(!u->scheme) - return CURLUE_OUT_OF_MEMORY; + if(schemep) { + u->scheme = strdup(schemep); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + } } - /* if this is a known scheme, get some details */ - h = Curl_builtin_scheme(u->scheme); - if(junkscan(path)) return CURLUE_MALFORMED_INPUT; @@ -916,7 +900,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) if(junkscan(hostname)) return CURLUE_MALFORMED_INPUT; - result = parse_hostname_login(u, h, &hostname, flags); + result = parse_hostname_login(u, &hostname, flags); if(result) return result; @@ -936,6 +920,28 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) u->host = strdup(hostname); if(!u->host) return CURLUE_OUT_OF_MEMORY; + + if((flags & CURLU_GUESS_SCHEME) && !schemep) { + /* legacy curl-style guess based on host name */ + if(checkprefix("ftp.", hostname)) + schemep = "ftp"; + else if(checkprefix("dict.", hostname)) + schemep = "dict"; + else if(checkprefix("ldap.", hostname)) + schemep = "ldap"; + else if(checkprefix("imap.", hostname)) + schemep = "imap"; + else if(checkprefix("smtp.", hostname)) + schemep = "smtp"; + else if(checkprefix("pop3.", hostname)) + schemep = "pop3"; + else + schemep = "http"; + + u->scheme = strdup(schemep); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + } } Curl_safefree(u->scratch); diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index 3effb1626f..e1348cf29b 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -367,6 +367,14 @@ struct ntlmdata { unsigned char nonce[8]; void *target_info; /* TargetInfo received in the ntlm type-2 message */ unsigned int target_info_len; + +#if defined(NTLM_WB_ENABLED) + /* used for communication with Samba's winbind daemon helper ntlm_auth */ + curl_socket_t ntlm_auth_hlpr_socket; + pid_t ntlm_auth_hlpr_pid; + char *challenge; /* The received base64 encoded ntlm type-2 message */ + char *response; /* The generated base64 ntlm type-1/type-3 message */ +#endif #endif }; #endif @@ -468,7 +476,6 @@ struct ConnectBits { BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(tls_enable_npn); /* TLS NPN extension? */ BIT(tls_enable_alpn); /* TLS ALPN extension? */ - BIT(socksproxy_connecting); /* connecting through a socks proxy */ BIT(connect_only); }; @@ -809,6 +816,41 @@ struct http_connect_state { struct ldapconninfo; +/* for the (SOCKS) connect state machine */ +enum connect_t { + CONNECT_INIT, + CONNECT_SOCKS_INIT, /* 1 */ + CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */ + CONNECT_SOCKS_READ_INIT, /* 3 set up read */ + CONNECT_SOCKS_READ, /* 4 read server response */ + CONNECT_GSSAPI_INIT, /* 5 */ + CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */ + CONNECT_AUTH_SEND, /* 7 send auth */ + CONNECT_AUTH_READ, /* 8 read auth response */ + CONNECT_REQ_INIT, /* 9 init SOCKS "request" */ + CONNECT_RESOLVING, /* 10 */ + CONNECT_RESOLVED, /* 11 */ + CONNECT_RESOLVE_REMOTE, /* 12 */ + CONNECT_REQ_SEND, /* 13 */ + CONNECT_REQ_SENDING, /* 14 */ + CONNECT_REQ_READ, /* 15 */ + CONNECT_REQ_READ_MORE, /* 16 */ + CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */ +}; + +#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \ + ((x) < CONNECT_DONE)) +#define SOCKS_REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */ + +struct connstate { + enum connect_t state; + unsigned char socksreq[SOCKS_REQUEST_BUFSIZE]; + + /* CONNECT_SOCKS_SEND */ + ssize_t outstanding; /* send this many bytes more */ + unsigned char *outp; /* send from this pointer */ +}; + /* * The connectdata struct contains all fields and variables that should be * unique for an entire connection. @@ -818,7 +860,7 @@ struct connectdata { caution that this might very well vary between different times this connection is used! */ struct Curl_easy *data; - + struct connstate cnnct; struct curl_llist_element bundle_node; /* conncache */ /* chunk is for HTTP chunked encoding, but is in the general connectdata @@ -906,7 +948,6 @@ struct connectdata { char *passwd; /* password string, allocated */ char *options; /* options string, allocated */ - char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ char *sasl_authzid; /* authorisation identity string, allocated */ int httpversion; /* the HTTP version*10 reported by the server */ @@ -918,8 +959,6 @@ struct connectdata { curl_socket_t sock[2]; /* two sockets, the second is used for the data transfer when doing FTP */ curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */ - bool sock_accepted[2]; /* TRUE if the socket on this index was created with - accept() */ Curl_recv *recv[2]; Curl_send *send[2]; @@ -1011,14 +1050,6 @@ struct connectdata { because it authenticates connections, not single requests! */ struct ntlmdata proxyntlm; /* NTLM data for proxy */ - -#if defined(NTLM_WB_ENABLED) - /* used for communication with Samba's winbind daemon helper ntlm_auth */ - curl_socket_t ntlm_auth_hlpr_socket; - pid_t ntlm_auth_hlpr_pid; - char *challenge_header; - char *response_header; -#endif #endif #ifdef USE_SPNEGO @@ -1082,6 +1113,8 @@ struct connectdata { handle */ BIT(writechannel_inuse); /* whether the write channel is in use by an easy handle */ + BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with + accept() */ }; /* The end of connectdata. */ @@ -1409,6 +1442,8 @@ struct UrlState { BIT(ftp_trying_alternative); BIT(wildcardmatch); /* enable wildcard matching */ BIT(expect100header); /* TRUE if we added Expect: 100-continue */ + BIT(disableexpect); /* TRUE if Expect: is disabled due to a previous + 417 response */ BIT(use_range); BIT(rangestringalloc); /* the range string is malloc()'ed */ BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE @@ -1451,6 +1486,14 @@ struct DynamicStatic { struct Curl_multi; /* declared and used only in multi.c */ +/* + * This enumeration MUST not use conditional directives (#ifdefs), new + * null terminated strings MUST be added to the enumeration immediately + * before STRING_LASTZEROTERMINATED, binary fields immediately before + * STRING_LAST. When doing so, ensure that the packages/OS400/chkstring.c + * test is updated and applicable changes for EBCDIC to ASCII conversion + * are catered for in curl_easy_setopt_ccsid() + */ enum dupstring { STRING_CERT_ORIG, /* client certificate file name */ STRING_CERT_PROXY, /* client certificate file name */ @@ -1507,36 +1550,35 @@ enum dupstring { STRING_RTSP_SESSION_ID, /* Session ID to use */ STRING_RTSP_STREAM_URI, /* Stream URI for this request */ STRING_RTSP_TRANSPORT, /* Transport for this session */ -#ifdef USE_SSH + STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ -#endif + STRING_PROXY_SERVICE_NAME, /* Proxy service name */ STRING_SERVICE_NAME, /* Service name */ STRING_MAIL_FROM, STRING_MAIL_AUTH, -#ifdef USE_TLS_SRP STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */ STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */ STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth <password> */ STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */ -#endif + STRING_BEARER, /* <bearer>, if used */ -#ifdef USE_UNIX_SOCKETS + STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ -#endif + STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ STRING_DOH, /* CURLOPT_DOH_URL */ -#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ -#endif + STRING_SASL_AUTHZID, /* CURLOPT_SASL_AUTHZID */ -#ifndef CURL_DISABLE_PROXY + STRING_TEMP_URL, /* temp URL storage for proxy use */ -#endif + /* -- end of zero-terminated strings -- */ STRING_LASTZEROTERMINATED, @@ -1792,6 +1834,8 @@ struct UserDefined { BIT(doh); /* DNS-over-HTTPS enabled */ BIT(doh_get); /* use GET for DoH requests, instead of POST */ BIT(http09_allowed); /* allow HTTP/0.9 responses */ + BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some + recipients */ }; struct Names { diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c index 8cd4d83ed3..a8835705f3 100644 --- a/libs/libcurl/src/vauth/digest.c +++ b/libs/libcurl/src/vauth/digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -62,7 +62,7 @@ what ultimately goes over the network. */ #define CURL_OUTPUT_DIGEST_CONV(a, b) \ - result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \ + result = Curl_convert_to_network(a, b, strlen(b)); \ if(result) { \ free(b); \ return result; \ @@ -660,7 +660,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, } /* - * _Curl_auth_create_digest_http_message() + * auth_create_digest_http_message() * * This is used to generate a HTTP DIGEST response message ready for sending * to the recipient. @@ -679,7 +679,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, * * Returns CURLE_OK on success. */ -static CURLcode _Curl_auth_create_digest_http_message( +static CURLcode auth_create_digest_http_message( struct Curl_easy *data, const char *userp, const char *passwdp, @@ -688,12 +688,12 @@ static CURLcode _Curl_auth_create_digest_http_message( struct digestdata *digest, char **outptr, size_t *outlen, void (*convert_to_ascii)(unsigned char *, unsigned char *), - void (*hash)(unsigned char *, const unsigned char *)) + void (*hash)(unsigned char *, const unsigned char *, + const size_t)) { CURLcode result; unsigned char hashbuf[32]; /* 32 bytes/256 bits */ unsigned char request_digest[65]; - unsigned char *hashthis; unsigned char ha1[65]; /* 64 digits and 1 zero byte */ unsigned char ha2[65]; /* 64 digits and 1 zero byte */ char userh[65]; @@ -701,6 +701,7 @@ static CURLcode _Curl_auth_create_digest_http_message( size_t cnonce_sz = 0; char *userp_quoted; char *response = NULL; + char *hashthis = NULL; char *tmp = NULL; if(!digest->nc) @@ -722,12 +723,12 @@ static CURLcode _Curl_auth_create_digest_http_message( } if(digest->userhash) { - hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm); + hashthis = aprintf("%s:%s", userp, digest->realm); if(!hashthis) return CURLE_OUT_OF_MEMORY; CURL_OUTPUT_DIGEST_CONV(data, hashthis); - hash(hashbuf, hashthis); + hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); free(hashthis); convert_to_ascii(hashbuf, (unsigned char *)userh); } @@ -743,14 +744,13 @@ static CURLcode _Curl_auth_create_digest_http_message( unq(nonce-value) ":" unq(cnonce-value) */ - hashthis = (unsigned char *) - aprintf("%s:%s:%s", digest->userhash ? userh : userp, - digest->realm, passwdp); + hashthis = aprintf("%s:%s:%s", digest->userhash ? userh : userp, + digest->realm, passwdp); if(!hashthis) return CURLE_OUT_OF_MEMORY; CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ - hash(hashbuf, hashthis); + hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); free(hashthis); convert_to_ascii(hashbuf, ha1); @@ -763,7 +763,7 @@ static CURLcode _Curl_auth_create_digest_http_message( return CURLE_OUT_OF_MEMORY; CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */ - hash(hashbuf, (unsigned char *) tmp); + hash(hashbuf, (unsigned char *) tmp, strlen(tmp)); free(tmp); convert_to_ascii(hashbuf, ha1); } @@ -781,19 +781,19 @@ static CURLcode _Curl_auth_create_digest_http_message( 5.1.1 of RFC 2616) */ - hashthis = (unsigned char *) aprintf("%s:%s", request, uripath); + hashthis = aprintf("%s:%s", request, uripath); if(!hashthis) return CURLE_OUT_OF_MEMORY; if(digest->qop && strcasecompare(digest->qop, "auth-int")) { /* We don't support auth-int for PUT or POST */ char hashed[65]; - unsigned char *hashthis2; + char *hashthis2; - hash(hashbuf, (const unsigned char *)""); + hash(hashbuf, (const unsigned char *)"", 0); convert_to_ascii(hashbuf, (unsigned char *)hashed); - hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed); + hashthis2 = aprintf("%s:%s", hashthis, hashed); free(hashthis); hashthis = hashthis2; } @@ -802,31 +802,23 @@ static CURLcode _Curl_auth_create_digest_http_message( return CURLE_OUT_OF_MEMORY; CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ - hash(hashbuf, hashthis); + hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); free(hashthis); convert_to_ascii(hashbuf, ha2); if(digest->qop) { - hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s", - ha1, - digest->nonce, - digest->nc, - digest->cnonce, - digest->qop, - ha2); + hashthis = aprintf("%s:%s:%08x:%s:%s:%s", ha1, digest->nonce, digest->nc, + digest->cnonce, digest->qop, ha2); } else { - hashthis = (unsigned char *) aprintf("%s:%s:%s", - ha1, - digest->nonce, - ha2); + hashthis = aprintf("%s:%s:%s", ha1, digest->nonce, ha2); } if(!hashthis) return CURLE_OUT_OF_MEMORY; CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ - hash(hashbuf, hashthis); + hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); free(hashthis); convert_to_ascii(hashbuf, request_digest); @@ -899,7 +891,7 @@ static CURLcode _Curl_auth_create_digest_http_message( if(digest->algorithm) { /* Append the algorithm */ - tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm); + tmp = aprintf("%s, algorithm=%s", response, digest->algorithm); free(response); if(!tmp) return CURLE_OUT_OF_MEMORY; @@ -955,21 +947,21 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, switch(digest->algo) { case CURLDIGESTALGO_MD5: case CURLDIGESTALGO_MD5SESS: - return _Curl_auth_create_digest_http_message(data, userp, passwdp, - request, uripath, digest, - outptr, outlen, - auth_digest_md5_to_ascii, - Curl_md5it); + return auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_md5_to_ascii, + Curl_md5it); case CURLDIGESTALGO_SHA256: case CURLDIGESTALGO_SHA256SESS: case CURLDIGESTALGO_SHA512_256: case CURLDIGESTALGO_SHA512_256SESS: - return _Curl_auth_create_digest_http_message(data, userp, passwdp, - request, uripath, digest, - outptr, outlen, - auth_digest_sha256_to_ascii, - Curl_sha256it); + return auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_sha256_to_ascii, + Curl_sha256it); default: return CURLE_UNSUPPORTED_PROTOCOL; diff --git a/libs/libcurl/src/vauth/ntlm.c b/libs/libcurl/src/vauth/ntlm.c index 047c2b5a3f..8f91038064 100644 --- a/libs/libcurl/src/vauth/ntlm.c +++ b/libs/libcurl/src/vauth/ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -40,6 +40,7 @@ #include "curl_ntlm_core.h" #include "curl_gethostname.h" #include "curl_multibyte.h" +#include "curl_md5.h" #include "warnless.h" #include "rand.h" #include "vtls/vtls.h" @@ -621,11 +622,11 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, memcpy(tmp, &ntlm->nonce[0], 8); memcpy(tmp + 8, entropy, 8); - result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); - if(!result) - /* We shall only use the first 8 bytes of md5sum, but the des code in - Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ - result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + Curl_md5it(md5sum, tmp, 16); + + /* We shall only use the first 8 bytes of md5sum, but the des code in + Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) return result; diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index 6405d369d7..77aca7cbe8 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -265,8 +265,10 @@ static const char * const protocols[] = { #ifndef CURL_DISABLE_RTSP "rtsp", #endif -#if defined(USE_SSH) +#if defined(USE_SSH) && !defined(USE_WOLFSSH) "scp", +#endif +#ifdef USE_SSH "sftp", #endif #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ diff --git a/libs/libcurl/src/vquic/ngtcp2.c b/libs/libcurl/src/vquic/ngtcp2.c index e97e9e871b..0788404c02 100644 --- a/libs/libcurl/src/vquic/ngtcp2.c +++ b/libs/libcurl/src/vquic/ngtcp2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -146,7 +146,7 @@ static void quic_settings(ngtcp2_settings *s, s->transport_params.initial_max_data = QUIC_MAX_DATA; s->transport_params.initial_max_streams_bidi = 1; s->transport_params.initial_max_streams_uni = 3; - s->transport_params.idle_timeout = QUIC_IDLE_TIMEOUT; + s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT; } static FILE *keylog_file; /* not thread-safe */ @@ -535,6 +535,8 @@ static ngtcp2_conn_callbacks ng_callbacks = { NULL, /* extend_max_remote_streams_bidi */ NULL, /* extend_max_remote_streams_uni */ cb_extend_max_stream_data, + NULL, /* dcid_status */ + NULL /* handshake_confirmed */ }; /* @@ -574,10 +576,10 @@ CURLcode Curl_quic_connect(struct connectdata *conn, qs->version = NGTCP2_PROTO_VER; qs->sslctx = quic_ssl_ctx(data); if(!qs->sslctx) - return CURLE_FAILED_INIT; /* TODO: better return code */ + return CURLE_QUIC_CONNECT_ERROR; if(quic_init_ssl(qs)) - return CURLE_FAILED_INIT; /* TODO: better return code */ + return CURLE_QUIC_CONNECT_ERROR; qs->dcid.datalen = NGTCP2_MAX_CIDLEN; result = Curl_rand(data, qs->dcid.data, NGTCP2_MAX_CIDLEN); @@ -595,7 +597,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr, &qs->local_addrlen); if(rv == -1) - return CURLE_FAILED_INIT; + return CURLE_QUIC_CONNECT_ERROR; ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, qs->local_addrlen, NULL); @@ -609,7 +611,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, QUICVER, &ng_callbacks, &qs->settings, NULL, qs); if(rc) - return CURLE_FAILED_INIT; /* TODO: create a QUIC error code */ + return CURLE_QUIC_CONNECT_ERROR; ngtcp2_conn_get_local_transport_params(qs->qconn, ¶ms); nwrite = ngtcp2_encode_transport_params( @@ -618,15 +620,15 @@ CURLcode Curl_quic_connect(struct connectdata *conn, if(nwrite < 0) { failf(data, "ngtcp2_encode_transport_params: %s\n", ngtcp2_strerror((int)nwrite)); - return CURLE_FAILED_INIT; + return CURLE_QUIC_CONNECT_ERROR; } if(!SSL_set_quic_transport_params(qs->ssl, paramsbuf, nwrite)) - return CURLE_FAILED_INIT; + return CURLE_QUIC_CONNECT_ERROR; rc = setup_initial_crypto_context(qs); if(rc) - return CURLE_FAILED_INIT; /* TODO: better return code */ + return CURLE_QUIC_CONNECT_ERROR; return CURLE_OK; } @@ -998,7 +1000,7 @@ static int init_ngh3_conn(struct quicsocket *qs) if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) { failf(qs->conn->data, "too few available QUIC streams"); - return CURLE_FAILED_INIT; + return CURLE_QUIC_CONNECT_ERROR; } nghttp3_conn_settings_default(&qs->h3settings); @@ -1015,32 +1017,32 @@ static int init_ngh3_conn(struct quicsocket *qs) rc = ngtcp2_conn_open_uni_stream(qs->qconn, &ctrl_stream_id, NULL); if(rc) { - result = CURLE_FAILED_INIT; + result = CURLE_QUIC_CONNECT_ERROR; goto fail; } rc = nghttp3_conn_bind_control_stream(qs->h3conn, ctrl_stream_id); if(rc) { - result = CURLE_FAILED_INIT; + result = CURLE_QUIC_CONNECT_ERROR; goto fail; } rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_enc_stream_id, NULL); if(rc) { - result = CURLE_FAILED_INIT; + result = CURLE_QUIC_CONNECT_ERROR; goto fail; } rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_dec_stream_id, NULL); if(rc) { - result = CURLE_FAILED_INIT; + result = CURLE_QUIC_CONNECT_ERROR; goto fail; } rc = nghttp3_conn_bind_qpack_streams(qs->h3conn, qpack_enc_stream_id, qpack_dec_stream_id); if(rc) { - result = CURLE_FAILED_INIT; + result = CURLE_QUIC_CONNECT_ERROR; goto fail; } @@ -1599,9 +1601,11 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, case AF_INET: pktlen = NGTCP2_MAX_PKTLEN_IPV4; break; +#ifdef ENABLE_IPV6 case AF_INET6: pktlen = NGTCP2_MAX_PKTLEN_IPV6; break; +#endif default: assert(0); } diff --git a/libs/libcurl/src/vquic/quiche.c b/libs/libcurl/src/vquic/quiche.c index e2f43237fa..d09ba7038a 100644 --- a/libs/libcurl/src/vquic/quiche.c +++ b/libs/libcurl/src/vquic/quiche.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -171,7 +171,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd, return CURLE_FAILED_INIT; } - quiche_config_set_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT); + quiche_config_set_max_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT); quiche_config_set_initial_max_data(qs->cfg, QUIC_MAX_DATA); quiche_config_set_initial_max_stream_data_bidi_local(qs->cfg, QUIC_MAX_DATA); quiche_config_set_initial_max_stream_data_bidi_remote(qs->cfg, diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index 62a7f1960c..647b4d4913 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2017 - 2019 Red Hat, Inc. + * Copyright (C) 2017 - 2020 Red Hat, Inc. * * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, * Robert Kolcun, Andreas Schneider @@ -322,14 +322,25 @@ static int myssh_is_known(struct connectdata *conn) ssh_key pubkey; size_t hlen; unsigned char *hash = NULL; - char *base64 = NULL; + char *found_base64 = NULL; + char *known_base64 = NULL; int vstate; enum curl_khmatch keymatch; struct curl_khkey foundkey; + 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; @@ -354,6 +365,65 @@ static int myssh_is_known(struct connectdata *conn) goto cleanup; } +#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); + + /* Case an entry was found in a known hosts file */ + if(knownhostsentry) { + if(knownhostsentry->publickey) { + rc = ssh_pki_export_pubkey_base64(knownhostsentry->publickey, + &known_base64); + if(rc != SSH_OK) { + goto cleanup; + } + knownkey.key = known_base64; + knownkey.len = strlen(known_base64); + + switch(ssh_key_type(knownhostsentry->publickey)) { + case SSH_KEYTYPE_RSA: + knownkey.keytype = CURLKHTYPE_RSA; + break; + case SSH_KEYTYPE_RSA1: + knownkey.keytype = CURLKHTYPE_RSA1; + break; + case SSH_KEYTYPE_ECDSA: + knownkey.keytype = CURLKHTYPE_ECDSA; + break; + case SSH_KEYTYPE_ED25519: + knownkey.keytype = CURLKHTYPE_ED25519; + break; + case SSH_KEYTYPE_DSS: + knownkey.keytype = CURLKHTYPE_DSS; + break; + default: + rc = SSH_ERROR; + goto cleanup; + } + knownkeyp = &knownkey; + } + } + + switch(vstate) { + case SSH_KNOWN_HOSTS_OK: + keymatch = CURLKHMATCH_OK; + break; + case SSH_KNOWN_HOSTS_OTHER: + /* fallthrough */ + case SSH_KNOWN_HOSTS_NOT_FOUND: + /* fallthrough */ + case SSH_KNOWN_HOSTS_UNKNOWN: + /* fallthrough */ + case SSH_KNOWN_HOSTS_ERROR: + keymatch = CURLKHMATCH_MISSING; + break; + default: + keymatch = CURLKHMATCH_MISMATCH; + break; + } + +#else vstate = ssh_is_server_known(sshc->ssh_session); switch(vstate) { case SSH_SERVER_KNOWN_OK: @@ -368,14 +438,15 @@ static int myssh_is_known(struct connectdata *conn) keymatch = CURLKHMATCH_MISMATCH; break; } +#endif if(func) { /* use callback to determine action */ - rc = ssh_pki_export_pubkey_base64(pubkey, &base64); + rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64); if(rc != SSH_OK) goto cleanup; - foundkey.key = base64; - foundkey.len = strlen(base64); + foundkey.key = found_base64; + foundkey.len = strlen(found_base64); switch(ssh_key_type(pubkey)) { case SSH_KEYTYPE_RSA: @@ -400,15 +471,19 @@ static int myssh_is_known(struct connectdata *conn) goto cleanup; } - /* we don't have anything equivalent to knownkey. Always NULL */ Curl_set_in_callback(data, true); - rc = func(data, NULL, &foundkey, /* from the remote host */ + rc = func(data, knownkeyp, /* from the knownhosts file */ + &foundkey, /* from the remote host */ keymatch, data->set.ssh_keyfunc_userp); Curl_set_in_callback(data, false); 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; } @@ -429,9 +504,20 @@ static int myssh_is_known(struct connectdata *conn) rc = SSH_OK; cleanup: + if(found_base64) { + free(found_base64); + } + if(known_base64) { + free(known_base64); + } 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; } @@ -1586,7 +1672,6 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) return CURLE_BAD_DOWNLOAD_RESUME; } } - /* Does a completed file need to be seeked and started or closed ? */ /* Now store the number of bytes we are expected to download */ data->req.size = size - data->state.resume_from; data->req.maxdownload = size - data->state.resume_from; diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index 063f3d2ae6..8e043747e7 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -106,6 +106,7 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); static LIBSSH2_FREE_FUNC(my_libssh2_free); +static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn); static CURLcode ssh_connect(struct connectdata *conn, bool *done); static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); static CURLcode ssh_do(struct connectdata *conn, bool *done); @@ -649,6 +650,129 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) } /* + * ssh_force_knownhost_key_type() will check the known hosts file and try to + * force a specific public key type from the server if an entry is found. + */ +static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + +#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519 + static const char * const hostkey_method_ssh_ed25519 + = "ssh-ed25519"; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521 + static const char * const hostkey_method_ssh_ecdsa_521 + = "ecdsa-sha2-nistp521"; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384 + static const char * const hostkey_method_ssh_ecdsa_384 + = "ecdsa-sha2-nistp384"; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256 + static const char * const hostkey_method_ssh_ecdsa_256 + = "ecdsa-sha2-nistp256"; +#endif + static const char * const hostkey_method_ssh_rsa + = "ssh-rsa"; + static const char * const hostkey_method_ssh_dss + = "ssh-dss"; + + const char *hostkey_method = NULL; + struct ssh_conn *sshc = &conn->proto.sshc; + struct Curl_easy *data = conn->data; + struct libssh2_knownhost* store = NULL; + const char *kh_name_end = NULL; + size_t kh_name_size = 0; + int port = 0; + bool found = false; + + if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) { + /* lets try to find our host in the known hosts file */ + while(!libssh2_knownhost_get(sshc->kh, &store, store)) { + /* For non-standard ports, the name will be enclosed in */ + /* square brackets, followed by a colon and the port */ + if(store->name[0] == '[') { + kh_name_end = strstr(store->name, "]:"); + if(!kh_name_end) { + infof(data, "Invalid host pattern %s in %s\n", + store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); + continue; + } + port = atoi(kh_name_end + 2); + if(kh_name_end && (port == conn->remote_port)) { + kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end); + if(strncmp(store->name + 1, conn->host.name, kh_name_size) == 0) { + found = true; + break; + } + } + } + else if(strcmp(store->name, conn->host.name) == 0) { + found = true; + break; + } + } + + if(found) { + infof(data, "Found host %s in %s\n", + store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); + + switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) { +#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519 + case LIBSSH2_KNOWNHOST_KEY_ED25519: + hostkey_method = hostkey_method_ssh_ed25519; + break; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521 + case LIBSSH2_KNOWNHOST_KEY_ECDSA_521: + hostkey_method = hostkey_method_ssh_ecdsa_521; + break; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384 + case LIBSSH2_KNOWNHOST_KEY_ECDSA_384: + hostkey_method = hostkey_method_ssh_ecdsa_384; + break; +#endif +#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256 + case LIBSSH2_KNOWNHOST_KEY_ECDSA_256: + hostkey_method = hostkey_method_ssh_ecdsa_256; + break; +#endif + case LIBSSH2_KNOWNHOST_KEY_SSHRSA: + hostkey_method = hostkey_method_ssh_rsa; + break; + case LIBSSH2_KNOWNHOST_KEY_SSHDSS: + hostkey_method = hostkey_method_ssh_dss; + break; + case LIBSSH2_KNOWNHOST_KEY_RSA1: + failf(data, "Found host key type RSA1 which is not supported\n"); + return CURLE_SSH; + default: + failf(data, "Unknown host key type: %i\n", + (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK)); + return CURLE_SSH; + } + + infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method); + result = libssh2_session_error_to_CURLE( + libssh2_session_method_pref( + sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method)); + } + else { + infof(data, "Did not find host %s in %s\n", + conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); + } + } + +#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ + + return result; +} + +/* * ssh_statemach_act() runs the SSH state machine as far as it can without * blocking and without reaching the end. The data the pointer 'block' points * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN @@ -680,6 +804,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) non-blocking */ libssh2_session_set_blocking(sshc->ssh_session, 0); + result = ssh_force_knownhost_key_type(conn); + if(result) { + state(conn, SSH_SESSION_FREE); + break; + } + state(conn, SSH_S_STARTUP); /* FALLTHROUGH */ @@ -2251,7 +2381,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) return CURLE_BAD_DOWNLOAD_RESUME; } } - /* Does a completed file need to be seeked and started or closed ? */ /* Now store the number of bytes we are expected to download */ data->req.size = attrs.filesize - data->state.resume_from; data->req.maxdownload = attrs.filesize - data->state.resume_from; diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index 3213c5a52e..0d4ee521d1 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -30,7 +30,10 @@ #elif defined(HAVE_LIBSSH_LIBSSH_H) #include <libssh/libssh.h> #include <libssh/sftp.h> -#endif /* HAVE_LIBSSH2_H */ +#elif defined(USE_WOLFSSH) +#include <wolfssh/ssh.h> +#include <wolfssh/wolfsftp.h> +#endif /**************************************************************************** * SSH unique setup @@ -188,6 +191,12 @@ struct ssh_conn { #ifdef HAVE_LIBSSH2_KNOWNHOST_API LIBSSH2_KNOWNHOSTS *kh; #endif +#elif defined(USE_WOLFSSH) + WOLFSSH *ssh_session; + WOLFSSH_CTX *ctx; + word32 handleSz; + byte handle[WOLFSSH_MAX_HANDLE]; + curl_off_t offset; #endif /* USE_LIBSSH */ }; @@ -195,9 +204,6 @@ struct ssh_conn { #define CURL_LIBSSH_VERSION ssh_version(0) -extern const struct Curl_handler Curl_handler_scp; -extern const struct Curl_handler Curl_handler_sftp; - #elif defined(USE_LIBSSH2) /* Feature detection based on version numbers to better work with @@ -237,11 +243,13 @@ extern const struct Curl_handler Curl_handler_sftp; #define CURL_LIBSSH2_VERSION LIBSSH2_VERSION #endif -extern const struct Curl_handler Curl_handler_scp; -extern const struct Curl_handler Curl_handler_sftp; #endif /* USE_LIBSSH2 */ #ifdef USE_SSH + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + /* generic SSH backend functions */ CURLcode Curl_ssh_init(void); void Curl_ssh_cleanup(void); diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c new file mode 100644 index 0000000000..363a52c772 --- /dev/null +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -0,0 +1,1156 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019 - 2020, 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. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WOLFSSH + +#include <limits.h> + +#include <wolfssh/ssh.h> +#include <wolfssh/wolfsftp.h> +#include "urldata.h" +#include "connect.h" +#include "sendf.h" +#include "progress.h" +#include "curl_path.h" +#include "strtoofft.h" +#include "transfer.h" +#include "speedcheck.h" +#include "select.h" +#include "multiif.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static CURLcode wssh_connect(struct connectdata *conn, bool *done); +static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode wssh_do(struct connectdata *conn, bool *done); +#if 0 +static CURLcode wscp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode wscp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode wscp_disconnect(struct connectdata *conn, + bool dead_connection); +#endif +static CURLcode wsftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode wsftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead); +static int wssh_getsock(struct connectdata *conn, + curl_socket_t *sock); +static int wssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock); +static CURLcode wssh_setup_connection(struct connectdata *conn); + +#if 0 +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + wssh_setup_connection, /* setup_connection */ + wssh_do, /* do_it */ + wscp_done, /* done */ + ZERO_NULL, /* do_more */ + wssh_connect, /* connect_it */ + wssh_multi_statemach, /* connecting */ + wscp_doing, /* doing */ + wssh_getsock, /* proto_getsock */ + wssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + wssh_perform_getsock, /* perform_getsock */ + wscp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +#endif + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + wssh_setup_connection, /* setup_connection */ + wssh_do, /* do_it */ + wsftp_done, /* done */ + ZERO_NULL, /* do_more */ + wssh_connect, /* connect_it */ + wssh_multi_statemach, /* connecting */ + wsftp_doing, /* doing */ + wssh_getsock, /* proto_getsock */ + wssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + wssh_perform_getsock, /* perform_getsock */ + wsftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void state(struct connectdata *conn, sshstate nowstate) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_GSSAPI", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_QUOTE_STATVFS", + "SSH_SFTP_GETINFO", + "SSH_SFTP_FILETIME", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DOWNLOAD", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + /* a precaution to make sure the lists are in sync */ + DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); + + if(sshc->state != nowstate) { + infof(conn->data, "wolfssh %p state change from %s to %s\n", + (void *)sshc, names[sshc->state], names[nowstate]); + } +#endif + + sshc->state = nowstate; +} + +static ssize_t wscp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite = 0; + (void)conn; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + (void)mem; + (void)len; + (void)err; + + return nwrite; +} + +static ssize_t wscp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread = 0; + (void)conn; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + (void)mem; + (void)len; + (void)err; + + return nread; +} + +/* return number of sent bytes */ +static ssize_t wsftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + word32 offset[2]; + int rc; + (void)sockindex; + + offset[0] = (word32)sshc->offset&0xFFFFFFFF; + offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; + + rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle, + sshc->handleSz, + &offset[0], + (byte *)mem, (word32)len); + + if(rc == WS_FATAL_ERROR) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + conn->waitfor = KEEP_RECV; + *err = CURLE_AGAIN; + return -1; + } + else if(rc == WS_WANT_WRITE) { + conn->waitfor = KEEP_SEND; + *err = CURLE_AGAIN; + return -1; + } + if(rc < 0) { + failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc); + return -1; + } + DEBUGASSERT(rc == (int)len); + infof(conn->data, "sent %zd bytes SFTP from offset %zd\n", + len, sshc->offset); + sshc->offset += len; + return (ssize_t)rc; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t wsftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + int rc; + struct ssh_conn *sshc = &conn->proto.sshc; + word32 offset[2]; + (void)sockindex; + + offset[0] = (word32)sshc->offset&0xFFFFFFFF; + offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; + + rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle, + sshc->handleSz, + &offset[0], + (byte *)mem, (word32)len); + if(rc == WS_FATAL_ERROR) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + conn->waitfor = KEEP_RECV; + *err = CURLE_AGAIN; + return -1; + } + else if(rc == WS_WANT_WRITE) { + conn->waitfor = KEEP_SEND; + *err = CURLE_AGAIN; + return -1; + } + + DEBUGASSERT(rc <= (int)len); + + if(rc < 0) { + failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc); + return -1; + } + sshc->offset += len; + + return (ssize_t)rc; +} + +/* + * SSH setup and connection + */ +static CURLcode wssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv wscp_recv, wsftp_recv; +static Curl_send wscp_send, wsftp_send; + +static int userauth(byte authtype, + WS_UserAuthData* authdata, + void *ctx) +{ + struct connectdata *conn = ctx; + DEBUGF(infof(conn->data, "wolfssh callback: type %s\n", + authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" : + "PUBLICCKEY")); + if(authtype == WOLFSSH_USERAUTH_PASSWORD) { + authdata->sf.password.password = (byte *)conn->passwd; + authdata->sf.password.passwordSz = (word32) strlen(conn->passwd); + } + + return 0; +} + +static CURLcode wssh_connect(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + wssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = wscp_recv; + conn->send[FIRSTSOCKET] = wscp_send; + } + else { + conn->recv[FIRSTSOCKET] = wsftp_recv; + conn->send[FIRSTSOCKET] = wsftp_send; + } + sshc = &conn->proto.sshc; + sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL); + if(!sshc->ctx) { + failf(data, "No wolfSSH context"); + goto error; + } + + sshc->ssh_session = wolfSSH_new(sshc->ctx); + if(sshc->ssh_session == NULL) { + failf(data, "No wolfSSH session"); + goto error; + } + + rc = wolfSSH_SetUsername(sshc->ssh_session, conn->user); + if(rc != WS_SUCCESS) { + failf(data, "wolfSSH failed to set user name"); + goto error; + } + + /* set callback for authentication */ + wolfSSH_SetUserAuth(sshc->ctx, userauth); + wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn); + + rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock); + if(rc) { + failf(data, "wolfSSH failed to set socket"); + goto error; + } + +#if 0 + wolfSSH_Debugging_ON(); +#endif + + *done = TRUE; + if(conn->handler->protocol & CURLPROTO_SCP) + state(conn, SSH_INIT); + else + state(conn, SSH_SFTP_INIT); + + return wssh_multi_statemach(conn, done); + error: + wolfSSH_free(sshc->ssh_session); + wolfSSH_CTX_free(sshc->ctx); + return CURLE_FAILED_INIT; +} + +/* + * wssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the wolfssh function returns EAGAIN meaning it + * wants to be called again when the socket is ready + */ + +static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *sshc = &conn->proto.sshc; + struct Curl_easy *data = conn->data; + struct SSHPROTO *sftp_scp = data->req.protop; + WS_SFTPNAME *name; + int rc = 0; + *block = FALSE; /* we're not blocking by default */ + + do { + switch(sshc->state) { + case SSH_INIT: + state(conn, SSH_S_STARTUP); + /* FALLTHROUGH */ + case SSH_S_STARTUP: + rc = wolfSSH_connect(sshc->ssh_session); + if(rc != WS_SUCCESS) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc != WS_SUCCESS) { + state(conn, SSH_STOP); + return CURLE_SSH; + } + infof(data, "wolfssh connected!\n"); + state(conn, SSH_STOP); + break; + case SSH_STOP: + break; + + case SSH_SFTP_INIT: + rc = wolfSSH_SFTP_connect(sshc->ssh_session); + if(rc != WS_SUCCESS) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc == WS_SUCCESS) { + infof(data, "wolfssh SFTP connected!\n"); + state(conn, SSH_SFTP_REALPATH); + } + else { + failf(data, "wolfssh SFTP connect error %d", rc); + return CURLE_SSH; + } + break; + case SSH_SFTP_REALPATH: + name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)"."); + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(name && (rc == WS_SUCCESS)) { + sshc->homedir = malloc(name->fSz + 1); + if(!sshc->homedir) { + sshc->actualcode = CURLE_OUT_OF_MEMORY; + } + else { + memcpy(sshc->homedir, name->fName, name->fSz); + sshc->homedir[name->fSz] = 0; + infof(data, "wolfssh SFTP realpath succeeded!\n"); + } + wolfSSH_SFTPNAME_list_free(name); + state(conn, SSH_STOP); + return CURLE_OK; + } + failf(data, "wolfssh SFTP realpath %d", rc); + return CURLE_SSH; + + case SSH_SFTP_QUOTE_INIT: + result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_GETINFO); + } + break; + case SSH_SFTP_GETINFO: + if(data->set.get_filetime) { + state(conn, SSH_SFTP_FILETIME); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + case SSH_SFTP_UPLOAD_INIT: { + word32 flags; + WS_SFTP_FILEATRB createattrs; + if(data->state.resume_from) { + WS_SFTP_FILEATRB attrs; + if(data->state.resume_from < 0) { + rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, + &attrs); + if(rc != WS_SUCCESS) + break; + + if(rc) { + data->state.resume_from = 0; + } + else { + curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0]; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + data->state.resume_from = size; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC; + + memset(&createattrs, 0, sizeof(createattrs)); + createattrs.per = (word32)data->set.new_file_perms; + sshc->handleSz = sizeof(sshc->handle); + rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, + flags, &createattrs, + sshc->handle, &sshc->handleSz); + if(rc == WS_FATAL_ERROR) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc == WS_SUCCESS) { + infof(data, "wolfssh SFTP open succeeded!\n"); + } + else { + failf(data, "wolfssh SFTP upload open failed: %d", rc); + return CURLE_SSH; + } + state(conn, SSH_SFTP_DOWNLOAD_STAT); + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + int seekerr = CURL_SEEKFUNC_OK; + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread; + Curl_set_in_callback(data, true); + actuallyread = data->state.fread_func(data->state.buffer, 1, + readthisamountnow, + data->state.in); + Curl_set_in_callback(data, false); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + sshc->offset += data->state.resume_from; + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + state(conn, SSH_STOP); + } + break; + } + case SSH_SFTP_DOWNLOAD_INIT: + sshc->handleSz = sizeof(sshc->handle); + rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, + WOLFSSH_FXF_READ, NULL, + sshc->handle, &sshc->handleSz); + if(rc == WS_FATAL_ERROR) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc == WS_SUCCESS) { + infof(data, "wolfssh SFTP open succeeded!\n"); + state(conn, SSH_SFTP_DOWNLOAD_STAT); + return CURLE_OK; + } + + failf(data, "wolfssh SFTP open failed: %d", rc); + return CURLE_SSH; + + case SSH_SFTP_DOWNLOAD_STAT: { + WS_SFTP_FILEATRB attrs; + curl_off_t size; + + rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, &attrs); + if(rc == WS_FATAL_ERROR) + rc = wolfSSH_get_error(sshc->ssh_session); + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc == WS_SUCCESS) { + infof(data, "wolfssh STAT succeeded!\n"); + } + else { + failf(data, "wolfssh SFTP open failed: %d", rc); + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + return CURLE_SSH; + } + + size = ((curl_off_t)attrs.sz[1] <<32) | attrs.sz[0]; + + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + + infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size); + + /* We cannot seek with wolfSSH so resuming and range requests are not + possible */ + if(conn->data->state.use_range || data->state.resume_from) { + infof(data, "wolfSSH cannot do range/seek on SFTP\n"); + return CURLE_BAD_DOWNLOAD_RESUME; + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + state(conn, SSH_STOP); + } + break; + } + case SSH_SFTP_CLOSE: + if(sshc->handleSz) + rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle, + sshc->handleSz); + else + rc = WS_SUCCESS; /* directory listing */ + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(rc == WS_SUCCESS) { + state(conn, SSH_STOP); + return CURLE_OK; + } + + failf(data, "wolfssh SFTP CLOSE failed: %d", rc); + return CURLE_SSH; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + state(conn, SSH_SFTP_READDIR); + /* FALLTHROUGH */ + case SSH_SFTP_READDIR: + name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path); + if(!name) + rc = wolfSSH_get_error(sshc->ssh_session); + else + rc = WS_SUCCESS; + + if(rc == WS_WANT_READ) { + *block = TRUE; + conn->waitfor = KEEP_RECV; + return CURLE_OK; + } + else if(rc == WS_WANT_WRITE) { + *block = TRUE; + conn->waitfor = KEEP_SEND; + return CURLE_OK; + } + else if(name && (rc == WS_SUCCESS)) { + WS_SFTPNAME *origname = name; + result = CURLE_OK; + while(name) { + char *line = aprintf("%s\n", + data->set.ftp_list_only ? + name->fName : name->lName); + if(line == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + line, strlen(line)); + free(line); + if(result) { + sshc->actualcode = result; + break; + } + name = name->next; + } + wolfSSH_SFTPNAME_list_free(origname); + state(conn, SSH_STOP); + return result; + } + failf(data, "wolfssh SFTP ls failed: %d", rc); + return CURLE_SSH; + + case SSH_SFTP_SHUTDOWN: + Curl_safefree(sshc->homedir); + wolfSSH_free(sshc->ssh_session); + wolfSSH_CTX_free(sshc->ctx); + state(conn, SSH_STOP); + return CURLE_OK; + default: + break; + } + } while(!rc && (sshc->state != SSH_STOP)); + return result; +} + +/* called repeatedly until done from multi.c */ +static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + do { + result = wssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then + try again */ + if(*done) { + DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n")); + } + } while(!result && !*done && !block); + + return result; +} + +static +CURLcode wscp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + (void)conn; + (void)connected; + (void)dophase_done; + return CURLE_OK; +} + +static +CURLcode wsftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = wssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* + * The DO function is generic for both protocols. + */ +static CURLcode wssh_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + data->req.size = -1; /* make sure this is unknown at this point */ + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs = 0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = wscp_perform(conn, &connected, done); + else + result = wsftp_perform(conn, &connected, done); + + return result; +} + +static CURLcode wssh_block_statemach(struct connectdata *conn, + bool disconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + timediff_t left = 1000; + struct curltime now = Curl_now(); + + result = wssh_statemach_act(conn, &block); + if(result) + break; + + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + result = Curl_speedcheck(data, now); + if(result) + break; + + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + } + + if(!result) { + int dir = conn->waitfor; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + curl_socket_t fd_read = CURL_SOCKET_BAD; + curl_socket_t fd_write = CURL_SOCKET_BAD; + if(dir == KEEP_RECV) + fd_read = sock; + else if(dir == KEEP_SEND) + fd_write = sock; + + /* wait for the socket to become ready */ + (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, + left>1000?1000:left); /* ignore result */ + } + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode wssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *sftp_scp = conn->data->req.protop; + + if(!status) { + /* run the state-machine */ + result = wssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(sftp_scp) + Curl_safefree(sftp_scp->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + +#if 0 +static CURLcode wscp_done(struct connectdata *conn, + CURLcode code, bool premature) +{ + CURLcode result = CURLE_OK; + (void)conn; + (void)code; + (void)premature; + + return result; +} + +static CURLcode wscp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + (void)conn; + (void)dophase_done; + + return result; +} + +static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void)conn; + (void)dead_connection; + + return result; +} +#endif + +static CURLcode wsftp_done(struct connectdata *conn, + CURLcode code, bool premature) +{ + (void)premature; + state(conn, SSH_SFTP_CLOSE); + + return wssh_done(conn, code); +} + +static CURLcode wsftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = wssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead) +{ + CURLcode result = CURLE_OK; + (void)dead; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = wssh_block_statemach(conn, TRUE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + return result; +} + +static int wssh_getsock(struct connectdata *conn, + curl_socket_t *sock) +{ + return wssh_perform_getsock(conn, sock); +} + +static int wssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock) +{ + int bitmap = GETSOCK_BLANK; + int dir = conn->waitfor; + sock[0] = conn->sock[FIRSTSOCKET]; + + if(dir == KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + else if(dir == KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +size_t Curl_ssh_version(char *buffer, size_t buflen) +{ + return msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING); +} + +CURLcode Curl_ssh_init(void) +{ + if(WS_SUCCESS != wolfSSH_Init()) { + DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); + return CURLE_FAILED_INIT; + } + + return CURLE_OK; +} +void Curl_ssh_cleanup(void) +{ +} + +#endif /* USE_WOLFSSH */ diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index 3737d7c685..5f740eeba1 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -666,6 +666,10 @@ gtls_connect_step1(struct connectdata *conn, /* Initialize TLS session as a client */ init_flags = GNUTLS_CLIENT; +#if defined(GNUTLS_FORCE_CLIENT_CERT) + init_flags |= GNUTLS_FORCE_CLIENT_CERT; +#endif + #if defined(GNUTLS_NO_TICKETS) /* Disable TLS session tickets */ init_flags |= GNUTLS_NO_TICKETS; diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index e34ec9d13f..f057315f30 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, 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 @@ -55,7 +55,7 @@ #include "connect.h" /* for the connect timeout */ #include "select.h" #include "multiif.h" -#include "polarssl_threadlock.h" +#include "mbedtls_threadlock.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -91,12 +91,12 @@ static int entropy_init_initialized = 0; static void entropy_init_mutex(mbedtls_entropy_context *ctx) { /* lock 0 = entropy_init_mutex() */ - Curl_polarsslthreadlock_lock_function(0); + Curl_mbedtlsthreadlock_lock_function(0); if(entropy_init_initialized == 0) { mbedtls_entropy_init(ctx); entropy_init_initialized = 1; } - Curl_polarsslthreadlock_unlock_function(0); + Curl_mbedtlsthreadlock_unlock_function(0); } /* end of entropy_init_mutex() */ @@ -105,9 +105,9 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len) { int ret; /* lock 1 = entropy_func_mutex() */ - Curl_polarsslthreadlock_lock_function(1); + Curl_mbedtlsthreadlock_lock_function(1); ret = mbedtls_entropy_func(data, output, len); - Curl_polarsslthreadlock_unlock_function(1); + Curl_mbedtlsthreadlock_unlock_function(1); return ret; } @@ -1017,12 +1017,12 @@ static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) */ static int Curl_mbedtls_init(void) { - return Curl_polarsslthreadlock_thread_setup(); + return Curl_mbedtlsthreadlock_thread_setup(); } static void Curl_mbedtls_cleanup(void) { - (void)Curl_polarsslthreadlock_thread_cleanup(); + (void)Curl_mbedtlsthreadlock_thread_cleanup(); } static bool Curl_mbedtls_data_pending(const struct connectdata *conn, diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c new file mode 100644 index 0000000000..4d672f106e --- /dev/null +++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> + * + * 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. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_MBEDTLS) && \ + ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))) + +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) +# include <pthread.h> +# define MBEDTLS_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) +# include <process.h> +# define MBEDTLS_MUTEX_T HANDLE +#endif + +#include "mbedtls_threadlock.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* number of thread locks */ +#define NUMT 2 + +/* This array will store all of the mutexes available to Mbedtls. */ +static MBEDTLS_MUTEX_T *mutex_buf = NULL; + +int Curl_mbedtlsthreadlock_thread_setup(void) +{ + int i; + + mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1); + if(!mutex_buf) + return 0; /* error, no number of threads defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_init(&mutex_buf[i], NULL); + if(ret) + return 0; /* pthread_mutex_init failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + mutex_buf[i] = CreateMutex(0, FALSE, 0); + if(mutex_buf[i] == 0) + return 0; /* CreateMutex failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + + return 1; /* OK */ +} + +int Curl_mbedtlsthreadlock_thread_cleanup(void) +{ + int i; + + if(!mutex_buf) + return 0; /* error, no threads locks defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_destroy(&mutex_buf[i]); + if(ret) + return 0; /* pthread_mutex_destroy failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = CloseHandle(mutex_buf[i]); + if(!ret) + return 0; /* CloseHandle failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + free(mutex_buf); + mutex_buf = NULL; + + return 1; /* OK */ +} + +int Curl_mbedtlsthreadlock_lock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_lock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: mbedtlsthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: mbedtlsthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +int Curl_mbedtlsthreadlock_unlock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_unlock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: mbedtlsthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_unlock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = ReleaseMutex(mutex_buf[n]); + if(!ret) { + DEBUGF(fprintf(stderr, + "Error: mbedtlsthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +#endif /* USE_MBEDTLS */ diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.h b/libs/libcurl/src/vtls/mbedtls_threadlock.h new file mode 100644 index 0000000000..96a787d1a2 --- /dev/null +++ b/libs/libcurl/src/vtls/mbedtls_threadlock.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_MBEDTLS_THREADLOCK_H +#define HEADER_CURL_MBEDTLS_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com> + * + * 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. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)) + +int Curl_mbedtlsthreadlock_thread_setup(void); +int Curl_mbedtlsthreadlock_thread_cleanup(void); +int Curl_mbedtlsthreadlock_lock_function(int n); +int Curl_mbedtlsthreadlock_unlock_function(int n); + +#else + +#define Curl_mbedtlsthreadlock_thread_setup() 1 +#define Curl_mbedtlsthreadlock_thread_cleanup() 1 +#define Curl_mbedtlsthreadlock_lock_function(x) 1 +#define Curl_mbedtlsthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_MBEDTLS */ + +#endif /* HEADER_CURL_MBEDTLS_THREADLOCK_H */ diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 726ff6e7ca..1d09cadca8 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -2212,7 +2212,6 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) curl_ssl_version_max = SSL_CONN_CONFIG(version_max); /* convert cURL max SSL version option to OpenSSL constant */ - ossl_ssl_version_max = 0; switch(curl_ssl_version_max) { case CURL_SSLVERSION_MAX_TLSv1_0: ossl_ssl_version_max = TLS1_VERSION; @@ -3122,28 +3121,25 @@ do { \ } while(0) #endif -static int X509V3_ext(struct Curl_easy *data, +static void X509V3_ext(struct Curl_easy *data, int certnum, CONST_EXTS STACK_OF(X509_EXTENSION) *exts) { int i; - size_t j; if((int)sk_X509_EXTENSION_num(exts) <= 0) /* no extensions, bail out */ - return 1; + return; for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) { ASN1_OBJECT *obj; X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); BUF_MEM *biomem; - char buf[512]; - char *ptr = buf; char namebuf[128]; BIO *bio_out = BIO_new(BIO_s_mem()); if(!bio_out) - return 1; + return; obj = X509_EXTENSION_get_object(ext); @@ -3153,26 +3149,10 @@ static int X509V3_ext(struct Curl_easy *data, ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); BIO_get_mem_ptr(bio_out, &biomem); - - for(j = 0; j < (size_t)biomem->length; j++) { - const char *sep = ""; - if(biomem->data[j] == '\n') { - sep = ", "; - j++; /* skip the newline */ - }; - while((j<(size_t)biomem->length) && (biomem->data[j] == ' ')) - j++; - if(j<(size_t)biomem->length) - ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, - biomem->data[j]); - } - - Curl_ssl_push_certinfo(data, certnum, namebuf, buf); - + Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data, + biomem->length); BIO_free(bio_out); - } - return 0; /* all is fine */ } #ifdef OPENSSL_IS_BORINGSSL diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index dc58ed0d3b..0818d947a4 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -718,7 +718,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) unsigned short* list_len = NULL; /* The first four bytes will be an unsigned int indicating number - of bytes of data in the rest of the the buffer. */ + of bytes of data in the rest of the buffer. */ extension_len = (unsigned int *)(&alpn_buffer[cur]); cur += sizeof(unsigned int); diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index 3a668adc76..e75132cadd 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, 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 @@ -293,6 +293,133 @@ cleanup: return result; } +/* + * Returns the number of characters necessary to populate all the host_names. + * If host_names is not NULL, populate it with all the host names. Each string + * in the host_names is null-terminated and the last string is double + * null-terminated. If no DNS names are found, a single null-terminated empty + * string is returned. + */ +static DWORD cert_get_name_string(struct Curl_easy *data, + CERT_CONTEXT *cert_context, + LPTSTR host_names, + DWORD length) +{ + DWORD actual_length = 0; + BOOL compute_content = FALSE; + CERT_INFO *cert_info = NULL; + CERT_EXTENSION *extension = NULL; + CRYPT_DECODE_PARA decode_para = {0, 0, 0}; + CERT_ALT_NAME_INFO *alt_name_info = NULL; + DWORD alt_name_info_size = 0; + BOOL ret_val = FALSE; + LPTSTR current_pos = NULL; + DWORD i; + + /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */ + if(Curl_verify_windows_version(6, 2, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { +#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG + /* CertGetNameString will provide the 8-bit character string without + * any decoding */ + DWORD name_flags = + CERT_NAME_DISABLE_IE4_UTF8_FLAG | CERT_NAME_SEARCH_ALL_NAMES_FLAG; + actual_length = CertGetNameString(cert_context, + CERT_NAME_DNS_TYPE, + name_flags, + NULL, + host_names, + length); + return actual_length; +#endif + } + + compute_content = host_names != NULL && length != 0; + + /* Initialize default return values. */ + actual_length = 1; + if(compute_content) { + *host_names = '\0'; + } + + if(!cert_context) { + failf(data, "schannel: Null certificate context."); + return actual_length; + } + + cert_info = cert_context->pCertInfo; + if(!cert_info) { + failf(data, "schannel: Null certificate info."); + return actual_length; + } + + extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2, + cert_info->cExtension, + cert_info->rgExtension); + if(!extension) { + failf(data, "schannel: CertFindExtension() returned no extension."); + return actual_length; + } + + decode_para.cbSize = sizeof(CRYPT_DECODE_PARA); + + ret_val = + CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + szOID_SUBJECT_ALT_NAME2, + extension->Value.pbData, + extension->Value.cbData, + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, + &decode_para, + &alt_name_info, + &alt_name_info_size); + if(!ret_val) { + failf(data, + "schannel: CryptDecodeObjectEx() returned no alternate name " + "information."); + return actual_length; + } + + current_pos = host_names; + + /* Iterate over the alternate names and populate host_names. */ + for(i = 0; i < alt_name_info->cAltEntry; i++) { + const CERT_ALT_NAME_ENTRY *entry = &alt_name_info->rgAltEntry[i]; + wchar_t *dns_w = NULL; + size_t current_length = 0; + + if(entry->dwAltNameChoice != CERT_ALT_NAME_DNS_NAME) { + continue; + } + if(entry->pwszDNSName == NULL) { + infof(data, "schannel: Empty DNS name."); + continue; + } + current_length = wcslen(entry->pwszDNSName) + 1; + if(!compute_content) { + actual_length += (DWORD)current_length; + continue; + } + /* Sanity check to prevent buffer overrun. */ + if((actual_length + current_length) > length) { + failf(data, "schannel: Not enough memory to list all host names."); + break; + } + dns_w = entry->pwszDNSName; + /* pwszDNSName is in ia5 string format and hence doesn't contain any + * non-ascii characters. */ + while(*dns_w != '\0') { + *current_pos++ = (char)(*dns_w++); + } + *current_pos++ = '\0'; + actual_length += (DWORD)current_length; + } + if(compute_content) { + /* Last string has double null-terminator. */ + *current_pos = '\0'; + } + return actual_length; +} + static CURLcode verify_host(struct Curl_easy *data, CERT_CONTEXT *pCertContextServer, const char * const conn_hostname) @@ -303,21 +430,8 @@ static CURLcode verify_host(struct Curl_easy *data, DWORD len = 0; DWORD actual_len = 0; - /* CertGetNameString will provide the 8-bit character string without - * any decoding */ - DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG; - -#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG - name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG; -#endif - /* Determine the size of the string needed for the cert hostname */ - len = CertGetNameString(pCertContextServer, - CERT_NAME_DNS_TYPE, - name_flags, - NULL, - NULL, - 0); + len = cert_get_name_string(data, pCertContextServer, NULL, 0); if(len == 0) { failf(data, "schannel: CertGetNameString() returned no " @@ -334,12 +448,8 @@ static CURLcode verify_host(struct Curl_easy *data, result = CURLE_OUT_OF_MEMORY; goto cleanup; } - actual_len = CertGetNameString(pCertContextServer, - CERT_NAME_DNS_TYPE, - name_flags, - NULL, - (LPTSTR) cert_hostname_buff, - len); + actual_len = cert_get_name_string( + data, pCertContextServer, (LPTSTR)cert_hostname_buff, len); /* Sanity check */ if(actual_len != len) { diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 4eece89d55..7dd028fb7f 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2020, 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 @@ -1164,7 +1164,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath, * the Keychain. * * As this doesn't match iOS, and apps may not want to see their client - * certificate saved in the the user's keychain, we use SecItemImport + * certificate saved in the user's keychain, we use SecItemImport * with a NULL keychain to avoid importing it. * * This returns a SecCertificateRef from which we can construct a diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index c493b15169..dfefa1bd5e 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -516,7 +516,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) } #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_SECTRANSP) || defined(USE_NSS) || \ defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL) int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks) { @@ -1183,8 +1183,6 @@ const struct Curl_ssl *Curl_ssl = &Curl_ssl_nss; #elif defined(USE_OPENSSL) &Curl_ssl_openssl; -#elif defined(USE_POLARSSL) - &Curl_ssl_polarssl; #elif defined(USE_SCHANNEL) &Curl_ssl_schannel; #elif defined(USE_MESALINK) @@ -1217,9 +1215,6 @@ static const struct Curl_ssl *available_backends[] = { #if defined(USE_OPENSSL) &Curl_ssl_openssl, #endif -#if defined(USE_POLARSSL) - &Curl_ssl_polarssl, -#endif #if defined(USE_SCHANNEL) &Curl_ssl_schannel, #endif @@ -1236,7 +1231,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size) { static const struct Curl_ssl *selected; static char backends[200]; - static size_t total; + static size_t backends_len; const struct Curl_ssl *current; current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl; @@ -1248,27 +1243,32 @@ static size_t Curl_multissl_version(char *buffer, size_t size) selected = current; - for(i = 0; available_backends[i] && p < (end - 4); i++) { - if(i) - *(p++) = ' '; - if(selected != available_backends[i]) - *(p++) = '('; - p += available_backends[i]->version(p, end - p - 2); - if(selected != available_backends[i]) - *(p++) = ')'; + backends[0] = '\0'; + + for(i = 0; available_backends[i]; ++i) { + char vb[200]; + bool paren = (selected != available_backends[i]); + + if(available_backends[i]->version(vb, sizeof(vb))) { + p += msnprintf(p, end - p, "%s%s%s%s", (p != backends ? " " : ""), + (paren ? "(" : ""), vb, (paren ? ")" : "")); + } } - *p = '\0'; - total = p - backends; + + backends_len = p - backends; } - if(size > total) - memcpy(buffer, backends, total + 1); - else { - memcpy(buffer, backends, size - 1); + if(!size) + return 0; + + if(size <= backends_len) { + strncpy(buffer, backends, size - 1); buffer[size - 1] = '\0'; + return size - 1; } - return CURLMIN(size - 1, total); + strcpy(buffer, backends); + return backends_len; } static int multissl_init(const struct Curl_ssl *backend) diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index 976cc43601..f58adee6e8 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -102,7 +102,6 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, #include "gtls.h" /* GnuTLS versions */ #include "nssg.h" /* NSS versions */ #include "gskit.h" /* Global Secure ToolKit versions */ -#include "polarssl.h" /* PolarSSL versions */ #include "wolfssl.h" /* wolfSSL versions */ #include "schannel.h" /* Schannel SSPI version */ #include "sectransp.h" /* SecureTransport (Darwin) version */ diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 890bcbf797..8c2d3f4a28 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -923,7 +923,7 @@ static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex) static CURLcode Curl_wolfssl_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { - RNG rng; + WC_RNG rng; (void)data; if(wc_InitRng(&rng)) return CURLE_FAILED_INIT; @@ -937,11 +937,11 @@ static CURLcode Curl_wolfssl_random(struct Curl_easy *data, } static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused) + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) { - Sha256 SHA256pw; + wc_Sha256 SHA256pw; (void)unused; wc_InitSha256(&SHA256pw); wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen); |