From e41e0c05795b60cd749ae038cd96c966ec0c87bb Mon Sep 17 00:00:00 2001 From: dartraiden Date: Wed, 27 Mar 2019 17:53:10 +0300 Subject: libcurl: update to 7.64.1 --- libs/libcurl/src/Makefile.am | 9 +- libs/libcurl/src/Makefile.in | 99 +- libs/libcurl/src/Makefile.inc | 11 +- libs/libcurl/src/altsvc.c | 571 ++++++ libs/libcurl/src/altsvc.h | 77 + libs/libcurl/src/amigaos.c | 32 +- libs/libcurl/src/amigaos.h | 10 +- libs/libcurl/src/asyn-thread.c | 68 +- libs/libcurl/src/config-os400.h | 5 +- libs/libcurl/src/config-vxworks.h | 5 +- libs/libcurl/src/config-win32.h | 7 - libs/libcurl/src/conncache.c | 13 +- libs/libcurl/src/connect.c | 72 +- libs/libcurl/src/connect.h | 9 +- libs/libcurl/src/cookie.c | 59 +- libs/libcurl/src/cookie.h | 11 +- libs/libcurl/src/curl_addrinfo.c | 32 +- libs/libcurl/src/curl_addrinfo.h | 13 +- libs/libcurl/src/curl_config.h.in | 24 +- libs/libcurl/src/curl_endian.c | 10 +- libs/libcurl/src/curl_fnmatch.c | 6 +- libs/libcurl/src/curl_gssapi.h | 16 +- libs/libcurl/src/curl_ntlm_core.c | 31 +- libs/libcurl/src/curl_ntlm_wb.c | 15 +- libs/libcurl/src/curl_path.c | 6 +- libs/libcurl/src/curl_rtmp.c | 9 +- libs/libcurl/src/curl_setup.h | 23 +- libs/libcurl/src/dict.c | 11 +- libs/libcurl/src/doh.c | 71 +- libs/libcurl/src/easy.c | 81 +- libs/libcurl/src/file.c | 4 +- libs/libcurl/src/ftp.c | 58 +- libs/libcurl/src/ftp.h | 3 +- libs/libcurl/src/getinfo.c | 4 +- libs/libcurl/src/gopher.c | 12 +- libs/libcurl/src/hostasyn.c | 8 +- libs/libcurl/src/hostip.c | 103 +- libs/libcurl/src/hostip.h | 12 +- libs/libcurl/src/hostip6.c | 9 +- libs/libcurl/src/http.c | 246 ++- libs/libcurl/src/http.h | 6 +- libs/libcurl/src/http2.c | 48 +- libs/libcurl/src/http2.h | 3 +- libs/libcurl/src/http_negotiate.c | 109 +- libs/libcurl/src/http_negotiate.h | 4 +- libs/libcurl/src/imap.c | 8 +- libs/libcurl/src/ldap.c | 4 +- libs/libcurl/src/libcurl.plist | 6 +- libs/libcurl/src/md5.c | 4 +- libs/libcurl/src/memdebug.c | 145 +- libs/libcurl/src/memdebug.h | 123 +- libs/libcurl/src/mime.c | 14 +- libs/libcurl/src/mime.h | 7 +- libs/libcurl/src/multi.c | 155 +- libs/libcurl/src/non-ascii.c | 4 +- libs/libcurl/src/openldap.c | 4 +- libs/libcurl/src/pop3.c | 2 +- libs/libcurl/src/rand.h | 7 +- libs/libcurl/src/rtsp.c | 22 +- libs/libcurl/src/security.c | 4 +- libs/libcurl/src/sendf.c | 8 +- libs/libcurl/src/setopt.c | 46 +- libs/libcurl/src/smtp.c | 4 +- libs/libcurl/src/socks.c | 4 +- libs/libcurl/src/socks_sspi.c | 5 +- libs/libcurl/src/ssh-libssh.c | 25 +- libs/libcurl/src/ssh.c | 35 +- libs/libcurl/src/strerror.c | 20 +- libs/libcurl/src/strerror.h | 11 +- libs/libcurl/src/system_win32.c | 82 + libs/libcurl/src/system_win32.h | 6 + libs/libcurl/src/telnet.c | 4 +- libs/libcurl/src/tftp.c | 30 +- libs/libcurl/src/timeval.c | 24 +- libs/libcurl/src/transfer.c | 51 +- libs/libcurl/src/transfer.h | 20 +- libs/libcurl/src/url.c | 136 +- libs/libcurl/src/urlapi.c | 38 +- libs/libcurl/src/urldata.h | 530 +++-- libs/libcurl/src/vauth/spnego_gssapi.c | 7 +- libs/libcurl/src/vauth/spnego_sspi.c | 8 +- libs/libcurl/src/version.c | 9 +- libs/libcurl/src/vtls/cyassl.c | 21 +- libs/libcurl/src/vtls/darwinssl.c | 3259 ------------------------------- libs/libcurl/src/vtls/darwinssl.h | 32 - libs/libcurl/src/vtls/gtls.c | 7 +- libs/libcurl/src/vtls/mbedtls.c | 8 + libs/libcurl/src/vtls/openssl.c | 23 +- libs/libcurl/src/vtls/schannel.c | 196 +- libs/libcurl/src/vtls/schannel_verify.c | 45 +- libs/libcurl/src/vtls/sectransp.c | 3259 +++++++++++++++++++++++++++++++ libs/libcurl/src/vtls/sectransp.h | 32 + libs/libcurl/src/vtls/vtls.c | 20 +- libs/libcurl/src/vtls/vtls.h | 8 +- libs/libcurl/src/warnless.c | 40 +- libs/libcurl/src/warnless.h | 6 +- libs/libcurl/src/x509asn1.c | 250 +-- 97 files changed, 5865 insertions(+), 4988 deletions(-) create mode 100644 libs/libcurl/src/altsvc.c create mode 100644 libs/libcurl/src/altsvc.h delete mode 100644 libs/libcurl/src/vtls/darwinssl.c delete mode 100644 libs/libcurl/src/vtls/darwinssl.h create mode 100644 libs/libcurl/src/vtls/sectransp.c create mode 100644 libs/libcurl/src/vtls/sectransp.h (limited to 'libs/libcurl/src') diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am index f2034a2f24..7c258b3fa7 100644 --- a/libs/libcurl/src/Makefile.am +++ b/libs/libcurl/src/Makefile.am @@ -131,9 +131,14 @@ include Makefile.inc libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS) +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + checksrc: - @PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ - $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] + $(CHECKSRC)(@PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ + $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch]) if CURLDEBUG # for debug builds, we scan the sources on all regular make invokes diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index 14c1c73afa..6b3fcfa87d 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -21,7 +21,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,7 @@ am__objects_1 = libcurl_la-file.lo libcurl_la-timeval.lo \ libcurl_la-sha256.lo libcurl_la-setopt.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-urlapi.lo libcurl_la-altsvc.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 \ @@ -244,7 +244,7 @@ am__objects_3 = vtls/libcurl_la-openssl.lo vtls/libcurl_la-gtls.lo \ vtls/libcurl_la-polarssl_threadlock.lo \ vtls/libcurl_la-cyassl.lo vtls/libcurl_la-schannel.lo \ vtls/libcurl_la-schannel_verify.lo \ - vtls/libcurl_la-darwinssl.lo vtls/libcurl_la-gskit.lo \ + vtls/libcurl_la-sectransp.lo vtls/libcurl_la-gskit.lo \ vtls/libcurl_la-mbedtls.lo vtls/libcurl_la-mesalink.lo am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3) am__objects_5 = @@ -311,7 +311,7 @@ am__objects_7 = libcurlu_la-file.lo libcurlu_la-timeval.lo \ libcurlu_la-sha256.lo libcurlu_la-setopt.lo \ libcurlu_la-curl_path.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-doh.lo libcurlu_la-urlapi.lo libcurlu_la-altsvc.lo am__objects_8 = 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 \ @@ -326,7 +326,7 @@ am__objects_9 = vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-gtls.lo \ vtls/libcurlu_la-polarssl_threadlock.lo \ vtls/libcurlu_la-cyassl.lo vtls/libcurlu_la-schannel.lo \ vtls/libcurlu_la-schannel_verify.lo \ - vtls/libcurlu_la-darwinssl.lo vtls/libcurlu_la-gskit.lo \ + vtls/libcurlu_la-sectransp.lo vtls/libcurlu_la-gskit.lo \ vtls/libcurlu_la-mbedtls.lo vtls/libcurlu_la-mesalink.lo am__objects_10 = $(am__objects_7) $(am__objects_8) $(am__objects_9) am_libcurlu_la_OBJECTS = $(am__objects_10) $(am__objects_6) @@ -350,7 +350,8 @@ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.Plo \ +am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ + ./$(DEPDIR)/libcurl_la-amigaos.Plo \ ./$(DEPDIR)/libcurl_la-asyn-ares.Plo \ ./$(DEPDIR)/libcurl_la-asyn-thread.Plo \ ./$(DEPDIR)/libcurl_la-base64.Plo \ @@ -457,6 +458,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.Plo \ ./$(DEPDIR)/libcurl_la-warnless.Plo \ ./$(DEPDIR)/libcurl_la-wildcard.Plo \ ./$(DEPDIR)/libcurl_la-x509asn1.Plo \ + ./$(DEPDIR)/libcurlu_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-amigaos.Plo \ ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \ ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \ @@ -593,7 +595,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.Plo \ vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo \ vauth/$(DEPDIR)/libcurlu_la-vauth.Plo \ vtls/$(DEPDIR)/libcurl_la-cyassl.Plo \ - vtls/$(DEPDIR)/libcurl_la-darwinssl.Plo \ vtls/$(DEPDIR)/libcurl_la-gskit.Plo \ vtls/$(DEPDIR)/libcurl_la-gtls.Plo \ vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo \ @@ -604,9 +605,9 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.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 \ vtls/$(DEPDIR)/libcurl_la-vtls.Plo \ vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo \ - vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo \ vtls/$(DEPDIR)/libcurlu_la-gskit.Plo \ vtls/$(DEPDIR)/libcurlu_la-gtls.Plo \ vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo \ @@ -617,6 +618,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.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 \ vtls/$(DEPDIR)/libcurlu_la-vtls.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ @@ -726,6 +728,7 @@ ENABLE_SHARED = @ENABLE_SHARED@ ENABLE_STATIC = @ENABLE_STATIC@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ GCOV = @GCOV@ GREP = @GREP@ HAVE_BROTLI = @HAVE_BROTLI@ @@ -733,6 +736,7 @@ HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ HAVE_LIBZ = @HAVE_LIBZ@ HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ IDN_ENABLED = @IDN_ENABLED@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -796,7 +800,6 @@ SUPPORT_FEATURES = @SUPPORT_FEATURES@ SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ USE_ARES = @USE_ARES@ USE_CYASSL = @USE_CYASSL@ -USE_DARWINSSL = @USE_DARWINSSL@ USE_GNUTLS = @USE_GNUTLS@ USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ USE_LIBRTMP = @USE_LIBRTMP@ @@ -809,6 +812,7 @@ USE_NSS = @USE_NSS@ USE_OPENLDAP = @USE_OPENLDAP@ USE_POLARSSL = @USE_POLARSSL@ USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ VERSION = @VERSION@ @@ -952,11 +956,11 @@ 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/cyassl.c vtls/schannel.c vtls/schannel_verify.c \ - vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ - vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \ + vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ vtls/mbedtls.h vtls/mesalink.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ @@ -977,7 +981,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c pipeline.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 + doh.c urlapi.c altsvc.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 \ @@ -997,7 +1001,8 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.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_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + altsvc.h LIB_RCFILES = libcurl.rc CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) @@ -1006,6 +1011,10 @@ HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) # Makefile.inc provides the CSOURCES and HHEADERS defines libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS) +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) # disable the tests that are mostly causing false positives TIDYFLAGS = -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet @@ -1162,7 +1171,7 @@ vtls/libcurl_la-schannel.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurl_la-schannel_verify.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurl_la-darwinssl.lo: vtls/$(am__dirstamp) \ +vtls/libcurl_la-sectransp.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurl_la-gskit.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -1215,7 +1224,7 @@ vtls/libcurlu_la-schannel.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurlu_la-schannel_verify.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurlu_la-darwinssl.lo: vtls/$(am__dirstamp) \ +vtls/libcurlu_la-sectransp.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurlu_la-gskit.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -1237,6 +1246,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-altsvc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-amigaos.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker @@ -1348,6 +1358,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-warnless.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-wildcard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-altsvc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-amigaos.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker @@ -1484,7 +1495,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-vauth.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-cyassl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-darwinssl.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 @@ -1495,9 +1505,9 @@ distclean-compile: @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 @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo@am__quote@ # am--include-marker @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 @@ -1508,6 +1518,7 @@ distclean-compile: @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 @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @@ -2317,6 +2328,13 @@ libcurl_la-urlapi.lo: urlapi.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-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c +libcurl_la-altsvc.lo: altsvc.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-altsvc.lo -MD -MP -MF $(DEPDIR)/libcurl_la-altsvc.Tpo -c -o libcurl_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-altsvc.Tpo $(DEPDIR)/libcurl_la-altsvc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='altsvc.c' object='libcurl_la-altsvc.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-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.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 @@ -2464,12 +2482,12 @@ vtls/libcurl_la-schannel_verify.lo: vtls/schannel_verify.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-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c -vtls/libcurl_la-darwinssl.lo: vtls/darwinssl.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-darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-darwinssl.Tpo -c -o vtls/libcurl_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-darwinssl.Tpo vtls/$(DEPDIR)/libcurl_la-darwinssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/darwinssl.c' object='vtls/libcurl_la-darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurl_la-sectransp.lo: vtls/sectransp.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-sectransp.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-sectransp.Tpo -c -o vtls/libcurl_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-sectransp.Tpo vtls/$(DEPDIR)/libcurl_la-sectransp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/sectransp.c' object='vtls/libcurl_la-sectransp.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-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.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-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c vtls/libcurl_la-gskit.lo: vtls/gskit.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-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gskit.Tpo -c -o vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c @@ -3269,6 +3287,13 @@ libcurlu_la-urlapi.lo: urlapi.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-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c +libcurlu_la-altsvc.lo: altsvc.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-altsvc.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-altsvc.Tpo -c -o libcurlu_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-altsvc.Tpo $(DEPDIR)/libcurlu_la-altsvc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='altsvc.c' object='libcurlu_la-altsvc.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-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.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 @@ -3416,12 +3441,12 @@ vtls/libcurlu_la-schannel_verify.lo: vtls/schannel_verify.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-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c -vtls/libcurlu_la-darwinssl.lo: vtls/darwinssl.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-darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-darwinssl.Tpo -c -o vtls/libcurlu_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-darwinssl.Tpo vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/darwinssl.c' object='vtls/libcurlu_la-darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurlu_la-sectransp.lo: vtls/sectransp.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-sectransp.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-sectransp.Tpo -c -o vtls/libcurlu_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-sectransp.Tpo vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/sectransp.c' object='vtls/libcurlu_la-sectransp.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-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.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-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c vtls/libcurlu_la-gskit.lo: vtls/gskit.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-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo -c -o vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c @@ -3585,7 +3610,8 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo @@ -3696,6 +3722,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo -rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo -rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo -rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo @@ -3832,7 +3859,6 @@ distclean: distclean-am -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo -rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-cyassl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-darwinssl.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 @@ -3843,9 +3869,9 @@ distclean: distclean-am -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 -rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo @@ -3856,6 +3882,7 @@ distclean: distclean-am -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 -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ @@ -3902,7 +3929,8 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo @@ -4013,6 +4041,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo -rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo -rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo -rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo @@ -4149,7 +4178,6 @@ maintainer-clean: maintainer-clean-am -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo -rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo -rm -f vtls/$(DEPDIR)/libcurl_la-cyassl.Plo - -rm -f vtls/$(DEPDIR)/libcurl_la-darwinssl.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 @@ -4160,9 +4188,9 @@ maintainer-clean: maintainer-clean-am -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 -rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo - -rm -f vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo @@ -4173,6 +4201,7 @@ maintainer-clean: maintainer-clean-am -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 -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -4214,8 +4243,8 @@ uninstall-am: uninstall-libLTLIBRARIES checksrc: - @PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ - $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] + $(CHECKSRC)(@PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ + $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch]) # for debug builds, we scan the sources on all regular make invokes @CURLDEBUG_TRUE@all-local: checksrc diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc index 54acd6cea1..6c47bcda55 100644 --- a/libs/libcurl/src/Makefile.inc +++ b/libs/libcurl/src/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,11 +30,11 @@ 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/cyassl.c vtls/schannel.c vtls/schannel_verify.c \ - vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ - vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \ + vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ vtls/mbedtls.h vtls/mesalink.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ @@ -55,7 +55,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c pipeline.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 + doh.c urlapi.c altsvc.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 \ @@ -75,7 +75,8 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.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_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + altsvc.h LIB_RCFILES = libcurl.rc diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c new file mode 100644 index 0000000000..1643466456 --- /dev/null +++ b/libs/libcurl/src/altsvc.c @@ -0,0 +1,571 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , 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. + * + ***************************************************************************/ +/* + * The Alt-Svc: header is defined in RFC 7838: + * https://tools.ietf.org/html/rfc7838 + */ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "urldata.h" +#include "altsvc.h" +#include "cookie.h" /* for Curl_get_line() */ +#include "strcase.h" +#include "parsedate.h" +#include "sendf.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" + +#define MAX_ALTSVC_LINE 4095 +#define MAX_ALTSVC_DATELENSTR "64" +#define MAX_ALTSVC_DATELEN 64 +#define MAX_ALTSVC_HOSTLENSTR "512" +#define MAX_ALTSVC_HOSTLEN 512 +#define MAX_ALTSVC_ALPNLENSTR "10" +#define MAX_ALTSVC_ALPNLEN 10 + +static enum alpnid alpn2alpnid(char *name) +{ + if(strcasecompare(name, "h1")) + return ALPN_h1; + if(strcasecompare(name, "h2")) + return ALPN_h2; + if(strcasecompare(name, "h2c")) + return ALPN_h2c; + if(strcasecompare(name, "h3")) + return ALPN_h3; + return ALPN_none; /* unknown, probably rubbish input */ +} + +/* Given the ALPN ID, return the name */ +const char *Curl_alpnid2str(enum alpnid id) +{ + switch(id) { + case ALPN_h1: + return "h1"; + case ALPN_h2: + return "h2"; + case ALPN_h2c: + return "h2c"; + case ALPN_h3: + return "h3"; + default: + return ""; /* bad */ + } +} + + +static void altsvc_free(struct altsvc *as) +{ + free(as->srchost); + free(as->dsthost); + free(as); +} + +static struct altsvc *altsvc_createid(const char *srchost, + const char *dsthost, + enum alpnid srcalpnid, + enum alpnid dstalpnid, + unsigned int srcport, + unsigned int dstport) +{ + struct altsvc *as = calloc(sizeof(struct altsvc), 1); + if(!as) + return NULL; + + as->srchost = strdup(srchost); + if(!as->srchost) + goto error; + as->dsthost = strdup(dsthost); + if(!as->dsthost) + goto error; + + as->srcalpnid = srcalpnid; + as->dstalpnid = dstalpnid; + as->srcport = curlx_ultous(srcport); + as->dstport = curlx_ultous(dstport); + + return as; + error: + altsvc_free(as); + return NULL; +} + +static struct altsvc *altsvc_create(char *srchost, + char *dsthost, + char *srcalpn, + char *dstalpn, + unsigned int srcport, + unsigned int dstport) +{ + enum alpnid dstalpnid = alpn2alpnid(dstalpn); + enum alpnid srcalpnid = alpn2alpnid(srcalpn); + if(!srcalpnid || !dstalpnid) + return NULL; + return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid, + srcport, dstport); +} + +/* only returns SERIOUS errors */ +static CURLcode altsvc_add(struct altsvcinfo *asi, char *line) +{ + /* Example line: + h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1 + */ + char srchost[MAX_ALTSVC_HOSTLEN + 1]; + char dsthost[MAX_ALTSVC_HOSTLEN + 1]; + char srcalpn[MAX_ALTSVC_ALPNLEN + 1]; + char dstalpn[MAX_ALTSVC_ALPNLEN + 1]; + char date[MAX_ALTSVC_DATELEN + 1]; + unsigned int srcport; + unsigned int dstport; + unsigned int prio; + unsigned int persist; + int rc; + + rc = sscanf(line, + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u", + srcalpn, srchost, &srcport, + dstalpn, dsthost, &dstport, + date, &persist, &prio); + if(9 == rc) { + struct altsvc *as; + time_t expires = curl_getdate(date, NULL); + as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport); + if(as) { + as->expires = expires; + as->prio = prio; + as->persist = persist ? 1 : 0; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + } + } + + return CURLE_OK; +} + +/* + * Load alt-svc entries from the given file. The text based line-oriented file + * format is documented here: + * https://github.com/curl/curl/wiki/QUIC-implementation + * + * This function only returns error on major problems that prevents alt-svc + * handling to work completely. It will ignore individual syntactical errors + * etc. + */ +static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result = CURLE_OK; + char *line = NULL; + FILE *fp = fopen(file, FOPEN_READTEXT); + if(fp) { + line = malloc(MAX_ALTSVC_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) { + char *lineptr = line; + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + if(*lineptr == '#') + /* skip commented lines */ + continue; + + altsvc_add(asi, lineptr); + } + free(line); /* free the line buffer */ + fclose(fp); + } + return result; + + fail: + free(line); + fclose(fp); + return CURLE_OUT_OF_MEMORY; +} + +/* + * Write this single altsvc entry to a single output line + */ + +static CURLcode altsvc_out(struct altsvc *as, FILE *fp) +{ + struct tm stamp; + CURLcode result = Curl_gmtime(as->expires, &stamp); + if(result) + return result; + + fprintf(fp, + "%s %s %u " + "%s %s %u " + "\"%d%02d%02d " + "%02d:%02d:%02d\" " + "%u %d\n", + Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport, + Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec, + as->persist, as->prio); + return CURLE_OK; +} + +/* ---- library-wide functions below ---- */ + +/* + * Curl_altsvc_init() creates a new altsvc cache. + * It returns the new instance or NULL if something goes wrong. + */ +struct altsvcinfo *Curl_altsvc_init(void) +{ + struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); + if(!asi) + return NULL; + Curl_llist_init(&asi->list, NULL); + + /* set default behavior */ + asi->flags = CURLALTSVC_H1 +#ifdef USE_NGHTTP2 + | CURLALTSVC_H2 +#endif +#ifdef USE_HTTP3 + /* TODO: adjust when known */ + | CURLALTSVC_H3 +#endif + ; + return asi; +} + +/* + * Curl_altsvc_load() loads alt-svc from file. + */ +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result; + DEBUGASSERT(asi); + result = altsvc_load(asi, file); + return result; +} + +/* + * Curl_altsvc_ctrl() passes on the external bitmask. + */ +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl) +{ + DEBUGASSERT(asi); + if(!ctrl) + /* unexpected */ + return CURLE_BAD_FUNCTION_ARGUMENT; + asi->flags = ctrl; + return CURLE_OK; +} + +/* + * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated + * resources. + */ +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + if(altsvc) { + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + altsvc_free(as); + } + free(altsvc); + } +} + +/* + * Curl_altsvc_save() writes the altsvc cache to a file. + */ +CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + CURLcode result = CURLE_OK; + FILE *out; + + if(!altsvc) + /* no cache activated */ + return CURLE_OK; + + if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0]) + /* marked as read-only or zero length file name */ + return CURLE_OK; + out = fopen(file, 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); + if(result) + break; + } + fclose(out); + return result; +} + +static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen) +{ + size_t len; + const char *protop; + const char *p = *ptr; + while(*p && ISBLANK(*p)) + p++; + protop = p; + while(*p && ISALNUM(*p)) + p++; + len = p - protop; + + if(!len || (len >= buflen)) + return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */ + memcpy(alpnbuf, protop, len); + alpnbuf[len] = 0; + *ptr = p; + return CURLE_OK; +} + +/* altsvc_flush() removes all alternatives for this source origin from the + list */ +static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid, + const char *srchost, unsigned short srcport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if((srcalpnid == as->srcalpnid) && + (srcport == as->srcport) && + strcasecompare(srchost, as->srchost)) { + Curl_llist_remove(&asi->list, e, NULL); + altsvc_free(as); + asi->num--; + } + } +} + +#ifdef DEBUGBUILD +/* to play well with debug builds, we can *set* a fixed time this will + return */ +static time_t debugtime(void *unused) +{ + char *timestr = getenv("CURL_TIME"); + (void)unused; + if(timestr) { + unsigned long val = strtol(timestr, NULL, 10); + return (time_t)val; + } + return time(NULL); +} +#define time(x) debugtime(x) +#endif + +/* + * Curl_altsvc_parse() takes an incoming alt-svc response header and stores + * the data correctly in the cache. + * + * 'value' points to the header *value*. That's contents to the right of the + * header name. + */ +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *asi, const char *value, + enum alpnid srcalpnid, const char *srchost, + unsigned short srcport) +{ + const char *p = value; + size_t len; + enum alpnid dstalpnid = srcalpnid; /* the same by default */ + char namebuf[MAX_ALTSVC_HOSTLEN] = ""; + 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; + + DEBUGASSERT(asi); + + /* Flush all cached alternatives for this source origin, if any */ + altsvc_flush(asi, srcalpnid, srchost, srcport); + + /* "clear" is a magic keyword */ + if(strcasecompare(alpnbuf, "clear")) { + /* TODO: clear whatever it is it should clear */ + 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; + semip++; /* pass the semicolon */ + result = getalnum(&semip, option, sizeof(option)); + if(result) + break; + while(*semip && ISBLANK(*semip)) + semip++; + if(*semip != '=') + continue; + semip++; + num = strtoul(semip, &end_ptr, 10); + if(num < ULONG_MAX) { + if(strcasecompare("ma", option)) + maxage = num; + else if(strcasecompare("persist", option) && (num == 1)) + persist = TRUE; + } + 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; + p++; + if(*p != ':') { + /* host name starts here */ + const char *hostp = p; + while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) + p++; + len = p - hostp; + if(!len || (len >= MAX_ALTSVC_HOSTLEN)) + return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */ + memcpy(namebuf, hostp, len); + namebuf[len] = 0; + dsthost = namebuf; + } + else { + /* no destination name, use source host */ + dsthost = srchost; + } + 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; + } + 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) { + /* TODO: 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)); + } + } + /* after the double quote there can be a comma if there's another + string or a semicolon if no more */ + if(*p == ',') { + /* comma means another alternative is presented */ + 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; + } + } + } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); + + return CURLE_OK; +} + +/* + * Return TRUE on a match + */ +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + time_t now = time(NULL); + DEBUGASSERT(asi); + DEBUGASSERT(srchost); + DEBUGASSERT(dsthost); + + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if(as->expires < now) { + /* an expired entry, remove */ + altsvc_free(as); + continue; + } + if((as->srcalpnid == srcalpnid) && + strcasecompare(as->srchost, srchost) && + as->srcport == srcport) { + /* match */ + *dstalpnid = as->dstalpnid; + *dsthost = as->dsthost; + *dstport = as->dstport; + return TRUE; + } + } + return FALSE; +} + +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ diff --git a/libs/libcurl/src/altsvc.h b/libs/libcurl/src/altsvc.h new file mode 100644 index 0000000000..eefb45bf61 --- /dev/null +++ b/libs/libcurl/src/altsvc.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_ALTSVC_H +#define HEADER_CURL_ALTSVC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , 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" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "llist.h" + +enum alpnid { + ALPN_none, + ALPN_h1, + ALPN_h2, + ALPN_h2c, + ALPN_h3 +}; + +struct altsvc { + char *srchost; + char *dsthost; + unsigned short srcport; + unsigned short dstport; + enum alpnid srcalpnid; + enum alpnid dstalpnid; + time_t expires; + bool persist; + int prio; + struct curl_llist_element node; +}; + +struct altsvcinfo { + char *filename; + struct curl_llist list; /* list of entries */ + size_t num; /* number of alt-svc entries */ + long flags; /* the publicly set bitmask */ +}; + +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_ctrl(struct altsvcinfo *asi, const long ctrl); +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *value, + enum alpnid srcalpn, const char *srchost, + unsigned short srcport); +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport); +#else +/* disabled */ +#define Curl_altsvc_save(a,b) +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ +#endif /* HEADER_CURL_ALTSVC_H */ diff --git a/libs/libcurl/src/amigaos.c b/libs/libcurl/src/amigaos.c index 4f55b30e76..cf44bdc8d1 100644 --- a/libs/libcurl/src/amigaos.c +++ b/libs/libcurl/src/amigaos.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,17 +22,26 @@ #include "curl_setup.h" -#if defined(__AMIGA__) && !defined(__ixemul__) - -#include +#ifdef __AMIGA__ +# include "amigaos.h" +# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +# include +# endif +# ifdef __libnix__ +# include +# endif +#endif -#include "amigaos.h" +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" +#ifdef __AMIGA__ +#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) struct Library *SocketBase = NULL; extern int errno, h_errno; #ifdef __libnix__ -#include void __request(const char *msg); #else # define __request(msg) Printf(msg "\n\a") @@ -74,4 +83,13 @@ bool Curl_amiga_init() ADD2EXIT(Curl_amiga_cleanup, -50); #endif -#endif /* __AMIGA__ && ! __ixemul__ */ +#endif /* HAVE_PROTO_BSDSOCKET_H */ + +#ifdef USE_AMISSL +void Curl_amiga_X509_free(X509 *a) +{ + X509_free(a); +} +#endif /* USE_AMISSL */ +#endif /* __AMIGA__ */ + diff --git a/libs/libcurl/src/amigaos.h b/libs/libcurl/src/amigaos.h index 7c0926cc35..c776c9c9bb 100644 --- a/libs/libcurl/src/amigaos.h +++ b/libs/libcurl/src/amigaos.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(__AMIGA__) && !defined(__ixemul__) +#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) bool Curl_amiga_init(); void Curl_amiga_cleanup(); @@ -35,4 +35,10 @@ void Curl_amiga_cleanup(); #endif +#ifdef USE_AMISSL +#include +void Curl_amiga_X509_free(X509 *a); +#endif /* USE_AMISSL */ + #endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index a9679d062e..55e0811c5c 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -461,6 +461,42 @@ static CURLcode resolver_error(struct connectdata *conn) return result; } +static CURLcode thread_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry, + bool report) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + CURLcode result = CURLE_OK; + + DEBUGASSERT(conn && td); + DEBUGASSERT(td->thread_hnd != curl_thread_t_null); + + /* wait for the thread to resolve the name */ + if(Curl_thread_join(&td->thread_hnd)) { + if(entry) + result = getaddrinfo_complete(conn); + } + else + DEBUGASSERT(0); + + conn->async.done = TRUE; + + if(entry) + *entry = conn->async.dns; + + if(!conn->async.dns && report) + /* a name was not resolved, report error */ + result = resolver_error(conn); + + destroy_async_data(&conn->async); + + if(!conn->async.dns && report) + connclose(conn, "asynch resolve failed"); + + return result; +} + + /* * Until we gain a way to signal the resolver threads to stop early, we must * simply wait for them and ignore their results. @@ -473,7 +509,7 @@ void Curl_resolver_kill(struct connectdata *conn) unfortunately. Otherwise, we can simply cancel to clean up any resolver data. */ if(td && td->thread_hnd != curl_thread_t_null) - (void)Curl_resolver_wait_resolv(conn, NULL); + (void)thread_wait_resolv(conn, NULL, FALSE); else Curl_resolver_cancel(conn); } @@ -494,35 +530,7 @@ void Curl_resolver_kill(struct connectdata *conn) CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **entry) { - struct thread_data *td = (struct thread_data*) conn->async.os_specific; - CURLcode result = CURLE_OK; - - DEBUGASSERT(conn && td); - DEBUGASSERT(td->thread_hnd != curl_thread_t_null); - - /* wait for the thread to resolve the name */ - if(Curl_thread_join(&td->thread_hnd)) { - if(entry) - result = getaddrinfo_complete(conn); - } - else - DEBUGASSERT(0); - - conn->async.done = TRUE; - - if(entry) - *entry = conn->async.dns; - - if(!conn->async.dns) - /* a name was not resolved, report error */ - result = resolver_error(conn); - - destroy_async_data(&conn->async); - - if(!conn->async.dns) - connclose(conn, "asynch resolve failed"); - - return result; + return thread_wait_resolv(conn, entry, TRUE); } /* diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h index 7844444feb..bde4f0b331 100644 --- a/libs/libcurl/src/config-os400.h +++ b/libs/libcurl/src/config-os400.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -425,6 +425,9 @@ /* Define if you can safely include both and . */ #define TIME_WITH_SYS_TIME +/* Define to enable alt-svc support (experimental) */ +#undef USE_ALTSVC + /* Version number of package */ #undef VERSION diff --git a/libs/libcurl/src/config-vxworks.h b/libs/libcurl/src/config-vxworks.h index a03e341e62..8790f82669 100644 --- a/libs/libcurl/src/config-vxworks.h +++ b/libs/libcurl/src/config-vxworks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -161,9 +161,6 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #define HAVE_FCNTL_O_NONBLOCK 1 -/* Define to 1 if you have the fdopen function. */ -#define HAVE_FDOPEN 1 - /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 76ff0d931e..76b00b9bbf 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -240,10 +240,6 @@ /* Define if you have the socket function. */ #define HAVE_SOCKET 1 -/* 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 */ @@ -713,9 +709,6 @@ Vista /* Define to use the Windows crypto library. */ #define USE_WIN32_CRYPTO -/* if SSL is enabled */ -#define USE_OPENSSL 1 - /* Define to use Unix sockets. */ #if defined(_MSC_VER) && _MSC_VER >= 1900 /* #define USE_UNIX_SOCKETS */ diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c index 78ad386c35..39302ba7ba 100644 --- a/libs/libcurl/src/conncache.c +++ b/libs/libcurl/src/conncache.c @@ -392,8 +392,8 @@ bool Curl_conncache_foreach(struct Curl_easy *data, NOTE: no locking is done here as this is presumably only done when cleaning up a cache! */ -struct connectdata * -Curl_conncache_find_first_connection(struct conncache *connc) +static struct connectdata * +conncache_find_first_connection(struct conncache *connc) { struct curl_hash_iterator iter; struct curl_hash_element *he; @@ -433,6 +433,7 @@ bool Curl_conncache_return_conn(struct connectdata *conn) data->multi->maxconnects; struct connectdata *conn_candidate = NULL; + conn->data = NULL; /* no owner anymore */ if(maxconnects > 0 && Curl_conncache_size(data) > maxconnects) { infof(data, "Connection cache is full, closing the oldest one.\n"); @@ -476,7 +477,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn)) { + if(!CONN_INUSE(conn) && !conn->data) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->now); @@ -534,7 +535,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn)) { + if(!CONN_INUSE(conn) && !conn->data) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->now); @@ -566,7 +567,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) { struct connectdata *conn; - conn = Curl_conncache_find_first_connection(connc); + conn = conncache_find_first_connection(connc); while(conn) { SIGPIPE_VARIABLE(pipe_st); conn->data = connc->closure_handle; @@ -577,7 +578,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) (void)Curl_disconnect(connc->closure_handle, conn, FALSE); sigpipe_restore(&pipe_st); - conn = Curl_conncache_find_first_connection(connc); + conn = conncache_find_first_connection(connc); } if(connc->closure_handle) { diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index ec3cd3a795..a53d79c214 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -446,9 +446,10 @@ static CURLcode bindlocal(struct connectdata *conn, curl_socklen_t size = sizeof(add); memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { + char buffer[STRERROR_LEN]; data->state.os_errno = error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return CURLE_INTERFACE_FAILED; } infof(data, "Local port: %hu\n", port); @@ -470,10 +471,12 @@ static CURLcode bindlocal(struct connectdata *conn, else break; } - - data->state.os_errno = error = SOCKERRNO; - failf(data, "bind failed with errno %d: %s", - error, Curl_strerror(conn, error)); + { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + } return CURLE_INTERFACE_FAILED; } @@ -617,10 +620,13 @@ void Curl_persistconninfo(struct connectdata *conn) conn->data->info.conn_local_port = conn->local_port; } +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port); + /* retrieves ip address and port from a sockaddr structure. note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */ -bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, - long *port) +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) { unsigned short us_port; struct sockaddr_in *si = NULL; @@ -683,11 +689,12 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) return; if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { + char buffer[STRERROR_LEN]; len = sizeof(struct Curl_sockaddr_storage); if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { int error = SOCKERRNO; failf(data, "getpeername() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return; } @@ -696,22 +703,22 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { int error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return; } - if(!Curl_getaddressinfo((struct sockaddr*)&ssrem, - conn->primary_ip, &conn->primary_port)) { + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { failf(data, "ssrem inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - if(!Curl_getaddressinfo((struct sockaddr*)&ssloc, - conn->local_ip, &conn->local_port)) { + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { failf(data, "ssloc inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } @@ -836,9 +843,11 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(conn->tempaddr[i]) { CURLcode status; char ipaddress[MAX_IPADR_LEN]; + char buffer[STRERROR_LEN]; Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); infof(data, "connect to %s port %ld failed: %s\n", - ipaddress, conn->port, Curl_strerror(conn, error)); + ipaddress, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? allow : allow / 2; @@ -854,8 +863,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(result) { /* no more addresses to try */ - const char *hostname; + char buffer[STRERROR_LEN]; /* if the first address family runs out of addresses to try before the happy eyeball timeout, go ahead and try the next family now */ @@ -875,13 +884,14 @@ CURLcode Curl_is_connected(struct connectdata *conn, hostname = conn->host.name; failf(data, "Failed to connect to %s port %ld: %s", - hostname, conn->port, Curl_strerror(conn, error)); + hostname, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); } return result; } -void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) +static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) { #if defined(TCP_NODELAY) #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -889,6 +899,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) #endif curl_socklen_t onoff = (curl_socklen_t) 1; int level = IPPROTO_TCP; + char buffer[STRERROR_LEN]; #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) conn; @@ -897,7 +908,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); else infof(data, "TCP_NODELAY set\n"); #else @@ -917,9 +928,11 @@ static void nosigpipe(struct connectdata *conn, struct Curl_easy *data = conn->data; int onoff = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, - sizeof(onoff)) < 0) + sizeof(onoff)) < 0) { + char buffer[STRERROR_LEN]; infof(data, "Could not set SO_NOSIGPIPE: %s\n", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } } #else #define nosigpipe(x,y) Curl_nop_stmt @@ -995,6 +1008,7 @@ static CURLcode singleipconnect(struct connectdata *conn, #ifdef TCP_FASTOPEN_CONNECT int optval = 1; #endif + char buffer[STRERROR_LEN]; *sockp = CURL_SOCKET_BAD; @@ -1006,11 +1020,11 @@ static CURLcode singleipconnect(struct connectdata *conn, return CURLE_OK; /* store remote address and port used in this connection attempt */ - if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr, - ipaddress, &port)) { + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + ipaddress, &port)) { /* malformed address or bug in inet_ntop, try next address */ failf(data, "sa_addr inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); Curl_closesocket(conn, sockfd); return CURLE_OK; } @@ -1023,7 +1037,7 @@ static CURLcode singleipconnect(struct connectdata *conn, is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; #endif if(is_tcp && data->set.tcp_nodelay) - Curl_tcpnodelay(conn, sockfd); + tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); @@ -1146,7 +1160,7 @@ static CURLcode singleipconnect(struct connectdata *conn, default: /* unknown error, fallthrough and try another address! */ infof(data, "Immediate connect fail for %s: %s\n", - ipaddress, Curl_strerror(conn, error)); + ipaddress, Curl_strerror(error, buffer, sizeof(buffer))); data->state.os_errno = error; /* connect failed */ @@ -1420,7 +1434,7 @@ void Curl_conncontrol(struct connectdata *conn, if((ctrl == CONNCTRL_STREAM) && (conn->handler->flags & PROTOPT_STREAM)) DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); - else if(closeit != conn->bits.close) { + else if((bit)closeit != conn->bits.close) { DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", reason)); conn->bits.close = closeit; /* the only place in the source code that diff --git a/libs/libcurl/src/connect.h b/libs/libcurl/src/connect.h index 193dc63978..6a5c755cc1 100644 --- a/libs/libcurl/src/connect.h +++ b/libs/libcurl/src/connect.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,11 +75,6 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); void Curl_persistconninfo(struct connectdata *conn); int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); -/* - * Get presentation format IP address and port from a sockaddr. - */ -bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port); - /* * The Curl_sockaddr_ex structure is basically libcurl's external API * curl_sockaddr structure with enough space available to directly hold any @@ -111,8 +106,6 @@ CURLcode Curl_socket(struct connectdata *conn, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd); -void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd); - /* * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' * argument specifies if it is the end of a connection or a stream. diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index 4fb992ac9d..44851a52f5 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -528,6 +528,19 @@ Curl_cookie_add(struct Curl_easy *data, while(*whatptr && ISBLANK(*whatptr)) whatptr++; + /* + * Check if we have a reserved prefix set before anything else, as we + * otherwise have to test for the prefix in both the cookie name and + * "the rest". Prefixes must start with '__' and end with a '-', so + * only test for names where that can possibly be true. + */ + if(nlen > 3 && name[0] == '_' && name[1] == '_') { + if(strncasecompare("__Secure-", name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + if(!co->name) { /* The very first name/value pair is the actual cookie name */ if(!sep) { @@ -803,8 +816,6 @@ Curl_cookie_add(struct Curl_easy *data, co->domain = strdup(ptr); if(!co->domain) badcookie = TRUE; - else if(bad_domain(co->domain)) - badcookie = TRUE; break; case 1: /* This field got its explanation on the 23rd of May 2001 by @@ -862,6 +873,11 @@ Curl_cookie_add(struct Curl_easy *data, co->name = strdup(ptr); if(!co->name) badcookie = TRUE; + /* For Netscape file format cookies we check prefix on the name */ + if(strncasecompare("__Secure-", co->name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", co->name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; break; case 6: co->value = strdup(ptr); @@ -890,6 +906,26 @@ Curl_cookie_add(struct Curl_easy *data, } + if(co->prefix & COOKIE_PREFIX__SECURE) { + /* The __Secure- prefix only requires that the cookie be set secure */ + if(!co->secure) { + freecookie(co); + return NULL; + } + } + if(co->prefix & COOKIE_PREFIX__HOST) { + /* + * The __Host- prefix requires the cookie to be secure, have a "/" path + * and not have a domain set. + */ + if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch) + ; + else { + freecookie(co); + return NULL; + } + } + if(!c->running && /* read from a file */ c->newsession && /* clean session cookies */ !co->expires) { /* this is a session cookie since it doesn't expire! */ @@ -908,20 +944,18 @@ Curl_cookie_add(struct Curl_easy *data, if(!noexpire) remove_expired(c); - if(domain && co->domain && !isip(co->domain)) { - int acceptable; #ifdef USE_LIBPSL + /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ + if(domain && co->domain && !isip(co->domain)) { const psl_ctx_t *psl = Curl_psl_use(data); + int acceptable; - /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ if(psl) { acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); Curl_psl_release(data); } else -#endif - /* Without libpsl, do the best we can. */ - acceptable = !bad_domain(co->domain); + acceptable = !bad_domain(domain); if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " @@ -930,6 +964,7 @@ Curl_cookie_add(struct Curl_easy *data, return NULL; } } +#endif myhash = cookiehash(co->domain); clist = c->cookies[myhash]; @@ -1054,7 +1089,7 @@ Curl_cookie_add(struct Curl_easy *data, * get_line() makes sure to only return complete whole lines that fit in 'len' * bytes and end with a newline. */ -static char *get_line(char *buf, int len, FILE *input) +char *Curl_get_line(char *buf, int len, FILE *input) { bool partial = FALSE; while(1) { @@ -1134,7 +1169,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, line = malloc(MAX_COOKIE_LINE); if(!line) goto fail; - while(get_line(line, MAX_COOKIE_LINE, fp)) { + while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) { if(checkprefix("Set-Cookie:", line)) { /* This is a cookie line, get it! */ lineptr = &line[11]; @@ -1503,6 +1538,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) unsigned int j; struct Cookie **array; + if(!c) + /* no cookie engine alive */ + return 0; + /* at first, remove expired cookies */ remove_expired(c); diff --git a/libs/libcurl/src/cookie.h b/libs/libcurl/src/cookie.h index 3ee457c622..6ac4a6ac09 100644 --- a/libs/libcurl/src/cookie.h +++ b/libs/libcurl/src/cookie.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,8 +44,16 @@ struct Cookie { bool livecookie; /* updated from a server, not a stored file */ bool httponly; /* true if the httponly directive is present */ int creationtime; /* time when the cookie was written */ + unsigned char prefix; /* bitmap fields indicating which prefix are set */ }; +/* + * Available cookie prefixes, as defined in + * draft-ietf-httpbis-rfc6265bis-02 + */ +#define COOKIE_PREFIX__SECURE (1<<0) +#define COOKIE_PREFIX__HOST (1<<1) + #define COOKIE_HASH_SIZE 256 struct CookieInfo { @@ -93,6 +101,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, void Curl_cookie_freelist(struct Cookie *cookies); void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies); +char *Curl_get_line(char *buf, int len, FILE *input); #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) #define Curl_cookie_list(x) NULL diff --git a/libs/libcurl/src/curl_addrinfo.c b/libs/libcurl/src/curl_addrinfo.c index fd49679c93..16c4779c1e 100644 --- a/libs/libcurl/src/curl_addrinfo.c +++ b/libs/libcurl/src/curl_addrinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -539,7 +539,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ defined(HAVE_FREEADDRINFO) /* - * curl_dofreeaddrinfo() + * curl_dbg_freeaddrinfo() * * This is strictly for memory tracing and are using the same style as the * family otherwise present in memdebug.c. I put these ones here since they @@ -547,23 +547,23 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) */ void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source) +curl_dbg_freeaddrinfo(struct addrinfo *freethis, + int line, const char *source) { + curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n", + source, line, (void *)freethis); #ifdef USE_LWIPSOCK lwip_freeaddrinfo(freethis); #else (freeaddrinfo)(freethis); #endif - curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n", - source, line, (void *)freethis); } #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) /* - * curl_dogetaddrinfo() + * curl_dbg_getaddrinfo() * * This is strictly for memory tracing and are using the same style as the * family otherwise present in memdebug.c. I put these ones here since they @@ -571,11 +571,11 @@ curl_dofreeaddrinfo(struct addrinfo *freethis, */ int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source) +curl_dbg_getaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) { #ifdef USE_LWIPSOCK int res = lwip_getaddrinfo(hostname, service, hints, result); @@ -584,11 +584,11 @@ curl_dogetaddrinfo(const char *hostname, #endif if(0 == res) /* success */ - curl_memlog("ADDR %s:%d getaddrinfo() = %p\n", - source, line, (void *)*result); + curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", + source, line, (void *)*result); else - curl_memlog("ADDR %s:%d getaddrinfo() failed\n", - source, line); + curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", + source, line); return res; } #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ diff --git a/libs/libcurl/src/curl_addrinfo.h b/libs/libcurl/src/curl_addrinfo.h index 8f6f3d1064..205e121ea6 100644 --- a/libs/libcurl/src/curl_addrinfo.h +++ b/libs/libcurl/src/curl_addrinfo.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -86,17 +86,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ defined(HAVE_FREEADDRINFO) void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source); +curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source); +curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, struct addrinfo **result, + int line, const char *source); #endif #ifdef HAVE_GETADDRINFO diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index 7ab164b7b0..04ed02a566 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -190,9 +190,6 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #undef HAVE_FCNTL_O_NONBLOCK -/* Define to 1 if you have the fdopen function. */ -#undef HAVE_FDOPEN - /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH @@ -526,6 +523,9 @@ /* Define to 1 if you have a working POSIX-style strerror_r function. */ #undef HAVE_POSIX_STRERROR_R +/* Define to 1 if you have the header file. */ +#undef HAVE_PROTO_BSDSOCKET_H + /* if you have */ #undef HAVE_PTHREAD_H @@ -616,9 +616,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H -/* Define to 1 if you have the header file. */ -#undef HAVE_STDIO_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H @@ -766,9 +763,6 @@ /* Define to 1 if you have the `wolfSSLv3_client_method' function. */ #undef HAVE_WOLFSSLV3_CLIENT_METHOD -/* Define to 1 if you have the `wolfSSL_CTX_UseSupportedCurve' function. */ -#undef HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE - /* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */ #undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE @@ -925,15 +919,18 @@ /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME +/* to enable alt-svc */ +#undef USE_ALTSVC + +/* if AmiSSL is in use */ +#undef USE_AMISSL + /* Define to enable c-ares support */ #undef USE_ARES /* if CyaSSL/WolfSSL is enabled */ #undef USE_CYASSL -/* to enable Apple OS native SSL/TLS support */ -#undef USE_DARWINSSL - /* if GnuTLS is enabled */ #undef USE_GNUTLS @@ -982,6 +979,9 @@ /* to enable Windows native SSL/TLS support */ #undef USE_SCHANNEL +/* enable Secure Transport */ +#undef USE_SECTRANSP + /* if you want POSIX threaded DNS lookup */ #undef USE_THREADS_POSIX diff --git a/libs/libcurl/src/curl_endian.c b/libs/libcurl/src/curl_endian.c index c25db4956e..b7563b3ded 100644 --- a/libs/libcurl/src/curl_endian.c +++ b/libs/libcurl/src/curl_endian.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -82,7 +82,7 @@ unsigned short Curl_read16_be(const unsigned char *buf) } /* - * Curl_write32_le() + * write32_le() * * This function converts a 32-bit integer from the native endian format, * to little endian format ready for sending down the wire. @@ -92,7 +92,7 @@ unsigned short Curl_read16_be(const unsigned char *buf) * value [in] - The 32-bit integer value. * buffer [in] - A pointer to the output buffer. */ -void Curl_write32_le(const int value, unsigned char *buffer) +static void write32_le(const int value, unsigned char *buffer) { buffer[0] = (char)(value & 0x000000FF); buffer[1] = (char)((value & 0x0000FF00) >> 8); @@ -118,7 +118,7 @@ void Curl_write64_le(const long long value, unsigned char *buffer) void Curl_write64_le(const __int64 value, unsigned char *buffer) #endif { - Curl_write32_le((int)value, buffer); - Curl_write32_le((int)(value >> 32), buffer + 4); + write32_le((int)value, buffer); + write32_le((int)(value >> 32), buffer + 4); } #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/libs/libcurl/src/curl_fnmatch.c b/libs/libcurl/src/curl_fnmatch.c index fbfd85c438..846ecaec3a 100644 --- a/libs/libcurl/src/curl_fnmatch.c +++ b/libs/libcurl/src/curl_fnmatch.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -21,7 +21,7 @@ ***************************************************************************/ #include "curl_setup.h" - +#ifndef CURL_DISABLE_FTP #include #include "curl_fnmatch.h" @@ -394,3 +394,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string) } #endif + +#endif /* if FTP is disabled */ diff --git a/libs/libcurl/src/curl_gssapi.h b/libs/libcurl/src/curl_gssapi.h index 9700a28174..88f68dbbbe 100644 --- a/libs/libcurl/src/curl_gssapi.h +++ b/libs/libcurl/src/curl_gssapi.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2011 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2011 - 2019, Daniel Stenberg, , 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,19 +26,6 @@ #include "urldata.h" #ifdef HAVE_GSSAPI - -#ifdef HAVE_GSSGNU -# include -#elif defined HAVE_GSSMIT - /* MIT style */ -# include -# include -# include -#else - /* Heimdal-style */ -# include -#endif - extern gss_OID_desc Curl_spnego_mech_oid; extern gss_OID_desc Curl_krb5_mech_oid; @@ -71,5 +58,4 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, #define GSSAUTH_P_PRIVACY 4 #endif /* HAVE_GSSAPI */ - #endif /* HEADER_CURL_GSSAPI_H */ diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c index 9eb6c43c8c..e7060eb29a 100644 --- a/libs/libcurl/src/curl_ntlm_core.c +++ b/libs/libcurl/src/curl_ntlm_core.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,7 +38,7 @@ 3. USE_GNUTLS 4. USE_NSS 5. USE_MBEDTLS - 6. USE_DARWINSSL + 6. USE_SECTRANSP 7. USE_OS400CRYPTO 8. USE_WIN32_CRYPTO @@ -101,7 +101,7 @@ # include "curl_md4.h" # endif -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) # include # include @@ -290,7 +290,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; } -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) static bool encrypt_des(const unsigned char *in, unsigned char *out, const unsigned char *key_56) @@ -437,7 +437,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, setup_des_key(keys + 14, &des); gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \ +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); @@ -501,7 +501,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, setup_des_key(pw + 7, &des); gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \ +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(magic, lmbuffer, pw); encrypt_des(magic, lmbuffer + 8, pw + 7); @@ -591,7 +591,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #else Curl_md4it(ntbuffer, pw, 2 * len); #endif -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); #elif defined(USE_OS400CRYPTO) Curl_md4it(ntbuffer, pw, 2 * len); @@ -621,9 +621,9 @@ 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 */ -CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, - const unsigned char *data, unsigned int datalen, - unsigned char *output) +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); @@ -668,9 +668,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 = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), - ntlmv2hash); - + result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), + ntlmv2hash); free(identity); return result; @@ -756,8 +755,8 @@ 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 = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, - NTLMv2_BLOB_LEN + 8, hmac_output); + result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + NTLMv2_BLOB_LEN + 8, hmac_output); if(result) { free(ptr); return result; @@ -799,7 +798,7 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, memcpy(&data[0], challenge_server, 8); memcpy(&data[8], challenge_client, 8); - result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); if(result) return result; diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index a4791eb412..18ee75dd90 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -124,6 +124,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) struct passwd pw, *pw_res; char pwbuf[1024]; #endif + char buffer[STRERROR_LEN]; /* Return if communication with ntlm_auth already set up */ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || @@ -179,13 +180,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) if(access(ntlm_auth, X_OK) != 0) { failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", - ntlm_auth, errno, Curl_strerror(conn, errno)); + 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", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } @@ -194,7 +195,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose(sockfds[0]); sclose(sockfds[1]); failf(conn->data, "Could not fork. errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } else if(!child_pid) { @@ -206,13 +207,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose_nolog(sockfds[0]); if(dup2(sockfds[1], STDIN_FILENO) == -1) { failf(conn->data, "Could not redirect child stdin. errno %d: %s", - errno, Curl_strerror(conn, errno)); + 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", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } @@ -232,7 +233,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose_nolog(sockfds[1]); failf(conn->data, "Could not execl(). errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } diff --git a/libs/libcurl/src/curl_path.c b/libs/libcurl/src/curl_path.c index 68f3e44ba8..ad386e7433 100644 --- a/libs/libcurl/src/curl_path.c +++ b/libs/libcurl/src/curl_path.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,6 +22,8 @@ #include "curl_setup.h" +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) + #include #include "curl_memory.h" #include "curl_path.h" @@ -193,3 +195,5 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) Curl_safefree(*path); return CURLE_QUOTE_ERROR; } + +#endif /* if SSH is used */ diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c index f09f2f332d..16b1de1ae4 100644 --- a/libs/libcurl/src/curl_rtmp.c +++ b/libs/libcurl/src/curl_rtmp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. * Copyright (C) 2010, Howard Chu, * * This software is licensed as described in the file COPYING, which @@ -239,17 +239,18 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done) static CURLcode rtmp_do(struct connectdata *conn, bool *done) { + struct Curl_easy *data = conn->data; RTMP *r = conn->proto.generic; if(!RTMP_ConnectStream(r, 0)) return CURLE_FAILED_INIT; if(conn->data->set.upload) { - Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize); - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_pgrsSetUploadSize(data, data->state.infilesize); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); } else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); *done = TRUE; return CURLE_OK; } diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h index f83e1ea4f7..4c3a173596 100644 --- a/libs/libcurl/src/curl_setup.h +++ b/libs/libcurl/src/curl_setup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -310,11 +310,12 @@ #endif #ifdef __AMIGA__ -# ifndef __ixemul__ -# include -# include -# include -# include +# include +# include +# include +# include +# ifdef HAVE_PROTO_BSDSOCKET_H +# include /* ensure bsdsocket.library use */ # define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) # endif #endif @@ -648,7 +649,7 @@ int netware_init(void); #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \ defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK) + defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) #define USE_SSL /* SSL support has been enabled */ #endif @@ -667,7 +668,7 @@ int netware_init(void); /* Single point where USE_NTLM definition might be defined */ #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ - defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ defined(USE_MBEDTLS) @@ -816,4 +817,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); #endif +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + #endif /* HEADER_CURL_SETUP_H */ diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c index 78ef046d44..208a2336fd 100644 --- a/libs/libcurl/src/dict.c +++ b/libs/libcurl/src/dict.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -137,7 +137,6 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; char *path = data->state.up.path; - curl_off_t *bytecount = &data->req.bytecount; *done = TRUE; /* unconditionally */ @@ -200,8 +199,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) failf(data, "Failed sending DICT request"); return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */ } else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || @@ -247,8 +245,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) failf(data, "Failed sending DICT request"); return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); } else { @@ -270,7 +267,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); } } diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index f06ed3311b..b5327c4aef 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -173,8 +173,12 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result) return 0; } -#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y); \ - if(result) goto error +#define ERROR_CHECK_SETOPT(x,y) \ +do { \ + result = curl_easy_setopt(doh, x, y); \ + if(result) \ + goto error; \ +} WHILE_FALSE static CURLcode dohprobe(struct Curl_easy *data, struct dnsprobe *p, DNStype dnstype, @@ -242,7 +246,68 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); #endif ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); - ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.verbose) + ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.no_signal) + ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); + + /* Inherit *some* SSL options from the user's transfer. This is a + best-guess as to which options are needed for compatibility. #3661 */ + if(data->set.ssl.falsestart) + ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L); + if(data->set.ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); + if(data->set.proxy_ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L); + if(data->set.ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); + if(data->set.proxy_ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L); + if(data->set.ssl.primary.verifystatus) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L); + if(data->set.str[STRING_SSL_CAFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO, + data->set.str[STRING_SSL_CAFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CAFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO, + data->set.str[STRING_SSL_CAFILE_PROXY]); + } + if(data->set.str[STRING_SSL_CAPATH_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAPATH, + data->set.str[STRING_SSL_CAPATH_ORIG]); + } + if(data->set.str[STRING_SSL_CAPATH_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH, + data->set.str[STRING_SSL_CAPATH_PROXY]); + } + if(data->set.str[STRING_SSL_CRLFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CRLFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_PROXY]); + } + if(data->set.ssl.certinfo) + ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); + if(data->set.str[STRING_SSL_RANDOM_FILE]) { + ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE, + data->set.str[STRING_SSL_RANDOM_FILE]); + } + if(data->set.str[STRING_SSL_EGDSOCKET]) { + ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET, + data->set.str[STRING_SSL_EGDSOCKET]); + } + if(data->set.ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.proxy_ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.ssl.fsslctx) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); + if(data->set.ssl.fsslctxp) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); + doh->set.fmultidone = Curl_doh_done; doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 6fcad3decd..ae6176f25b 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -75,6 +75,7 @@ #include "ssh.h" #include "setopt.h" #include "http_digest.h" +#include "system_win32.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -83,70 +84,6 @@ void Curl_version_init(void); -/* win32_cleanup() is for win32 socket cleanup functionality, the opposite - of win32_init() */ -static void win32_cleanup(void) -{ -#ifdef USE_WINSOCK - WSACleanup(); -#endif -#ifdef USE_WINDOWS_SSPI - Curl_sspi_global_cleanup(); -#endif -} - -/* win32_init() performs win32 socket initialization to properly setup the - stack to allow networking */ -static CURLcode win32_init(void) -{ -#ifdef USE_WINSOCK - WORD wVersionRequested; - WSADATA wsaData; - int res; - -#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) - Error IPV6_requires_winsock2 -#endif - - wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); - - res = WSAStartup(wVersionRequested, &wsaData); - - if(res != 0) - /* Tell the user that we couldn't find a usable */ - /* winsock.dll. */ - return CURLE_FAILED_INIT; - - /* Confirm that the Windows Sockets DLL supports what we need.*/ - /* Note that if the DLL supports versions greater */ - /* than wVersionRequested, it will still return */ - /* wVersionRequested in wVersion. wHighVersion contains the */ - /* highest supported version. */ - - if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || - HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { - /* Tell the user that we couldn't find a usable */ - - /* winsock.dll. */ - WSACleanup(); - return CURLE_FAILED_INIT; - } - /* The Windows Sockets DLL is acceptable. Proceed. */ -#elif defined(USE_LWIPSOCK) - lwip_init(); -#endif - -#ifdef USE_WINDOWS_SSPI - { - CURLcode result = Curl_sspi_global_init(); - if(result) - return result; - } -#endif - - return CURLE_OK; -} - /* true globals -- for curl_global_init() and curl_global_cleanup() */ static unsigned int initialized; static long init_flags; @@ -223,11 +160,12 @@ static CURLcode global_init(long flags, bool memoryfuncs) return CURLE_FAILED_INIT; } - if(flags & CURL_GLOBAL_WIN32) - if(win32_init()) { - DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); - return CURLE_FAILED_INIT; - } +#ifdef WIN32 + if(Curl_win32_init(flags)) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif #ifdef __AMIGA__ if(!Curl_amiga_init()) { @@ -331,8 +269,9 @@ void curl_global_cleanup(void) Curl_ssl_cleanup(); Curl_resolver_global_cleanup(); - if(init_flags & CURL_GLOBAL_WIN32) - win32_cleanup(); +#ifdef WIN32 + Curl_win32_cleanup(init_flags); +#endif Curl_amiga_cleanup(); diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c index 8bba3b9165..d349cd9241 100644 --- a/libs/libcurl/src/file.c +++ b/libs/libcurl/src/file.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -311,7 +311,7 @@ static CURLcode file_upload(struct connectdata *conn) if(result) break; - if(readcount <= 0) /* fix questionable compare error. curlvms */ + if(!readcount) break; nread = readcount; diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index c5f9540002..825aaaa1d7 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -448,7 +448,6 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) static CURLcode InitiateTransfer(struct connectdata *conn) { struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; CURLcode result = CURLE_OK; if(conn->bits.ftp_use_data_ssl) { @@ -461,24 +460,19 @@ static CURLcode InitiateTransfer(struct connectdata *conn) } if(conn->proto.ftpc.state_saved == FTP_STOR) { - *(ftp->bytecountp) = 0; - /* When we know we're uploading a specified file, we can get the file size prior to the actual upload. */ - Curl_pgrsSetUploadSize(data, data->state.infilesize); /* set the SO_SNDBUF for the secondary socket for those who need it */ Curl_sndbufset(conn->sock[SECONDARYSOCKET]); - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - SECONDARYSOCKET, ftp->bytecountp); + Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET); } else { /* FTP download: */ - Curl_setup_transfer(conn, SECONDARYSOCKET, - conn->proto.ftpc.retr_size_saved, FALSE, - ftp->bytecountp, -1, NULL); /* no upload here */ + Curl_setup_transfer(data, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, -1); } conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ @@ -955,7 +949,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, unsigned short port_max = 0; unsigned short port; bool possibly_non_local = TRUE; - + char buffer[STRERROR_LEN]; char *addr = NULL; /* Step 1, figure out what is requested, @@ -1064,11 +1058,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(!host) { /* not an interface and not a host name, get default by extracting the IP from the control connection */ - sslen = sizeof(ss); if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); free(addr); return CURLE_FTP_PORT_FAILED; } @@ -1121,7 +1114,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, break; } if(!ai) { - failf(data, "socket failure: %s", Curl_strerror(conn, error)); + failf(data, "socket failure: %s", + Curl_strerror(error, buffer, sizeof(buffer))); return CURLE_FTP_PORT_FAILED; } @@ -1145,14 +1139,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* The requested bind address is not local. Use the address used for * the control connection instead and restart the port loop */ - infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, - Curl_strerror(conn, error) ); + Curl_strerror(error, buffer, sizeof(buffer))); sslen = sizeof(ss); if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1162,7 +1155,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, } if(error != EADDRINUSE && error != EACCES) { failf(data, "bind(port=%hu) failed: %s", port, - Curl_strerror(conn, error) ); + Curl_strerror(error, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1185,7 +1178,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, sslen = sizeof(ss); if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1193,7 +1186,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* step 4, listen on the socket */ if(listen(portsock, 1)) { - failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO)); + failf(data, "socket failure: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1658,7 +1652,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, infof(data, "File already completely uploaded\n"); /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); /* Set ->transfer so that we won't get any error in * ftp_done() because we didn't transfer anything! */ @@ -2230,7 +2224,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn, if(ftp->downloadsize == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); /* Set ->transfer so that we won't get any error in ftp_done() @@ -3308,33 +3302,33 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, ; else if(data->set.upload) { if((-1 != data->state.infilesize) && - (data->state.infilesize != *ftp->bytecountp) && + (data->state.infilesize != data->req.writebytecount) && !data->set.crlf && (ftp->transfer == FTPTRANSFER_BODY)) { failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", - *ftp->bytecountp, data->state.infilesize); + data->req.bytecount, data->state.infilesize); result = CURLE_PARTIAL_FILE; } } else { if((-1 != data->req.size) && - (data->req.size != *ftp->bytecountp) && + (data->req.size != data->req.bytecount) && #ifdef CURL_DO_LINEEND_CONV /* Most FTP servers don't adjust their file SIZE response for CRLFs, so * we'll check to see if the discrepancy can be explained by the number * of CRLFs we've changed to LFs. */ ((data->req.size + data->state.crlf_conversions) != - *ftp->bytecountp) && + data->req.bytecount) && #endif /* CURL_DO_LINEEND_CONV */ - (data->req.maxdownload != *ftp->bytecountp)) { + (data->req.maxdownload != data->req.bytecount)) { failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T - " bytes", *ftp->bytecountp); + " bytes", data->req.bytecount); result = CURLE_PARTIAL_FILE; } else if(!ftpc->dont_check && - !*ftp->bytecountp && + !data->req.bytecount && (data->req.size>0)) { failf(data, "No data was received!"); result = CURLE_FTP_COULDNT_RETR_FILE; @@ -3629,7 +3623,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(!result && (ftp->transfer != FTPTRANSFER_BODY)) /* no data to transfer. FIX: it feels like a kludge to have this here too! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); if(!ftpc->wait_data_conn) { /* no waiting for the data connection so this is now complete */ @@ -4308,7 +4302,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, if(ftp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); else if(!connected) /* since we didn't connect now, we want do_more to get called */ conn->bits.do_more = TRUE; @@ -4395,7 +4389,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ - data->state.slash_removed = TRUE; /* we've skipped the slash */ /* FTP URLs support an extension like ";type=" that * we'll try to get now! */ @@ -4428,7 +4421,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) } /* get some initial data into the ftp struct */ - ftp->bytecountp = &conn->data->req.bytecount; ftp->transfer = FTPTRANSFER_BODY; ftp->downloadsize = 0; diff --git a/libs/libcurl/src/ftp.h b/libs/libcurl/src/ftp.h index 38d03223ca..828d69a21d 100644 --- a/libs/libcurl/src/ftp.h +++ b/libs/libcurl/src/ftp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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 @@ typedef enum { perhaps the Curl_easy is changed between the times the connection is used. */ struct FTP { - curl_off_t *bytecountp; char *user; /* user name string */ char *passwd; /* password string */ char *path; /* points to the urlpieces struct field */ diff --git a/libs/libcurl/src/getinfo.c b/libs/libcurl/src/getinfo.c index 19de657d8b..e118da80d4 100644 --- a/libs/libcurl/src/getinfo.c +++ b/libs/libcurl/src/getinfo.c @@ -163,10 +163,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, *param_longp = (long)data->info.filetime; break; case CURLINFO_HEADER_SIZE: - *param_longp = data->info.header_size; + *param_longp = (long)data->info.header_size; break; case CURLINFO_REQUEST_SIZE: - *param_longp = data->info.request_size; + *param_longp = (long)data->info.request_size; break; case CURLINFO_SSL_VERIFYRESULT: *param_longp = data->set.ssl.certverifyresult; diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c index 485b4b79a0..b296c62d19 100644 --- a/libs/libcurl/src/gopher.c +++ b/libs/libcurl/src/gopher.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -78,8 +78,6 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - - curl_off_t *bytecount = &data->req.bytecount; char *gopherpath; char *path = data->state.up.path; char *query = data->state.up.query; @@ -90,7 +88,10 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) *done = TRUE; /* unconditionally */ - if(path && query) + /* path is guaranteed non-NULL */ + DEBUGASSERT(path); + + if(query) gopherpath = aprintf("%s?%s", path, query); else gopherpath = strdup(path); @@ -167,8 +168,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) if(result) return result; - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); return CURLE_OK; } #endif /*CURL_DISABLE_GOPHER*/ diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c index 6ff60ba61a..99d872b352 100644 --- a/libs/libcurl/src/hostasyn.c +++ b/libs/libcurl/src/hostasyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -85,14 +85,14 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, dns = Curl_cache_addr(data, ai, conn->async.hostname, conn->async.port); + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + if(!dns) { /* failed to store, cleanup and return error */ Curl_freeaddrinfo(ai); result = CURLE_OUT_OF_MEMORY; } - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); } else { result = CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index 89b88e9323..7909141c17 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -73,6 +73,8 @@ #define USE_ALARM_TIMEOUT #endif +#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + /* * hostip.c explained * ================== @@ -198,23 +200,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) } /* - * Return a hostcache id string for the provided host + port, to be used by - * the DNS caching. + * Create a hostcache id string for the provided host + port, to be used by + * the DNS caching. Without alloc. */ -static char * -create_hostcache_id(const char *name, int port) +static void +create_hostcache_id(const char *name, int port, char *ptr, size_t buflen) { - /* create and return the new allocated entry */ - char *id = aprintf("%s:%d", name, port); - char *ptr = id; - if(ptr) { - /* lower case the name part */ - while(*ptr && (*ptr != ':')) { - *ptr = (char)TOLOWER(*ptr); - ptr++; - } - } - return id; + size_t len = strlen(name); + if(len > (buflen - 7)) + len = buflen - 7; + /* store and lower case the name */ + while(len--) + *ptr++ = (char)TOLOWER(*name++); + msnprintf(ptr, 7, ":%u", port); } struct hostcache_prune_data { @@ -296,17 +294,13 @@ fetch_addr(struct connectdata *conn, const char *hostname, int port) { - char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; struct Curl_easy *data = conn->data; + char entry_id[MAX_HOSTCACHE_LEN]; /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return dns; - + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); /* See if its already in our dns cache */ @@ -314,18 +308,7 @@ fetch_addr(struct connectdata *conn, /* No entry found in cache, check if we might have a wildcard entry */ if(!dns && data->change.wildcard_resolve) { - /* - * Free the previous entry_id before requesting a new one to avoid leaking - * memory - */ - free(entry_id); - - entry_id = create_hostcache_id("*", port); - - /* If we can't create the entry id, fail */ - if(!entry_id) - return dns; - + create_hostcache_id("*", port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); /* See if it's already in our dns cache */ @@ -346,9 +329,6 @@ fetch_addr(struct connectdata *conn, } } - /* free the allocated entry_id again */ - free(entry_id); - return dns; } @@ -388,6 +368,9 @@ Curl_fetch_addr(struct connectdata *conn, return dns; } +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr); + /* * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' * struct by re-linking its linked list. @@ -400,7 +383,8 @@ Curl_fetch_addr(struct connectdata *conn, * * @unittest: 1608 */ -CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr) +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr) { CURLcode result = CURLE_OK; const int num_addrs = Curl_num_addresses(*addr); @@ -467,7 +451,7 @@ Curl_cache_addr(struct Curl_easy *data, const char *hostname, int port) { - char *entry_id; + char entry_id[MAX_HOSTCACHE_LEN]; size_t entry_len; struct Curl_dns_entry *dns; struct Curl_dns_entry *dns2; @@ -479,20 +463,16 @@ Curl_cache_addr(struct Curl_easy *data, return NULL; } - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return NULL; - entry_len = strlen(entry_id); - /* Create a new cache entry */ dns = calloc(1, sizeof(struct Curl_dns_entry)); if(!dns) { - free(entry_id); return NULL; } + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + dns->inuse = 1; /* the cache has the first reference */ dns->addr = addr; /* this is the address(es) */ time(&dns->timestamp); @@ -504,16 +484,11 @@ Curl_cache_addr(struct Curl_easy *data, (void *)dns); if(!dns2) { free(dns); - free(entry_id); return NULL; } dns = dns2; dns->inuse++; /* mark entry as in-use */ - - /* free the allocated entry_id */ - free(entry_id); - return dns; } @@ -568,7 +543,7 @@ int Curl_resolv(struct connectdata *conn, /* The entry was not in the cache. Resolve it to IP address */ Curl_addrinfo *addr; - int respwait; + int respwait = 0; /* Check what IP specifics the app has requested and if we can provide it. * If not, bail out. */ @@ -896,10 +871,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) data->change.wildcard_resolve = false; for(hostp = data->change.resolve; hostp; hostp = hostp->next) { + char entry_id[MAX_HOSTCACHE_LEN]; if(!hostp->data) continue; if(hostp->data[0] == '-') { - char *entry_id; size_t entry_len; if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { @@ -909,12 +884,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) { - return CURLE_OUT_OF_MEMORY; - } - + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); if(data->share) @@ -925,14 +895,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - /* free the allocated entry_id again */ - free(entry_id); } else { struct Curl_dns_entry *dns; Curl_addrinfo *head = NULL, *tail = NULL; - char *entry_id; size_t entry_len; char address[64]; #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -1028,12 +994,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) { - Curl_freeaddrinfo(head); - return CURLE_OUT_OF_MEMORY; - } + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); if(data->share) @@ -1054,8 +1015,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); } - /* free the allocated entry_id again */ - free(entry_id); /* put this new host in the cache */ dns = Curl_cache_addr(data, head, hostname, port); diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index 29fd1ef7cc..cd43882af6 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -178,16 +178,6 @@ Curl_fetch_addr(struct connectdata *conn, const char *hostname, int port); -/* - * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' - * struct by re-linking its linked list. - * - * The addr argument should be the address of a pointer to the head node of a - * `Curl_addrinfo` list and it will be modified to point to the new head after - * shuffling. - */ -CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr); - /* * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. * diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index e06d0343a5..fb2f35ce3d 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -101,14 +101,15 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) { printf("dump_addrinfo:\n"); for(; ai; ai = ai->ai_next) { - char buf[INET6_ADDRSTRLEN]; - + char buf[INET6_ADDRSTRLEN]; + char buffer[STRERROR_LEN]; printf(" fam %2d, CNAME %s, ", ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); if(Curl_printable_address(ai, buf, sizeof(buf))) printf("%s\n", buf); else - printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO)); + printf("failed; %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); } } #else diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index dd98e4a126..a0520b40ec 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -77,6 +77,7 @@ #include "http2.h" #include "connect.h" #include "strdup.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -102,13 +103,14 @@ static int https_getsock(struct connectdata *conn, #else #define https_connecting(x,y) CURLE_COULDNT_CONNECT #endif +static CURLcode http_setup_conn(struct connectdata *conn); /* * HTTP handler interface. */ const struct Curl_handler Curl_handler_http = { "HTTP", /* scheme */ - Curl_http_setup_conn, /* setup_connection */ + http_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ @@ -133,7 +135,7 @@ const struct Curl_handler Curl_handler_http = { */ const struct Curl_handler Curl_handler_https = { "HTTPS", /* scheme */ - Curl_http_setup_conn, /* setup_connection */ + http_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ @@ -153,7 +155,7 @@ const struct Curl_handler Curl_handler_https = { }; #endif -CURLcode Curl_http_setup_conn(struct connectdata *conn) +static CURLcode http_setup_conn(struct connectdata *conn) { /* allocate the HTTP-specific struct for the Curl_easy, only to survive during this request */ @@ -415,7 +417,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) break; } - bytessent = http->writebytecount; + bytessent = data->req.writebytecount; if(conn->bits.authneg) { /* This is a state where we are known to be negotiating and we don't send @@ -479,8 +481,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) (curl_off_t)(expectsend - bytessent)); } #endif +#if defined(USE_SPNEGO) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) || + (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) { + if(((expectsend - bytessent) < 2000) || + (conn->negotiate.state != GSS_AUTHNONE) || + (conn->proxyneg.state != GSS_AUTHNONE)) { + /* The NEGOTIATE-negotiation has started *OR* + there is just a little (<2K) data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; - /* This is not NTLM or many bytes left to send: close */ + infof(data, "NEGOTIATE send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif + + /* This is not NEGOTIATE/NTLM or many bytes left to send: close */ streamclose(conn, "Mid-auth HTTP and much data left to send"); data->req.size = 0; /* don't download any more than 0 bytes */ @@ -598,10 +628,6 @@ output_auth_headers(struct connectdata *conn, #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO) struct Curl_easy *data = conn->data; #endif -#ifdef USE_SPNEGO - struct negotiatedata *negdata = proxy ? - &data->state.proxyneg : &data->state.negotiate; -#endif #ifdef CURL_DISABLE_CRYPTO_AUTH (void)request; @@ -609,15 +635,11 @@ output_auth_headers(struct connectdata *conn, #endif #ifdef USE_SPNEGO - negdata->state = GSS_AUTHNONE; - if((authstatus->picked == CURLAUTH_NEGOTIATE) && - negdata->context && !GSS_ERROR(negdata->status)) { + if((authstatus->picked == CURLAUTH_NEGOTIATE)) { auth = "Negotiate"; result = Curl_output_negotiate(conn, proxy); if(result) return result; - authstatus->done = TRUE; - negdata->state = GSS_AUTHSENT; } else #endif @@ -750,7 +772,7 @@ Curl_http_output_auth(struct connectdata *conn, #ifndef CURL_DISABLE_PROXY /* Send proxy authentication header if needed */ if(conn->bits.httpproxy && - (conn->bits.tunnel_proxy == proxytunnel)) { + (conn->bits.tunnel_proxy == (bit)proxytunnel)) { result = output_auth_headers(conn, authproxy, request, path, TRUE); if(result) return result; @@ -794,7 +816,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, #ifdef USE_SPNEGO struct negotiatedata *negdata = proxy? - &data->state.proxyneg:&data->state.negotiate; + &conn->proxyneg:&conn->negotiate; #endif unsigned long *availp; struct auth *authp; @@ -833,21 +855,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, authp->avail |= CURLAUTH_NEGOTIATE; if(authp->picked == CURLAUTH_NEGOTIATE) { - if(negdata->state == GSS_AUTHSENT || - negdata->state == GSS_AUTHNONE) { - CURLcode result = Curl_input_negotiate(conn, proxy, auth); - if(!result) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authproblem = FALSE; - /* we received a GSS auth token and we dealt with it fine */ - negdata->state = GSS_AUTHRECV; - } - else - data->state.authproblem = TRUE; + CURLcode result = Curl_input_negotiate(conn, proxy, auth); + if(!result) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received a GSS auth token and we dealt with it fine */ + negdata->state = GSS_AUTHRECV; } + else + data->state.authproblem = TRUE; } } } @@ -1117,14 +1136,13 @@ void Curl_add_buffer_free(Curl_send_buffer **inp) CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, struct connectdata *conn, - /* add the number of sent bytes to this - counter */ - long *bytes_written, + /* add the number of sent bytes to this + counter */ + curl_off_t *bytes_written, - /* how much of the buffer contains body data */ + /* how much of the buffer contains body data */ size_t included_body_bytes, int socketindex) - { ssize_t amount; CURLcode result; @@ -1220,7 +1238,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, if(http) { /* if we sent a piece of the body here, up the byte counter for it accordingly */ - http->writebytecount += bodylen; + data->req.writebytecount += bodylen; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if((size_t)amount != size) { /* The whole request could not be sent in one system call. We must @@ -1553,20 +1572,6 @@ CURLcode Curl_http_done(struct connectdata *conn, Curl_unencode_cleanup(conn); -#ifdef USE_SPNEGO - if(data->state.proxyneg.state == GSS_AUTHSENT || - data->state.negotiate.state == GSS_AUTHSENT) { - /* add forbid re-use if http-code != 401/407 as a WA only needed for - * 401/407 that signal auth failure (empty) otherwise state will be RECV - * with current code. - * Do not close CONNECT_ONLY connections. */ - if((data->req.httpcode != 401) && (data->req.httpcode != 407) && - !data->set.connect_only) - streamclose(conn, "Negotiate transfer completed"); - Curl_cleanup_negotiate(data); - } -#endif - /* set the proper values (possibly modified on POST) */ conn->seek_func = data->set.seek_func; /* restore */ conn->seek_client = data->set.seek_client; /* restore */ @@ -1582,16 +1587,6 @@ CURLcode Curl_http_done(struct connectdata *conn, Curl_mime_cleanpart(&http->form); - switch(data->set.httpreq) { - case HTTPREQ_PUT: - case HTTPREQ_POST_FORM: - case HTTPREQ_POST_MIME: - data->req.bytecount = http->readbytecount + http->writebytecount; - break; - default: - break; - } - if(status) return status; @@ -1599,7 +1594,7 @@ CURLcode Curl_http_done(struct connectdata *conn, entire operation is complete */ !conn->bits.retry && !data->set.connect_only && - (http->readbytecount + + (data->req.bytecount + data->req.headerbytecount - data->req.deductheadercount) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was @@ -1789,9 +1784,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, } else { if(*(--ptr) == ';') { - /* send no-value custom header if terminated by semicolon */ - *ptr = ':'; - semicolonp = ptr; + /* copy the source */ + semicolonp = strdup(headers->data); + if(!semicolonp) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + /* put a colon where the semicolon is */ + semicolonp[ptr - headers->data] = ':'; + /* point at the colon */ + optr = &semicolonp [ptr - headers->data]; } } ptr = optr; @@ -1807,36 +1809,37 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, if(*ptr || semicolonp) { /* only send this if the contents was non-blank or done special */ CURLcode result = CURLE_OK; + char *compare = semicolonp ? semicolonp : headers->data; if(conn->allocptr.host && /* a Host: header was sent already, don't pass on any custom Host: header as that will produce *two* in the same request! */ - checkprefix("Host:", headers->data)) + checkprefix("Host:", compare)) ; else if(data->set.httpreq == HTTPREQ_POST_FORM && /* this header (extended by formdata.c) is sent later */ - checkprefix("Content-Type:", headers->data)) + checkprefix("Content-Type:", compare)) ; else if(data->set.httpreq == HTTPREQ_POST_MIME && /* this header is sent later */ - checkprefix("Content-Type:", headers->data)) + checkprefix("Content-Type:", compare)) ; else if(conn->bits.authneg && /* while doing auth neg, don't allow the custom length since we will force length zero then */ - checkprefix("Content-Length:", headers->data)) + checkprefix("Content-Length:", compare)) ; else if(conn->allocptr.te && /* when asking for Transfer-Encoding, don't pass on a custom Connection: */ - checkprefix("Connection:", headers->data)) + checkprefix("Connection:", compare)) ; else if((conn->httpversion == 20) && - checkprefix("Transfer-Encoding:", headers->data)) + checkprefix("Transfer-Encoding:", compare)) /* HTTP/2 doesn't support chunked requests */ ; - else if((checkprefix("Authorization:", headers->data) || - checkprefix("Cookie:", headers->data)) && + else if((checkprefix("Authorization:", compare) || + checkprefix("Cookie:", compare)) && /* be careful of sending this potentially sensitive header to other hosts */ (data->state.this_is_a_follow && @@ -1845,10 +1848,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, !strcasecompare(data->state.first_host, conn->host.name))) ; else { - result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data); + result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare); } if(semicolonp) - *semicolonp = ';'; /* put back the semicolon */ + free(semicolonp); if(result) return result; } @@ -2000,7 +2003,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->state.first_remote_port = conn->remote_port; } - http->writebytecount = http->readbytecount = 0; if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && data->set.upload) { @@ -2061,7 +2063,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if((data->state.authhost.multipass || data->state.authproxy.multipass) && + if(((data->state.authhost.multipass && !data->state.authhost.done) + || (data->state.authproxy.multipass && !data->state.authproxy.done)) && (httpreq != HTTPREQ_GET) && (httpreq != HTTPREQ_HEAD)) { /* Auth is required and we are not authenticated yet. Make a PUT or POST @@ -2697,9 +2700,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending PUT request"); else /* prepare for transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); if(result) return result; break; @@ -2719,12 +2721,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); break; } - postsize = http->postsize; + data->state.infilesize = postsize = http->postsize; /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both @@ -2788,9 +2789,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* prepare for transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); if(result) return result; @@ -2944,9 +2944,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) failf(data, "Failed sending HTTP POST request"); else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); break; default: @@ -2962,33 +2961,30 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); } if(result) return result; - if(http->writebytecount) { + if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; - if(http->writebytecount >= postsize) { + if(data->req.writebytecount >= postsize) { /* already sent the entire request body, mark the "upload" as complete */ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", - http->writebytecount, postsize); + data->req.writebytecount, postsize); data->req.upload_done = TRUE; data->req.keepon &= ~KEEP_SEND; /* we're done writing */ data->req.exp100 = EXP100_SEND_DATA; /* already sent */ Curl_expire_done(data, EXPIRE_100_TIMEOUT); } - else - data->req.writebytecount = http->writebytecount; } if((conn->httpversion == 20) && data->req.upload_chunky) @@ -3383,7 +3379,24 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, data->state.authproblem = TRUE; } #endif - +#if defined(USE_SPNEGO) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->negotiate.state == GSS_AUTHRECV)) || + ((data->req.httpcode == 407) && + (conn->proxyneg.state == GSS_AUTHRECV)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } + if((conn->negotiate.state == GSS_AUTHDONE) && + (data->req.httpcode != 401)) { + conn->negotiate.state = GSS_AUTHSUCC; + } + if((conn->proxyneg.state == GSS_AUTHDONE) && + (data->req.httpcode != 407)) { + conn->proxyneg.state = GSS_AUTHSUCC; + } +#endif /* * When all the headers have been parsed, see if we should give * up and return an error. @@ -3960,6 +3973,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(result) return result; } + #ifdef USE_SPNEGO + else if(checkprefix("Persistent-Auth", k->p)) { + struct negotiatedata *negdata = &conn->negotiate; + struct auth *authp = &data->state.authhost; + if(authp->picked == CURLAUTH_NEGOTIATE) { + char *persistentauth = Curl_copy_header_value(k->p); + if(!persistentauth) + return CURLE_OUT_OF_MEMORY; + negdata->noauthpersist = checkprefix("false", persistentauth); + negdata->havenoauthpersist = TRUE; + infof(data, "Negotiate: noauthpersist -> %d, header part: %s", + negdata->noauthpersist, persistentauth); + free(persistentauth); + } + } + #endif else if((k->httpcode >= 300 && k->httpcode < 400) && checkprefix("Location:", k->p) && !data->req.location) { @@ -3987,6 +4016,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } } } +#ifdef USE_ALTSVC + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->asi && checkprefix("Alt-Svc:", k->p) && + ((conn->handler->flags & PROTOPT_SSL) || +#ifdef CURLDEBUG + /* allow debug builds to circumvent the HTTPS restriction */ + getenv("CURL_ALTSVC_HTTP") +#else + 0 +#endif + )) { + /* the ALPN of the current request */ + enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; + result = Curl_altsvc_parse(data, data->asi, + &k->p[ strlen("Alt-Svc:") ], + id, conn->host.name, + curlx_uitous(conn->remote_port)); + if(result) + return result; + } +#endif else if(conn->handler->protocol & CURLPROTO_RTSP) { result = Curl_rtsp_parseheader(conn, k->p); if(result) diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index 7fa0471ad0..a59fe7af0e 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -65,7 +65,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, size_t size) WARN_UNUSED_RESULT; CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, struct connectdata *conn, - long *bytes_written, + curl_off_t *bytes_written, size_t included_body_bytes, int socketindex); @@ -139,8 +139,6 @@ struct HTTP { const char *p_pragma; /* Pragma: string */ const char *p_accept; /* Accept: string */ - curl_off_t readbytecount; - curl_off_t writebytecount; /* For FORM posting */ curl_mimepart form; diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index 3b8088dffc..b5c53cdf60 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -357,7 +357,7 @@ int Curl_http2_ver(char *p, size_t len) https://tools.ietf.org/html/rfc7540#page-77 nghttp2_error_code enums are identical. */ -const char *Curl_http2_strerror(uint32_t err) +static const char *http2_strerror(uint32_t err) { #ifndef NGHTTP2_HAS_HTTP2_STRERROR const char *str[] = { @@ -618,6 +618,18 @@ static int push_promise(struct Curl_easy *data, return rv; } +/* + * multi_connchanged() is called to tell that there is a connection in + * this multi handle that has changed state (pipelining become possible, the + * number of allowed streams changed or similar), and a subsequent use of this + * multi handle should move CONNECT_PEND handles back to CONNECT to have them + * retry. + */ +static void multi_connchanged(struct Curl_multi *multi) +{ + multi->recheckstate = TRUE; +} + static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { @@ -650,7 +662,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, infof(conn->data, "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", httpc->settings.max_concurrent_streams); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); } } return 0; @@ -837,7 +849,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", - Curl_http2_strerror(error_code), error_code, stream_id)); + http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -957,6 +969,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { char *h; + if(!strcmp(":authority", (const char *)name)) { + /* psuedo headers are lower case */ + int rc = 0; + char *check = aprintf("%s:%d", conn->host.name, conn->remote_port); + if(!check) + /* no memory */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + if(!Curl_strcasecompare(check, (const char *)value)) { + /* This is push is not for the same authority that was asked for in + * the URL. RFC 7540 section 8.2 says: "A client MUST treat a + * PUSH_PROMISE for which the server is not authoritative as a stream + * error of type PROTOCOL_ERROR." + */ + (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + rc = NGHTTP2_ERR_CALLBACK_FAILURE; + } + free(check); + if(rc) + return rc; + } + if(!stream->push_headers) { stream->push_headers_alloc = 10; stream->push_headers = malloc(stream->push_headers_alloc * @@ -1197,7 +1231,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature) /* * Initialize nghttp2 for a Curl connection */ -CURLcode Curl_http2_init(struct connectdata *conn) +static CURLcode http2_init(struct connectdata *conn) { if(!conn->proto.httpc.h2) { int rc; @@ -1431,7 +1465,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, Curl_http2_strerror(httpc->error_code), + stream->stream_id, http2_strerror(httpc->error_code), httpc->error_code); *err = CURLE_HTTP2_STREAM; return -1; @@ -2141,7 +2175,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) else conn->handler = &Curl_handler_http2; - result = Curl_http2_init(conn); + result = http2_init(conn); if(result) { Curl_add_buffer_free(&stream->header_recvbuf); return result; @@ -2163,7 +2197,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) conn->bundle->multiuse = BUNDLE_MULTIPLEX; infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); return CURLE_OK; } diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h index 67db3dffb0..db6217b11e 100644 --- a/libs/libcurl/src/http2.h +++ b/libs/libcurl/src/http2.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -63,7 +63,6 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data); /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ bool Curl_h2_http_1_1_error(struct connectdata *conn); #else /* USE_NGHTTP2 */ -#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c index 2a97707eba..9415236fb1 100644 --- a/libs/libcurl/src/http_negotiate.c +++ b/libs/libcurl/src/http_negotiate.c @@ -56,7 +56,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, service = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; host = conn->http_proxy.host.name; - neg_ctx = &data->state.proxyneg; + neg_ctx = &conn->proxyneg; } else { userp = conn->user; @@ -64,7 +64,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : "HTTP"; host = conn->host.name; - neg_ctx = &data->state.negotiate; + neg_ctx = &conn->negotiate; } /* Not set means empty */ @@ -80,11 +80,16 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, header++; len = strlen(header); + neg_ctx->havenegdata = len != 0; if(!len) { - /* Is this the first call in a new negotiation? */ - if(neg_ctx->context) { - /* The server rejected our authentication and hasn't suppled any more + if(neg_ctx->state == GSS_AUTHSUCC) { + infof(conn->data, "Negotiate auth restarted\n"); + Curl_cleanup_negotiate(conn); + } + else if(neg_ctx->state != GSS_AUTHNONE) { + /* The server rejected our authentication and hasn't supplied any more negotiation mechanisms */ + Curl_cleanup_negotiate(conn); return CURLE_LOGIN_DENIED; } } @@ -106,38 +111,96 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) { - struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg : - &conn->data->state.negotiate; + struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg : + &conn->negotiate; + struct auth *authp = proxy ? &conn->data->state.authproxy : + &conn->data->state.authhost; char *base64 = NULL; size_t len = 0; char *userp; CURLcode result; - result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len); - if(result) - return result; + authp->done = FALSE; + + if(neg_ctx->state == GSS_AUTHRECV) { + if(neg_ctx->havenegdata) { + neg_ctx->havemultiplerequests = TRUE; + } + } + else if(neg_ctx->state == GSS_AUTHSUCC) { + if(!neg_ctx->havenoauthpersist) { + neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests; + } + } - userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", - base64); + if(neg_ctx->noauthpersist || + (neg_ctx->state != GSS_AUTHDONE && neg_ctx->state != GSS_AUTHSUCC)) { - if(proxy) { - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = userp; + if(neg_ctx->noauthpersist && neg_ctx->state == GSS_AUTHSUCC) { + infof(conn->data, "Curl_output_negotiate, " + "no persistent authentication: cleanup existing context"); + Curl_auth_spnego_cleanup(neg_ctx); + } + if(!neg_ctx->context) { + result = Curl_input_negotiate(conn, proxy, "Negotiate"); + if(result) + return result; + } + + result = Curl_auth_create_spnego_message(conn->data, + neg_ctx, &base64, &len); + if(result) + return result; + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + base64); + + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + + free(base64); + + if(userp == NULL) { + return CURLE_OUT_OF_MEMORY; + } + + neg_ctx->state = GSS_AUTHSENT; + #ifdef HAVE_GSSAPI + if(neg_ctx->status == GSS_S_COMPLETE || + neg_ctx->status == GSS_S_CONTINUE_NEEDED) { + neg_ctx->state = GSS_AUTHDONE; + } + #else + #ifdef USE_WINDOWS_SSPI + if(neg_ctx->status == SEC_E_OK || + neg_ctx->status == SEC_I_CONTINUE_NEEDED) { + neg_ctx->state = GSS_AUTHDONE; + } + #endif + #endif } - else { - Curl_safefree(conn->allocptr.userpwd); - conn->allocptr.userpwd = userp; + + if(neg_ctx->state == GSS_AUTHDONE || neg_ctx->state == GSS_AUTHSUCC) { + /* connection is already authenticated, + * don't send a header in future requests */ + authp->done = TRUE; } - free(base64); + neg_ctx->havenegdata = FALSE; - return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; + return CURLE_OK; } -void Curl_cleanup_negotiate(struct Curl_easy *data) +void Curl_cleanup_negotiate(struct connectdata *conn) { - Curl_auth_spnego_cleanup(&data->state.negotiate); - Curl_auth_spnego_cleanup(&data->state.proxyneg); + Curl_auth_spnego_cleanup(&conn->negotiate); + Curl_auth_spnego_cleanup(&conn->proxyneg); } #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ diff --git a/libs/libcurl/src/http_negotiate.h b/libs/libcurl/src/http_negotiate.h index c64e548251..d4a7f09e09 100644 --- a/libs/libcurl/src/http_negotiate.h +++ b/libs/libcurl/src/http_negotiate.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, /* this is for creating Negotiate header output */ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); -void Curl_cleanup_negotiate(struct Curl_easy *data); +void Curl_cleanup_negotiate(struct connectdata *conn); #endif /* USE_SPNEGO */ diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index 5d96900f89..075b3ad201 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -1177,11 +1177,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, if(data->req.bytecount == size) /* The entire data is already transferred! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); else { /* IMAP download */ data->req.maxdownload = size; - Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1); } } else { @@ -1231,7 +1231,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, Curl_pgrsSetUploadSize(data, data->state.infilesize); /* IMAP upload */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ state(conn, IMAP_STOP); @@ -1660,7 +1660,7 @@ static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) if(imap->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); return CURLE_OK; } diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c index a149f8cbc3..79dc2f2ed8 100644 --- a/libs/libcurl/src/ldap.c +++ b/libs/libcurl/src/ldap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -744,7 +744,7 @@ quit: #endif /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); connclose(conn, "LDAP connection always disable re-use"); return result; diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index 13f2cf742a..7d005b7955 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ se.haxx.curl.libcurl CFBundleVersion - 7.64.0 + 7.64.1 CFBundleName libcurl @@ -27,9 +27,9 @@ ???? CFBundleShortVersionString - libcurl 7.64.0 + libcurl 7.64.1 CFBundleGetInfoString - libcurl.plist 7.64.0 + libcurl.plist 7.64.1 diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c index a17a58fa61..db4cc2656f 100644 --- a/libs/libcurl/src/md5.c +++ b/libs/libcurl/src/md5.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -83,7 +83,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) gcry_md_close(*ctx); } -#elif defined(USE_OPENSSL) +#elif defined(USE_OPENSSL) && !defined(USE_AMISSL) /* When OpenSSL is available we use the MD5-function from OpenSSL */ #include #include "curl_memory.h" diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c index 05590a8f83..e3ac8edf74 100644 --- a/libs/libcurl/src/memdebug.c +++ b/libs/libcurl/src/memdebug.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -100,19 +100,18 @@ struct memdebug { * Don't use these with multithreaded test programs! */ -#define logfile curl_debuglogfile -FILE *curl_debuglogfile = NULL; +FILE *curl_dbg_logfile = NULL; static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ /* this sets the log file name */ -void curl_memdebug(const char *logname) +void curl_dbg_memdebug(const char *logname) { - if(!logfile) { + if(!curl_dbg_logfile) { if(logname && *logname) - logfile = fopen(logname, FOPEN_WRITETEXT); + curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT); else - logfile = stderr; + curl_dbg_logfile = stderr; #ifdef MEMDEBUG_LOG_SYNC /* Flush the log file after every line so the log isn't lost in a crash */ if(logfile) @@ -123,7 +122,7 @@ void curl_memdebug(const char *logname) /* This function sets the number of malloc() calls that should return successfully! */ -void curl_memlimit(long limit) +void curl_dbg_memlimit(long limit) { if(!memlimit) { memlimit = TRUE; @@ -140,12 +139,12 @@ static bool countcheck(const char *func, int line, const char *source) if(!memsize) { if(source) { /* log to file */ - curl_memlog("LIMIT %s:%d %s reached memlimit\n", - source, line, func); + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", + source, line, func); /* log to stderr also */ fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", source, line, func); - fflush(logfile); /* because it might crash now */ + fflush(curl_dbg_logfile); /* because it might crash now */ } errno = ENOMEM; return TRUE; /* RETURN ERROR! */ @@ -159,7 +158,7 @@ static bool countcheck(const char *func, int line, const char *source) return FALSE; /* allow this */ } -void *curl_domalloc(size_t wantedsize, int line, const char *source) +void *curl_dbg_malloc(size_t wantedsize, int line, const char *source) { struct memdebug *mem; size_t size; @@ -180,15 +179,15 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source) } if(source) - curl_memlog("MEM %s:%d malloc(%zu) = %p\n", - source, line, wantedsize, - mem ? (void *)mem->mem : (void *)0); + curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n", + source, line, wantedsize, + mem ? (void *)mem->mem : (void *)0); return (mem ? mem->mem : NULL); } -void *curl_docalloc(size_t wanted_elements, size_t wanted_size, - int line, const char *source) +void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size, + int line, const char *source) { struct memdebug *mem; size_t size, user_size; @@ -208,14 +207,14 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size, mem->size = user_size; if(source) - curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n", - source, line, wanted_elements, wanted_size, - mem ? (void *)mem->mem : (void *)0); + curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n", + source, line, wanted_elements, wanted_size, + mem ? (void *)mem->mem : (void *)0); return (mem ? mem->mem : NULL); } -char *curl_dostrdup(const char *str, int line, const char *source) +char *curl_dbg_strdup(const char *str, int line, const char *source) { char *mem; size_t len; @@ -227,19 +226,19 @@ char *curl_dostrdup(const char *str, int line, const char *source) len = strlen(str) + 1; - mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */ + mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */ if(mem) memcpy(mem, str, len); if(source) - curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n", - source, line, (const void *)str, len, (const void *)mem); + curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n", + source, line, (const void *)str, len, (const void *)mem); return mem; } #if defined(WIN32) && defined(UNICODE) -wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) +wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) { wchar_t *mem; size_t wsiz, bsiz; @@ -252,12 +251,12 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) wsiz = wcslen(str) + 1; bsiz = wsiz * sizeof(wchar_t); - mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */ + mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */ if(mem) memcpy(mem, str, bsiz); if(source) - curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n", + curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n", source, line, (void *)str, bsiz, (void *)mem); return mem; @@ -266,8 +265,8 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) /* We provide a realloc() that accepts a NULL as pointer, which then performs a malloc(). In order to work with ares. */ -void *curl_dorealloc(void *ptr, size_t wantedsize, - int line, const char *source) +void *curl_dbg_realloc(void *ptr, size_t wantedsize, + int line, const char *source) { struct memdebug *mem = NULL; @@ -293,7 +292,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize, mem = (Curl_crealloc)(mem, size); if(source) - curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n", + curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n", source, line, (void *)ptr, wantedsize, mem ? (void *)mem->mem : (void *)0); @@ -305,7 +304,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize, return NULL; } -void curl_dofree(void *ptr, int line, const char *source) +void curl_dbg_free(void *ptr, int line, const char *source) { struct memdebug *mem; @@ -331,11 +330,11 @@ void curl_dofree(void *ptr, int line, const char *source) } if(source) - curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr); + curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); } -curl_socket_t curl_socket(int domain, int type, int protocol, - int line, const char *source) +curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d socket() = %d\n" : @@ -351,44 +350,44 @@ curl_socket_t curl_socket(int domain, int type, int protocol, sockfd = socket(domain, type, protocol); if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); return sockfd; } -SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd, - SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, - SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, - const char *source) +SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, + const char *source) { SEND_TYPE_RETV rc; if(countcheck("send", line, source)) return -1; rc = send(sockfd, buf, len, flags); if(source) - curl_memlog("SEND %s:%d send(%lu) = %ld\n", + curl_dbg_log("SEND %s:%d send(%lu) = %ld\n", source, line, (unsigned long)len, (long)rc); return rc; } -RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, - RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, - const char *source) +RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, + const char *source) { RECV_TYPE_RETV rc; if(countcheck("recv", line, source)) return -1; rc = recv(sockfd, buf, len, flags); if(source) - curl_memlog("RECV %s:%d recv(%lu) = %ld\n", + curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n", source, line, (unsigned long)len, (long)rc); return rc; } #ifdef HAVE_SOCKETPAIR -int curl_socketpair(int domain, int type, int protocol, - curl_socket_t socket_vector[2], - int line, const char *source) +int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d socketpair() = %d %d\n" : @@ -399,14 +398,14 @@ int curl_socketpair(int domain, int type, int protocol, int res = socketpair(domain, type, protocol, socket_vector); if(source && (0 == res)) - curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]); + curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]); return res; } #endif -curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, - int line, const char *source) +curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen, + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d accept() = %d\n" : @@ -420,13 +419,13 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, curl_socket_t sockfd = accept(s, addr, addrlen); if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); return sockfd; } /* separate function to allow libcurl to mark a "faked" close */ -void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) +void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d sclose(%d)\n": @@ -435,54 +434,40 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) "FD %s:%d sclose(%zd)\n"; if(source) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); } /* this is our own defined way to close sockets on *ALL* platforms */ -int curl_sclose(curl_socket_t sockfd, int line, const char *source) +int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source) { int res = sclose(sockfd); - curl_mark_sclose(sockfd, line, source); + curl_dbg_mark_sclose(sockfd, line, source); return res; } -FILE *curl_fopen(const char *file, const char *mode, - int line, const char *source) +FILE *curl_dbg_fopen(const char *file, const char *mode, + int line, const char *source) { FILE *res = fopen(file, mode); if(source) - curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", + curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", source, line, file, mode, (void *)res); return res; } -#ifdef HAVE_FDOPEN -FILE *curl_fdopen(int filedes, const char *mode, - int line, const char *source) -{ - FILE *res = fdopen(filedes, mode); - - if(source) - curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", - source, line, filedes, mode, (void *)res); - - return res; -} -#endif - -int curl_fclose(FILE *file, int line, const char *source) +int curl_dbg_fclose(FILE *file, int line, const char *source) { int res; DEBUGASSERT(file != NULL); - res = fclose(file); - if(source) - curl_memlog("FILE %s:%d fclose(%p)\n", - source, line, (void *)file); + curl_dbg_log("FILE %s:%d fclose(%p)\n", + source, line, (void *)file); + + res = fclose(file); return res; } @@ -490,13 +475,13 @@ int curl_fclose(FILE *file, int line, const char *source) #define LOGLINE_BUFSIZE 1024 /* this does the writing to the memory tracking log file */ -void curl_memlog(const char *format, ...) +void curl_dbg_log(const char *format, ...) { char *buf; int nchars; va_list ap; - if(!logfile) + if(!curl_dbg_logfile) return; buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); @@ -511,7 +496,7 @@ void curl_memlog(const char *format, ...) nchars = LOGLINE_BUFSIZE - 1; if(nchars > 0) - fwrite(buf, 1, (size_t)nchars, logfile); + fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile); (Curl_cfree)(buf); } diff --git a/libs/libcurl/src/memdebug.h b/libs/libcurl/src/memdebug.h index 233de65a47..5236f60fa5 100644 --- a/libs/libcurl/src/memdebug.h +++ b/libs/libcurl/src/memdebug.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,97 +30,92 @@ #define CURL_MT_LOGFNAME_BUFSIZE 512 -#define logfile curl_debuglogfile - -extern FILE *logfile; +extern FILE *curl_dbg_logfile; /* memory functions */ -CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source); -CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line, - const char *source); -CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line, - const char *source); -CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source); -CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source); -#if defined(WIN32) && defined(UNICODE) -CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line, +CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line, const char *source); +CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, + const char *source); #endif -CURL_EXTERN void curl_memdebug(const char *logname); -CURL_EXTERN void curl_memlimit(long limit); -CURL_EXTERN void curl_memlog(const char *format, ...); +CURL_EXTERN void curl_dbg_memdebug(const char *logname); +CURL_EXTERN void curl_dbg_memlimit(long limit); +CURL_EXTERN void curl_dbg_log(const char *format, ...); /* file descriptor manipulators */ -CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol, - int line, const char *source); -CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd, - int line, const char *source); -CURL_EXTERN int curl_sclose(curl_socket_t sockfd, - int line, const char *source); -CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen, +CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source); +CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source); -#ifdef HAVE_SOCKETPAIR -CURL_EXTERN int curl_socketpair(int domain, int type, int protocol, - curl_socket_t socket_vector[2], +CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source); +CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source); #endif /* send/receive sockets */ -CURL_EXTERN SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd, - SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, - SEND_TYPE_ARG3 len, - SEND_TYPE_ARG4 flags, int line, - const char *source); -CURL_EXTERN RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, - RECV_TYPE_ARG2 buf, RECV_TYPE_ARG3 len, - RECV_TYPE_ARG4 flags, int line, - const char *source); +CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, + SEND_TYPE_ARG4 flags, int line, + const char *source); +CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, + RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, + RECV_TYPE_ARG4 flags, int line, + const char *source); /* FILE functions */ -CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line, - const char *source); -#ifdef HAVE_FDOPEN -CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line, - const char *source); -#endif -CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); +CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, + const char *source); +CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); #ifndef MEMDEBUG_NODEFINES /* Set this symbol on the command-line, recompile all lib-sources */ #undef strdup -#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) -#define malloc(size) curl_domalloc(size, __LINE__, __FILE__) -#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__) -#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__) -#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__) -#define send(a,b,c,d) curl_dosend(a,b,c,d, __LINE__, __FILE__) -#define recv(a,b,c,d) curl_dorecv(a,b,c,d, __LINE__, __FILE__) +#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) +#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) +#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) #ifdef WIN32 # ifdef UNICODE # undef wcsdup -# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # undef _wcsdup -# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # undef _tcsdup -# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # else # undef _tcsdup -# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) +# define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) # endif #endif #undef socket #define socket(domain,type,protocol)\ - curl_socket(domain, type, protocol, __LINE__, __FILE__) + curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__) #undef accept /* for those with accept as a macro */ #define accept(sock,addr,len)\ - curl_accept(sock, addr, len, __LINE__, __FILE__) + curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) #ifdef HAVE_SOCKETPAIR #define socketpair(domain,type,protocol,socket_vector)\ - curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) + curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) #endif #ifdef HAVE_GETADDRINFO @@ -129,31 +124,31 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); our macro as for other platforms. Instead, we redefine the new name they define getaddrinfo to become! */ #define ogetaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) #else #undef getaddrinfo #define getaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) #endif #endif /* HAVE_GETADDRINFO */ #ifdef HAVE_FREEADDRINFO #undef freeaddrinfo #define freeaddrinfo(data) \ - curl_dofreeaddrinfo(data, __LINE__, __FILE__) + curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) #endif /* HAVE_FREEADDRINFO */ /* sclose is probably already defined, redefine it! */ #undef sclose -#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__) +#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) -#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__) +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) #undef fopen -#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__) +#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) #undef fdopen -#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__) -#define fclose(file) curl_fclose(file,__LINE__,__FILE__) +#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) #endif /* MEMDEBUG_NODEFINES */ diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index ca492d11ae..48147d4f59 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1122,8 +1122,6 @@ void curl_mime_free(curl_mime *mime) Curl_mime_cleanpart(part); free(part); } - - free(mime->boundary); free(mime); } } @@ -1220,18 +1218,10 @@ curl_mime *curl_mime_init(struct Curl_easy *easy) mime->firstpart = NULL; mime->lastpart = NULL; - /* Get a part boundary. */ - mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1); - if(!mime->boundary) { - free(mime); - return NULL; - } - memset(mime->boundary, '-', 24); - if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24, + if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24], MIME_RAND_BOUNDARY_CHARS + 1)) { /* failed to get random separator, bail out */ - free(mime->boundary); free(mime); return NULL; } diff --git a/libs/libcurl/src/mime.h b/libs/libcurl/src/mime.h index 4d5c70404d..0721c8ca45 100644 --- a/libs/libcurl/src/mime.h +++ b/libs/libcurl/src/mime.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,13 +88,16 @@ typedef struct { size_t offset; /* State-dependent offset. */ } mime_state; +/* minimum buffer size for the boundary string */ +#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1) + /* A mime multipart. */ struct curl_mime_s { struct Curl_easy *easy; /* The associated easy handle. */ curl_mimepart *parent; /* Parent part. */ curl_mimepart *firstpart; /* First part. */ curl_mimepart *lastpart; /* Last part. */ - char *boundary; /* The part boundary. */ + char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */ mime_state state; /* Current readback state. */ }; diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index 130226f561..cc16924a3c 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -80,6 +80,7 @@ static CURLMcode add_next_timeout(struct curltime now, static CURLMcode multi_timeout(struct Curl_multi *multi, long *timeout_ms); static void process_pending_handles(struct Curl_multi *multi); +static void detach_connnection(struct Curl_easy *data); #ifdef DEBUGBUILD static const char * const statename[]={ @@ -114,7 +115,7 @@ static void Curl_init_completed(struct Curl_easy *data) /* Important: reset the conn pointer so that we don't point to memory that could be freed anytime */ - Curl_detach_connnection(data); + detach_connnection(data); Curl_expire_clear(data); /* stop all timers */ } @@ -496,6 +497,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->set.server_response_timeout; data->state.conn_cache->closure_handle->set.no_signal = data->set.no_signal; + data->state.conn_cache->closure_handle->set.verbose = + data->set.verbose; update_timer(multi); return CURLM_OK; @@ -572,7 +575,7 @@ static CURLcode multi_done(struct Curl_easy *data, if(conn->send_pipe.size || conn->recv_pipe.size) { /* Stop if pipeline is not empty . */ - Curl_detach_connnection(data); + detach_connnection(data); DEBUGF(infof(data, "Connection still in use %zu/%zu, " "no more multi_done now!\n", conn->send_pipe.size, conn->recv_pipe.size)); @@ -597,7 +600,7 @@ static CURLcode multi_done(struct Curl_easy *data, /* if data->set.reuse_forbid is TRUE, it means the libcurl client has forced us to close this connection. This is ignored for requests taking - place in a NTLM authentication handshake + place in a NTLM/NEGOTIATE authentication handshake if conn->bits.close is TRUE, it means that the connection should be closed in spite of all our efforts to be nice, due to protocol @@ -614,6 +617,10 @@ static CURLcode multi_done(struct Curl_easy *data, #if defined(USE_NTLM) && !(conn->ntlm.state == NTLMSTATE_TYPE2 || conn->proxyntlm.state == NTLMSTATE_TYPE2) +#endif +#if defined(USE_SPNEGO) + && !(conn->negotiate.state == GSS_AUTHRECV || + conn->proxyneg.state == GSS_AUTHRECV) #endif ) || conn->bits.close || (premature && !(conn->handler->flags & PROTOPT_STREAM))) { @@ -645,7 +652,7 @@ static CURLcode multi_done(struct Curl_easy *data, data->state.lastconnect = NULL; } - Curl_detach_connnection(data); + detach_connnection(data); Curl_free_request_state(data); return result; } @@ -752,7 +759,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* Remove the association between the connection and the handle */ if(data->conn) { data->conn->data = NULL; - Curl_detach_connnection(data); + detach_connnection(data); } #ifdef USE_LIBPSL @@ -804,7 +811,7 @@ bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits) /* This is the only function that should clear data->conn. This will occasionally be called with the pointer already cleared. */ -void Curl_detach_connnection(struct Curl_easy *data) +static void detach_connnection(struct Curl_easy *data) { data->conn = NULL; } @@ -998,11 +1005,11 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, unsigned int i; unsigned int nfds = 0; unsigned int curlfds; - struct pollfd *ufds = NULL; bool ufds_malloc = FALSE; long timeout_internal; int retcode = 0; struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; + struct pollfd *ufds = &a_few_on_stack[0]; if(gotsocket) *gotsocket = FALSE; @@ -1047,19 +1054,15 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, curlfds = nfds; /* number of internal file descriptors */ nfds += extra_nfds; /* add the externally provided ones */ - if(nfds) { - if(nfds > NUM_POLLS_ON_STACK) { - /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes - big, so at 2^29 sockets this value might wrap. When a process gets - the capability to actually handle over 500 million sockets this - calculation needs a integer overflow check. */ - ufds = malloc(nfds * sizeof(struct pollfd)); - if(!ufds) - return CURLM_OUT_OF_MEMORY; - ufds_malloc = TRUE; - } - else - ufds = &a_few_on_stack[0]; + if(nfds > NUM_POLLS_ON_STACK) { + /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes + big, so at 2^29 sockets this value might wrap. When a process gets + the capability to actually handle over 500 million sockets this + calculation needs a integer overflow check. */ + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + ufds_malloc = TRUE; } nfds = 0; @@ -1154,17 +1157,6 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, { return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); } -/* - * Curl_multi_connchanged() is called to tell that there is a connection in - * this multi handle that has changed state (pipelining become possible, the - * number of allowed streams changed or similar), and a subsequent use of this - * multi handle should move CONNECT_PEND handles back to CONNECT to have them - * retry. - */ -void Curl_multi_connchanged(struct Curl_multi *multi) -{ - multi->recheckstate = TRUE; -} /* * multi_ischanged() is called @@ -1207,57 +1199,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, return rc; } -static CURLcode multi_reconnect_request(struct Curl_easy *data) -{ - CURLcode result = CURLE_OK; - struct connectdata *conn = data->conn; - - /* This was a re-use of a connection and we got a write error in the - * DO-phase. Then we DISCONNECT this connection and have another attempt to - * CONNECT and then DO again! The retry cannot possibly find another - * connection to re-use, since we only keep one possible connection for - * each. */ - - infof(data, "Re-used connection seems dead, get a new one\n"); - - connclose(conn, "Reconnect dead connection"); /* enforce close */ - result = multi_done(data, result, FALSE); /* we are so done with this */ - - /* data->conn was detached in multi_done() */ - - /* - * We need to check for CURLE_SEND_ERROR here as well. This could happen - * when the request failed on a FTP connection and thus multi_done() itself - * tried to use the connection (again). - */ - if(!result || (CURLE_SEND_ERROR == result)) { - bool async; - bool protocol_done = TRUE; - - /* Now, redo the connect and get a new connection */ - result = Curl_connect(data, &async, &protocol_done); - if(!result) { - /* We have connected or sent away a name resolve query fine */ - - conn = data->conn; /* in case it was updated */ - if(async) { - /* Now, if async is TRUE here, we need to wait for the name - to resolve */ - result = Curl_resolver_wait_resolv(conn, NULL); - if(result) - return result; - - /* Resolved, continue with the connection */ - result = Curl_once_resolved(conn, &protocol_done); - if(result) - return result; - } - } - } - - return result; -} - /* * do_complete is called when the DO actions are complete. * @@ -1267,8 +1208,6 @@ static CURLcode multi_reconnect_request(struct Curl_easy *data) static void do_complete(struct connectdata *conn) { conn->data->req.chunk = FALSE; - conn->data->req.maxfd = (conn->sockfd>conn->writesockfd? - conn->sockfd:conn->writesockfd) + 1; Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); } @@ -1281,27 +1220,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) /* generic protocol-specific function pointer set in curl_connect() */ result = conn->handler->do_it(conn, done); - /* This was formerly done in transfer.c, but we better do it here */ - if((CURLE_SEND_ERROR == result) && conn->bits.reuse) { - /* - * If the connection is using an easy handle, call reconnect - * to re-establish the connection. Otherwise, let the multi logic - * figure out how to re-establish the connection. - */ - if(!data->multi) { - result = multi_reconnect_request(data); - - if(!result) { - /* ... finally back to actually retry the DO phase */ - conn = data->conn; /* re-assign conn since multi_reconnect_request - creates a new connection */ - result = conn->handler->do_it(conn, done); - } - } - else - return result; - } - if(!result && *done) /* do_complete must be called after the protocol-specific DO function */ do_complete(conn); @@ -1549,7 +1467,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(result) /* if Curl_once_resolved() returns failure, the connection struct is already freed and gone */ - Curl_detach_connnection(data); /* no more connection */ + detach_connnection(data); /* no more connection */ else { /* call again please so that we get the next socket setup */ rc = CURLM_CALL_MULTI_PERFORM; @@ -1620,7 +1538,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } else if(result) { /* failure detected */ - /* Just break, the cleaning up is handled all in one place */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); stream_error = TRUE; break; } @@ -1933,13 +1852,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, k = &data->req; - if(!(k->keepon & KEEP_RECV)) + if(!(k->keepon & KEEP_RECV)) { /* We're done receiving */ Curl_pipeline_leave_read(data->conn); + } - if(!(k->keepon & KEEP_SEND)) + if(!(k->keepon & KEEP_SEND)) { /* We're done sending */ Curl_pipeline_leave_write(data->conn); + } if(done || (result == CURLE_RECV_ERROR)) { /* If CURLE_RECV_ERROR happens early enough, we assume it was a race @@ -2087,7 +2008,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * removed before we perform the processing in CURLM_STATE_COMPLETED */ if(data->conn) - Curl_detach_connnection(data); + detach_connnection(data); } if(data->state.wildcardmatch) { @@ -2145,7 +2066,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* This is where we make sure that the conn pointer is reset. We don't have to do this in every case block above where a failure is detected */ - Curl_detach_connnection(data); + detach_connnection(data); } } else if(data->mstate == CURLM_STATE_CONNECT) { @@ -2298,8 +2219,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_psl_destroy(&multi->psl); /* Free the blacklists by setting them to NULL */ - Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); - Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); + (void)Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); + (void)Curl_pipeline_set_server_blacklist(NULL, + &multi->pipelining_server_bl); free(multi); @@ -2360,8 +2282,6 @@ static CURLMcode singlesocket(struct Curl_multi *multi, int num; unsigned int curraction; int actions[MAX_SOCKSPEREASYHANDLE]; - unsigned int comboaction; - bool sincebefore = FALSE; for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) socks[i] = CURL_SOCKET_BAD; @@ -2380,6 +2300,8 @@ static CURLMcode singlesocket(struct Curl_multi *multi, i++) { unsigned int action = CURL_POLL_NONE; unsigned int prevaction = 0; + unsigned int comboaction; + bool sincebefore = FALSE; s = socks[i]; @@ -3028,9 +2950,6 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id) DEBUGASSERT(id < EXPIRE_LAST); - infof(data, "Expire in %ld ms for %x (transfer %p)\n", - (long)milli, id, data); - set = Curl_now(); set.tv_sec += milli/1000; set.tv_usec += (unsigned int)(milli%1000)*1000; diff --git a/libs/libcurl/src/non-ascii.c b/libs/libcurl/src/non-ascii.c index 14143248fb..42beaec45d 100644 --- a/libs/libcurl/src/non-ascii.c +++ b/libs/libcurl/src/non-ascii.c @@ -78,7 +78,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data, /* * Curl_convert_to_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. + * conversions on non-ASCII platforms. It converts the buffer _in place_. */ CURLcode Curl_convert_to_network(struct Curl_easy *data, char *buffer, size_t length) @@ -144,7 +144,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, /* * Curl_convert_from_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. + * conversions on non-ASCII platforms. It converts the buffer _in place_. */ CURLcode Curl_convert_from_network(struct Curl_easy *data, char *buffer, size_t length) diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c index bc007883e3..a98c50b460 100644 --- a/libs/libcurl/src/openldap.c +++ b/libs/libcurl/src/openldap.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, Howard Chu, - * Copyright (C) 2011 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -414,7 +414,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; lr->msgid = msgid; data->req.protop = lr; - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); *done = TRUE; return CURLE_OK; } diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index 4f65f289b4..8dbd448b2c 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -912,7 +912,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, if(pop3->transfer == FTPTRANSFER_BODY) { /* POP3 download */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); if(pp->cache) { /* The header "cache" contains a bunch of data that is actually body diff --git a/libs/libcurl/src/rand.h b/libs/libcurl/src/rand.h index c6fae35537..5deb041613 100644 --- a/libs/libcurl/src/rand.h +++ b/libs/libcurl/src/rand.h @@ -39,8 +39,11 @@ */ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); -/* Same as above but outputs only random lowercase hex characters. - Does NOT terminate.*/ +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, size_t num); diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c index 01dfce640c..b9a8ef5e86 100644 --- a/libs/libcurl/src/rtsp.c +++ b/libs/libcurl/src/rtsp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -80,8 +80,6 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, bool *readmore); static CURLcode rtsp_setup_connection(struct connectdata *conn); - -bool rtsp_connisdead(struct connectdata *check); static unsigned int rtsp_conncheck(struct connectdata *check, unsigned int checks_to_perform); @@ -147,7 +145,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn) * Instead, if it is readable, run Curl_connalive() to peek at the socket * and distinguish between closed and data. */ -bool rtsp_connisdead(struct connectdata *check) +static bool rtsp_connisdead(struct connectdata *check) { int sval; bool ret_val = TRUE; @@ -251,7 +249,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; Curl_RtspReq rtspreq = data->set.rtspreq; struct RTSP *rtsp = data->req.protop; - struct HTTP *http; Curl_send_buffer *req_buffer; curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ @@ -270,10 +267,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) *done = TRUE; - http = &(rtsp->http_wrapper); - /* Assert that no one has changed the RTSP struct in an evil way */ - DEBUGASSERT((void *)http == (void *)rtsp); - rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; rtsp->CSeq_recv = 0; @@ -330,8 +323,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } if(rtspreq == RTSPREQ_RECEIVE) { - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); return result; } @@ -599,17 +591,15 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - putsize?FIRSTSOCKET:-1, - putsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1); /* Increment the CSeq on success */ data->state.rtsp_next_client_CSeq++; - if(http->writebytecount) { + if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; } diff --git a/libs/libcurl/src/security.c b/libs/libcurl/src/security.c index 7f13071f6f..eec6e6f446 100644 --- a/libs/libcurl/src/security.c +++ b/libs/libcurl/src/security.c @@ -10,7 +10,7 @@ * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * - * Copyright (C) 2001 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 2001 - 2019, Daniel Stenberg, , et al. * * All rights reserved. * @@ -142,7 +142,7 @@ socket_read(curl_socket_t fd, void *to, size_t len) { char *to_p = to; CURLcode result; - ssize_t nread; + ssize_t nread = 0; while(len > 0) { result = Curl_read_plain(fd, to_p, len, &nread); diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index e8598e6173..5008d9333d 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -411,8 +411,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, *code = CURLE_AGAIN; } else { + char buffer[STRERROR_LEN]; failf(conn->data, "Send failure: %s", - Curl_strerror(conn, err)); + Curl_strerror(err, buffer, sizeof(buffer))); conn->data->state.os_errno = err; *code = CURLE_SEND_ERROR; } @@ -476,8 +477,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, *code = CURLE_AGAIN; } else { + char buffer[STRERROR_LEN]; failf(conn->data, "Recv failure: %s", - Curl_strerror(conn, err)); + Curl_strerror(err, buffer, sizeof(buffer))); conn->data->state.os_errno = err; *code = CURLE_RECV_ERROR; } diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index d98ca66c91..b5f74a93db 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -44,6 +44,7 @@ #include "http2.h" #include "setopt.h" #include "multiif.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -111,8 +112,8 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) #define C_SSLVERSION_VALUE(x) (x & 0xffff) #define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) -CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, - va_list param) +static CURLcode vsetopt(struct Curl_easy *data, CURLoption option, + va_list param) { char *argptr; CURLcode result = CURLE_OK; @@ -682,7 +683,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, * Set header option. */ arg = va_arg(param, long); - data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE; + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); break; case CURLOPT_HTTP200ALIASES: @@ -884,7 +885,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE; + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -967,7 +969,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE; + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -2076,13 +2079,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; case CURLOPT_PROXY_SSL_OPTIONS: arg = va_arg(param, long); - data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; @@ -2651,6 +2656,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, data->set.trailer_data = va_arg(param, void *); #endif break; +#ifdef USE_ALTSVC + case CURLOPT_ALTSVC: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); + result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); + if(result) + return result; + (void)Curl_altsvc_load(data->asi, argptr); + break; + case CURLOPT_ALTSVC_CTRL: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + arg = va_arg(param, long); + result = Curl_altsvc_ctrl(data->asi, arg); + if(result) + return result; + break; +#endif default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; @@ -2679,7 +2709,7 @@ CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) va_start(arg, tag); - result = Curl_vsetopt(data, tag, arg); + result = vsetopt(data, tag, arg); va_end(arg); return result; diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index d55647b12e..f3db714b5a 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -959,7 +959,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, Curl_pgrsSetUploadSize(data, data->state.infilesize); /* SMTP upload */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ state(conn, SMTP_STOP); @@ -1388,7 +1388,7 @@ static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) if(smtp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); return CURLE_OK; } diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index d2209ad899..d0aba0605a 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,7 +54,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ ssize_t buffersize, /* max amount to read */ ssize_t *n) /* amount bytes read */ { - ssize_t nread; + ssize_t nread = 0; ssize_t allread = 0; int result; *n = 0; diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c index bedb01ebbc..57027ef686 100644 --- a/libs/libcurl/src/socks_sspi.c +++ b/libs/libcurl/src/socks_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. * Copyright (C) 2009, 2011, Markus Moeller, * * This software is licensed as described in the file COPYING, which @@ -51,8 +51,9 @@ static int check_sspi_err(struct connectdata *conn, status != SEC_I_COMPLETE_AND_CONTINUE && status != SEC_I_COMPLETE_NEEDED && status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; failf(conn->data, "SSPI error: %s failed: %s", function, - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(status, buffer, sizeof(buffer))); return 1; } return 0; diff --git a/libs/libcurl/src/ssh-libssh.c b/libs/libcurl/src/ssh-libssh.c index 333df03ef2..609da1e09b 100644 --- a/libs/libcurl/src/ssh-libssh.c +++ b/libs/libcurl/src/ssh-libssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2017 - 2018 Red Hat, Inc. + * Copyright (C) 2017 - 2019 Red Hat, Inc. * * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, * Robert Kolcun, Andreas Schneider @@ -1200,7 +1200,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_pgrsSetUploadSize(data, data->state.infilesize); } /* upload data */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -1462,7 +1462,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->sftp_dir = NULL; /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); state(conn, SSH_STOP); break; @@ -1603,13 +1603,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* Setup the actual download */ if(data->req.size == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); state(conn, SSH_STOP); break; } - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -1731,8 +1730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) } /* upload data */ - Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, - FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -1775,8 +1773,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* download data */ bytecount = ssh_scp_request_get_size(sshc->scp_session); data->req.maxdownload = (curl_off_t) bytecount; - Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, - NULL); + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2398,13 +2395,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status, /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!status && !premature && conn->data->set.postquote && - !conn->bits.retry) { + if(!premature && conn->data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); - } - else - state(conn, SSH_SFTP_CLOSE); + state(conn, SSH_SFTP_CLOSE); } return myssh_done(conn, status); } diff --git a/libs/libcurl/src/ssh.c b/libs/libcurl/src/ssh.c index 8c68adcc17..46f52eceb0 100644 --- a/libs/libcurl/src/ssh.c +++ b/libs/libcurl/src/ssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,11 +81,11 @@ #include "multiif.h" #include "select.h" #include "warnless.h" +#include "curl_path.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" -#include "curl_path.h" #include "memdebug.h" #if LIBSSH2_VERSION_NUM >= 0x010206 @@ -1808,7 +1808,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_pgrsSetUploadSize(data, data->state.infilesize); } /* upload data */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -2105,7 +2105,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->readdir_longentry); /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); state(conn, SSH_STOP); break; @@ -2245,13 +2245,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* Setup the actual download */ if(data->req.size == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); state(conn, SSH_STOP); break; } - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2395,8 +2394,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } /* upload data */ - Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, - FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -2467,7 +2465,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* download data */ bytecount = (curl_off_t)sb.st_size; data->req.maxdownload = (curl_off_t)sb.st_size; - Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2791,9 +2789,12 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; bool block; /* we store the status and use that to provide a ssh_getsock() implementation */ - - result = ssh_statemach_act(conn, &block); - *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + do { + result = ssh_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 */ + } while(!result && !*done && !block); ssh_block2waitfor(conn, block); return result; @@ -3222,13 +3223,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status, /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!status && !premature && conn->data->set.postquote && - !conn->bits.retry) { + if(!premature && conn->data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); - } - else - state(conn, SSH_SFTP_CLOSE); + state(conn, SSH_SFTP_CLOSE); } return ssh_done(conn, status); } diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index bf30c89077..e273f3765c 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2004 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 2004 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -646,20 +646,18 @@ get_winsock_error (int err, char *buf, size_t len) * We don't do range checking (on systems other than Windows) since there is * no good reliable and portable way to do it. */ -const char *Curl_strerror(struct connectdata *conn, int err) +const char *Curl_strerror(int err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE DWORD old_win_err = GetLastError(); #endif int old_errno = errno; - char *buf, *p; + char *p; size_t max; - DEBUGASSERT(conn); DEBUGASSERT(err >= 0); - buf = conn->syserr_buf; - max = sizeof(conn->syserr_buf)-1; + max = buflen - 1; *buf = '\0'; #ifdef USE_WINSOCK @@ -757,7 +755,7 @@ const char *Curl_strerror(struct connectdata *conn, int err) } #ifdef USE_WINDOWS_SSPI -const char *Curl_sspi_strerror (struct connectdata *conn, int err) +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE DWORD old_win_err = GetLastError(); @@ -768,15 +766,13 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) size_t outmax; #ifndef CURL_DISABLE_VERBOSE_STRINGS char txtbuf[80]; - char msgbuf[sizeof(conn->syserr_buf)]; + char msgbuf[256]; char *p, *str, *msg = NULL; bool msg_formatted = FALSE; #endif - DEBUGASSERT(conn); - - outbuf = conn->syserr_buf; - outmax = sizeof(conn->syserr_buf)-1; + outbuf = buf; + outmax = buflen - 1; *outbuf = '\0'; #ifndef CURL_DISABLE_VERBOSE_STRINGS diff --git a/libs/libcurl/src/strerror.h b/libs/libcurl/src/strerror.h index 627273eb26..683b5b4a3a 100644 --- a/libs/libcurl/src/strerror.h +++ b/libs/libcurl/src/strerror.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,14 +24,11 @@ #include "urldata.h" -const char *Curl_strerror (struct connectdata *conn, int err); - -#ifdef USE_LIBIDN2 -const char *Curl_idn_strerror (struct connectdata *conn, int err); -#endif +#define STRERROR_LEN 128 /* a suitable length */ +const char *Curl_strerror(int err, char *buf, size_t buflen); #ifdef USE_WINDOWS_SSPI -const char *Curl_sspi_strerror (struct connectdata *conn, int err); +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); #endif #endif /* HEADER_CURL_STRERROR_H */ diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index 6b8004e5bb..f7f817dd45 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -26,12 +26,94 @@ #include #include "system_win32.h" +#include "curl_sspi.h" #include "warnless.h" /* The last #include files should be: */ #include "curl_memory.h" #include "memdebug.h" +LARGE_INTEGER Curl_freq; +bool Curl_isVistaOrGreater; + +/* Curl_win32_init() performs win32 global initialization */ +CURLcode Curl_win32_init(long flags) +{ + /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which + is just for Winsock at the moment. Any required win32 initialization + should take place after this block. */ + if(flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WORD wVersionRequested; + WSADATA wsaData; + int res; + +#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) +#error IPV6_requires_winsock2 +#endif + + wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); + + res = WSAStartup(wVersionRequested, &wsaData); + + if(res != 0) + /* Tell the user that we couldn't find a usable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a usable */ + + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; + } + /* The Windows Sockets DLL is acceptable. Proceed. */ + #elif defined(USE_LWIPSOCK) + lwip_init(); + #endif + } /* CURL_GLOBAL_WIN32 */ + +#ifdef USE_WINDOWS_SSPI + { + CURLcode result = Curl_sspi_global_init(); + if(result) + return result; + } +#endif + + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + Curl_isVistaOrGreater = TRUE; + QueryPerformanceFrequency(&Curl_freq); + } + else + Curl_isVistaOrGreater = FALSE; + + return CURLE_OK; +} + +/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ +void Curl_win32_cleanup(long init_flags) +{ +#ifdef USE_WINDOWS_SSPI + Curl_sspi_global_cleanup(); +#endif + + if(init_flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WSACleanup(); +#endif + } +} + #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ defined(USE_WINSOCK)) diff --git a/libs/libcurl/src/system_win32.h b/libs/libcurl/src/system_win32.h index 1e772856b2..926328a9aa 100644 --- a/libs/libcurl/src/system_win32.h +++ b/libs/libcurl/src/system_win32.h @@ -26,6 +26,12 @@ #if defined(WIN32) +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +CURLcode Curl_win32_init(long flags); +void Curl_win32_cleanup(long init_flags); + /* Version condition */ typedef enum { VERSION_LESS_THAN, diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c index e4c0bac3dc..955255c36c 100644 --- a/libs/libcurl/src/telnet.c +++ b/libs/libcurl/src/telnet.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1692,7 +1692,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } #endif /* mark this as "no further transfer wanted" */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); return result; } diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index 269b3cde4b..8b92b7bd68 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -540,7 +540,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) state->conn->ip_addr->ai_addr, state->conn->ip_addr->ai_addrlen); if(senddata != (ssize_t)sbytes) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); } free(filename); break; @@ -590,6 +591,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ssize_t sbytes; int rblock; struct Curl_easy *data = state->conn->data; + char buffer[STRERROR_LEN]; switch(event) { @@ -622,7 +624,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } @@ -647,7 +649,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } @@ -673,7 +675,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } } @@ -713,6 +715,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) CURLcode result = CURLE_OK; struct SingleRequest *k = &data->req; size_t cb; /* Bytes currently read */ + char buffer[STRERROR_LEN]; switch(event) { @@ -747,7 +750,8 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, + buffer, sizeof(buffer))); result = CURLE_SEND_ERROR; } } @@ -791,7 +795,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } /* Update the progress meter */ @@ -817,7 +821,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } /* since this was a re-send, we remain at the still byte position */ @@ -1030,8 +1034,9 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, conn->ip_addr->ai_addrlen); if(rc) { + char buffer[STRERROR_LEN]; failf(conn->data, "bind() failed; %s", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_COULDNT_CONNECT; } conn->bits.bound = TRUE; @@ -1242,7 +1247,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } else { /* no timeouts to handle, check our socket */ @@ -1251,7 +1256,8 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) if(rc == -1) { /* bail out */ int error = SOCKERRNO; - failf(data, "%s", Curl_strerror(conn, error)); + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); state->event = TFTP_EVENT_ERROR; } else if(rc != 0) { @@ -1264,7 +1270,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } /* if rc == 0, then select() timed out */ } diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/timeval.c index 2569f175c3..ff8d8a69af 100644 --- a/libs/libcurl/src/timeval.c +++ b/libs/libcurl/src/timeval.c @@ -21,30 +21,22 @@ ***************************************************************************/ #include "timeval.h" -#include "system_win32.h" #if defined(WIN32) && !defined(MSDOS) +/* set in win32_init() */ +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + struct curltime Curl_now(void) { struct curltime now; - static LARGE_INTEGER freq; - static int isVistaOrGreater = -1; - if(isVistaOrGreater == -1) { - if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) { - isVistaOrGreater = 1; - QueryPerformanceFrequency(&freq); - } - else - isVistaOrGreater = 0; - } - if(isVistaOrGreater == 1) { /* QPC timer might have issues pre-Vista */ + if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ LARGE_INTEGER count; QueryPerformanceCounter(&count); - now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart); - now.tv_usec = - (int)((count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart); + now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart); + now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 / + Curl_freq.QuadPart); } else { /* Disable /analyze warning that GetTickCount64 is preferred */ diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index 3a18c7bdd0..ca6031724b 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -296,10 +296,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, here, knowing they'll become CRLFs later on. */ - char hexbuffer[11]; + char hexbuffer[11] = ""; + int hexlen = 0; const char *endofline_native; const char *endofline_network; - int hexlen = 0; if( #ifdef CURL_DO_LINEEND_CONV @@ -354,12 +354,14 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, length = nread; else /* just translate the protocol portion */ - length = strlen(hexbuffer); - result = Curl_convert_to_network(data, data->req.upload_fromhere, - length); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(result) - return result; + length = hexlen; + if(length) { + result = Curl_convert_to_network(data, data->req.upload_fromhere, + length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } } #endif /* CURL_DOES_CONVERSIONS */ @@ -1196,6 +1198,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, (size_t)bytes_written); k->writebytecount += bytes_written; + Curl_pgrsSetUploadCounter(data, k->writebytecount); if((!k->upload_chunky || k->forbidchunk) && (k->writebytecount == data->state.infilesize)) { @@ -1229,7 +1232,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data, } } - Curl_pgrsSetUploadCounter(data, k->writebytecount); } WHILE_FALSE; /* just to break out from! */ @@ -1307,11 +1309,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, k->now = Curl_now(); if(didwhat) { - /* Update read/write counters */ - if(k->bytecountp) - *k->bytecountp = k->bytecount; /* read count */ - if(k->writebytecountp) - *k->writebytecountp = k->writebytecount; /* write count */ + ; } else { /* no read no write, this is a timeout? */ @@ -1526,11 +1524,14 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(data->set.httpreq == HTTPREQ_PUT) data->state.infilesize = data->set.filesize; - else { + else if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { data->state.infilesize = data->set.postfieldsize; if(data->set.postfields && (data->state.infilesize == -1)) data->state.infilesize = (curl_off_t)strlen(data->set.postfields); } + else + data->state.infilesize = 0; /* If there is a list of cookie files to read, do it now! */ if(data->change.cookielist) @@ -1852,8 +1853,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, if(conn->handler->protocol&PROTO_FAMILY_HTTP) { - struct HTTP *http = data->req.protop; - if(http->writebytecount) { + if(data->req.writebytecount) { CURLcode result = Curl_readrewind(conn); if(result) { Curl_safefree(*url); @@ -1871,24 +1871,17 @@ CURLcode Curl_retry_request(struct connectdata *conn, */ void Curl_setup_transfer( - struct connectdata *conn, /* connection data */ + struct Curl_easy *data, /* transfer */ int sockindex, /* socket index to read from or -1 */ curl_off_t size, /* -1 if unknown at this point */ bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read or NULL */ - int writesockindex, /* socket index to write to, it may very well be + int writesockindex /* socket index to write to, it may very well be the same we read from. -1 disables */ - curl_off_t *writecountp /* return number of bytes written or NULL */ ) { - struct Curl_easy *data; - struct SingleRequest *k; - + struct SingleRequest *k = &data->req; + struct connectdata *conn = data->conn; DEBUGASSERT(conn != NULL); - - data = conn->data; - k = &data->req; - DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); if(conn->bits.multiplex || conn->httpversion == 20) { @@ -1907,8 +1900,6 @@ Curl_setup_transfer( k->getheader = getheader; k->size = size; - k->bytecountp = bytecountp; - k->writebytecountp = writecountp; /* The code sequence below is placed in this function just because all necessary input is not always known in do_complete() as this function may diff --git a/libs/libcurl/src/transfer.h b/libs/libcurl/src/transfer.h index 9742455ae8..a9bff63486 100644 --- a/libs/libcurl/src/transfer.h +++ b/libs/libcurl/src/transfer.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,15 +59,13 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data); /* This sets up a forthcoming transfer */ void -Curl_setup_transfer (struct connectdata *data, - int sockindex, /* socket index to read from or -1 */ - curl_off_t size, /* -1 if unknown at this point */ - bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read */ - int writesockindex, /* socket index to write to, it may - very well be the same we read from. - -1 disables */ - curl_off_t *writecountp /* return number of bytes written */ -); +Curl_setup_transfer (struct Curl_easy *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to. May be + the same we read from. -1 + disables */ + ); #endif /* HEADER_CURL_TRANSFER_H */ diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index d5a982008e..eb09a24be2 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -120,6 +120,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "dotdot.h" #include "strdup.h" #include "setopt.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -292,7 +293,7 @@ void Curl_freeset(struct Curl_easy *data) } /* free the URL pieces */ -void Curl_up_free(struct Curl_easy *data) +static void up_free(struct Curl_easy *data) { struct urlpieces *up = &data->state.up; Curl_safefree(up->scheme); @@ -303,7 +304,8 @@ void Curl_up_free(struct Curl_easy *data) Curl_safefree(up->options); Curl_safefree(up->path); Curl_safefree(up->query); - curl_url_cleanup(data->state.uh); + if(data->set.uh != data->state.uh) + curl_url_cleanup(data->state.uh); data->state.uh = NULL; } @@ -369,11 +371,16 @@ CURLcode Curl_close(struct Curl_easy *data) } data->change.referer = NULL; - Curl_up_free(data); + up_free(data); Curl_safefree(data->state.buffer); Curl_safefree(data->state.headerbuff); Curl_safefree(data->state.ulbuf); Curl_flush_cookies(data, 1); +#ifdef USE_ALTSVC + Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_cleanup(data->asi); + data->asi = NULL; +#endif Curl_digest_cleanup(data); Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); @@ -660,11 +667,15 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ -static void conn_free(struct connectdata *conn) + +static void conn_shutdown(struct connectdata *conn) { if(!conn) return; + infof(conn->data, "Closing connection %ld\n", conn->connection_id); + DEBUGASSERT(conn->data); + /* possible left-overs from the async name resolvers */ Curl_resolver_cancel(conn); @@ -688,6 +699,21 @@ static void conn_free(struct connectdata *conn) Curl_ntlm_wb_cleanup(conn); #endif + /* unlink ourselves. this should be called last since other shutdown + procedures need a valid conn->data and this may clear it. */ + Curl_conncache_remove_conn(conn->data, conn, TRUE); +} + +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_safefree(conn->user); Curl_safefree(conn->passwd); Curl_safefree(conn->oauth_bearer); @@ -780,27 +806,20 @@ CURLcode Curl_disconnect(struct Curl_easy *data, /* Cleanup NTLM connection-related data */ Curl_http_ntlm_cleanup(conn); #endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + /* Cleanup NEGOTIATE connection-related data */ + Curl_cleanup_negotiate(conn); +#endif - /* the protocol specific disconnect handler needs a transfer for its - connection! */ + /* the protocol specific disconnect handler and conn_shutdown need a transfer + for the connection! */ conn->data = data; + if(conn->handler->disconnect) /* This is set if protocol-specific cleanups should be made */ conn->handler->disconnect(conn, dead_connection); - /* unlink ourselves! */ - infof(data, "Closing connection %ld\n", conn->connection_id); - Curl_conncache_remove_conn(data, conn, TRUE); - - 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); - - /* this assumes that the pointer is still there after the connection was - detected from the cache */ - Curl_ssl_close(conn, FIRSTSOCKET); - + conn_shutdown(conn); conn_free(conn); return CURLE_OK; } @@ -956,7 +975,7 @@ static bool extract_if_dead(struct connectdata *conn, struct Curl_easy *data) { size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size; - if(!pipeLen && !CONN_INUSE(conn)) { + if(!pipeLen && !CONN_INUSE(conn) && !conn->data) { /* The check for a dead socket makes sense only if there are no handles in pipeline and the connection isn't already marked in use */ @@ -965,7 +984,10 @@ static bool extract_if_dead(struct connectdata *conn, /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ unsigned int state; + struct Curl_easy *olddata = conn->data; + conn->data = data; /* use this transfer for now */ state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); + conn->data = olddata; dead = (state & CONNRESULT_DEAD); } else { @@ -994,7 +1016,6 @@ struct prunedead { static int call_extract_if_dead(struct connectdata *conn, void *param) { struct prunedead *p = (struct prunedead *)param; - conn->data = p->data; /* transfer to use for this check */ if(extract_if_dead(conn, p->data)) { /* stop the iteration here, pass back the connection that was extracted */ p->extracted = conn; @@ -1132,6 +1153,10 @@ ConnectionExists(struct Curl_easy *data, check = curr->ptr; curr = curr->next; + if(check->bits.connect_only) + /* connect-only connections will not be reused */ + continue; + if(extract_if_dead(check, data)) { /* disconnect it */ (void)Curl_disconnect(data, check, /* dead_connection */TRUE); @@ -1262,14 +1287,15 @@ ConnectionExists(struct Curl_easy *data, } } - if(!canpipe && CONN_INUSE(check)) + if(!canpipe && check->data) /* this request can't be pipelined but the checked connection is already in use so we skip it */ continue; - if(CONN_INUSE(check) && (check->data->multi != needle->data->multi)) - /* this could be subject for pipeline/multiplex use, but only - if they belong to the same multi handle */ + if(CONN_INUSE(check) && check->data && + (check->data->multi != needle->data->multi)) + /* this could be subject for pipeline/multiplex use, but only if they + belong to the same multi handle */ continue; if(needle->localdev || needle->localport) { @@ -1685,6 +1711,8 @@ static bool is_ASCII_name(const char *hostname) static void strip_trailing_dot(struct hostname *host) { size_t len; + if(!host || !host->name) + return; len = strlen(host->name); if(len && (host->name[len-1] == '.')) host->name[len-1] = 0; @@ -1749,15 +1777,6 @@ static CURLcode idnconvert_hostname(struct connectdata *conn, infof(data, "IDN support not present, can't parse Unicode domains\n"); #endif } - { - char *hostp; - for(hostp = host->name; *hostp; hostp++) { - if(*hostp <= 32) { - failf(data, "Host name '%s' contains bad letter", host->name); - return CURLE_URL_MALFORMAT; - } - } - } return CURLE_OK; } @@ -1899,8 +1918,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) data->set.proxy_ssl.primary.verifystatus; conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; - conn->ip_version = data->set.ipver; + conn->bits.connect_only = data->set.connect_only; #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ defined(NTLM_WB_ENABLED) @@ -2029,11 +2048,11 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, CURLUcode uc; char *hostname; - Curl_up_free(data); /* cleanup previous leftovers first */ + up_free(data); /* cleanup previous leftovers first */ /* parse the URL */ if(data->set.uh) { - uh = data->set.uh; + uh = data->state.uh = data->set.uh; } else { uh = data->state.uh = curl_url(); @@ -3361,6 +3380,34 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, conn_to_host = conn_to_host->next; } +#ifdef USE_ALTSVC + if(data->asi && !host && (port == -1) && + (conn->handler->protocol == CURLPROTO_HTTPS)) { + /* no connect_to match, try alt-svc! */ + const char *nhost; + int nport; + enum alpnid nalpnid; + bool hit; + host = conn->host.rawalloc; + hit = Curl_altsvc_lookup(data->asi, + ALPN_h1, host, conn->remote_port, /* from */ + &nalpnid, &nhost, &nport /* to */); + if(hit) { + char *hostd = strdup((char *)nhost); + if(!hostd) + return CURLE_OUT_OF_MEMORY; + conn->conn_to_host.rawalloc = hostd; + conn->conn_to_host.name = hostd; + conn->bits.conn_to_host = TRUE; + conn->conn_to_port = nport; + conn->bits.conn_to_port = TRUE; + infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n", + Curl_alpnid2str(ALPN_h1), host, conn->remote_port, + Curl_alpnid2str(nalpnid), hostd, nport); + } + } +#endif + return result; } @@ -3374,6 +3421,8 @@ static CURLcode resolve_server(struct Curl_easy *data, CURLcode result = CURLE_OK; timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + DEBUGASSERT(conn); + DEBUGASSERT(data); /************************************************************* * Resolve the name of the server or proxy *************************************************************/ @@ -3789,9 +3838,8 @@ static CURLcode create_conn(struct Curl_easy *data, (void)conn->handler->done(conn, result, FALSE); goto out; } - - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - -1, NULL); /* no upload */ + Curl_attach_connnection(data, conn); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } /* since we skip do_init() */ @@ -3877,8 +3925,9 @@ static CURLcode create_conn(struct Curl_easy *data, /* reuse_fresh is TRUE if we are told to use a new connection by force, but we only acknowledge this option if this is not a re-used connection already (which happens due to follow-location or during a HTTP - authentication phase). */ - if(data->set.reuse_fresh && !data->state.this_is_a_follow) + authentication phase). CONNECT_ONLY transfers also refuse reuse. */ + if((data->set.reuse_fresh && !data->state.this_is_a_follow) || + data->set.connect_only) reuse = FALSE; else reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe); @@ -4170,7 +4219,8 @@ CURLcode Curl_connect(struct Curl_easy *data, connectdata struct, free those here */ Curl_disconnect(data, conn, TRUE); } - else + else if(!data->conn) + /* FILE: transfers already have the connection attached */ Curl_attach_connnection(data, conn); return result; diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index 3af8e9399f..a19867eb0f 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -67,12 +67,6 @@ struct Curl_URL { #define DEFAULT_SCHEME "https" -#ifdef DEBUGBUILD -#define UNITTEST -#else -#define UNITTEST static -#endif - static void free_urlhandle(struct Curl_URL *u) { free(u->scheme); @@ -141,7 +135,7 @@ static bool urlchar_needs_escaping(int c) * URL encoding should be skipped for host names, otherwise IDN resolution * will fail. */ -size_t Curl_strlen_url(const char *url, bool relative) +static size_t strlen_url(const char *url, bool relative) { const unsigned char *ptr; size_t newlen = 0; @@ -183,7 +177,7 @@ size_t Curl_strlen_url(const char *url, bool relative) * URL encoding should be skipped for host names, otherwise IDN resolution * will fail. */ -void Curl_strcpy_url(char *output, const char *url, bool relative) +static void strcpy_url(char *output, const char *url, bool relative) { /* we must add this with whitespace-replacing */ bool left = TRUE; @@ -268,7 +262,7 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen) * The returned pointer must be freed by the caller unless NULL * (returns NULL on out of memory). */ -char *Curl_concat_url(const char *base, const char *relurl) +static char *concat_url(const char *base, const char *relurl) { /*** TRY to append this new path to the old URL @@ -392,7 +386,7 @@ char *Curl_concat_url(const char *base, const char *relurl) letter we replace each space with %20 while it is replaced with '+' on the right side of the '?' letter. */ - newlen = Curl_strlen_url(useurl, !host_changed); + newlen = strlen_url(useurl, !host_changed); urllen = strlen(url_clone); @@ -414,7 +408,7 @@ char *Curl_concat_url(const char *base, const char *relurl) newest[urllen++]='/'; /* then append the new piece on the right side */ - Curl_strcpy_url(&newest[urllen], useurl, !host_changed); + strcpy_url(&newest[urllen], useurl, !host_changed); free(url_clone); @@ -574,15 +568,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname) /* scan for byte values < 31 or 127 */ static CURLUcode junkscan(char *part) { - char badbytes[]={ - /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x7f, - 0x00 /* zero terminate */ - }; if(part) { + static const char badbytes[]={ + /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x7f, + 0x00 /* zero terminate */ + }; size_t n = strlen(part); size_t nfine = strcspn(part, badbytes); if(nfine != n) @@ -1083,10 +1077,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, return CURLUE_OUT_OF_MEMORY; *part = url; return CURLUE_OK; - break; } default: ptr = NULL; + break; } if(ptr) { *part = strdup(ptr); @@ -1252,7 +1246,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } /* apply the relative part to create a new URL */ - redired_url = Curl_concat_url(oldurl, part); + redired_url = concat_url(oldurl, part); free(oldurl); if(!redired_url) return CURLUE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index ff3cc9a655..24187a4c48 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -129,12 +129,14 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #ifdef HAVE_GSSAPI # ifdef HAVE_GSSGNU # include -# elif defined HAVE_GSSMIT +# elif defined HAVE_GSSAPI_GSSAPI_H # include -# include # else # include # endif +# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +# include +# endif #endif #ifdef HAVE_LIBSSH2_H @@ -154,13 +156,16 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #define GOOD_EASY_HANDLE(x) \ ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) +/* the type we use for storing a single boolean bit */ +typedef unsigned int bit; + #ifdef HAVE_GSSAPI /* Types needed for krb5-ftp connections */ struct krb5buffer { void *data; size_t size; size_t index; - int eof_flag; + bit eof_flag:1; }; enum protection_level { @@ -198,21 +203,17 @@ struct ssl_connect_data { /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm but at least asked to or meaning to use it. See 'state' for the exact current state of the connection. */ - bool use; ssl_connection_state state; ssl_connect_state connecting_state; #if defined(USE_SSL) struct ssl_backend_data *backend; #endif + bit use:1; }; struct ssl_primary_config { long version; /* what version the client wants to use */ long version_max; /* max supported version the client wants to use*/ - bool verifypeer; /* set TRUE if this is desired */ - bool verifyhost; /* set TRUE if CN/SAN must match hostname */ - bool verifystatus; /* set TRUE if certificate status must be checked */ - bool sessionid; /* cache session IDs or not */ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ char *clientcert; @@ -220,32 +221,33 @@ struct ssl_primary_config { char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + bit verifypeer:1; /* set TRUE if this is desired */ + bit verifyhost:1; /* set TRUE if CN/SAN must match hostname */ + bit verifystatus:1; /* set TRUE if certificate status must be checked */ + bit sessionid:1; /* cache session IDs or not */ }; struct ssl_config_data { struct ssl_primary_config primary; - bool enable_beast; /* especially allow this flaw for interoperability's - sake*/ - bool no_revoke; /* disable SSL certificate revocation checks */ long certverifyresult; /* result from the certificate verification */ char *CRLfile; /* CRL to check certificate revocation */ char *issuercert;/* optional issuer certificate filename */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ - bool certinfo; /* gather lots of certificate info */ - bool falsestart; - char *cert; /* client certificate file name */ char *cert_type; /* format for certificate (default: PEM)*/ char *key; /* private key file name */ char *key_type; /* format for private key (default: PEM) */ char *key_passwd; /* plain text private key password */ - #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ char *password; /* TLS password (for, e.g., SRP) */ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ #endif + bit certinfo:1; /* gather lots of certificate info */ + bit falsestart:1; + bit enable_beast:1; /* allow this flaw for interoperability's sake*/ + bit no_revoke:1; /* disable SSL certificate revocation checks */ }; struct ssl_general_config { @@ -284,12 +286,12 @@ struct digestdata { char *cnonce; char *realm; int algo; - bool stale; /* set true for re-negotiation */ char *opaque; char *qop; char *algorithm; int nc; /* nounce count */ - bool userhash; + bit stale:1; /* set true for re-negotiation */ + bit userhash:1; #endif }; @@ -356,7 +358,9 @@ struct ntlmdata { struct negotiatedata { /* When doing Negotiate (SPNEGO) auth, we first need to send a token and then validate the received one. */ - enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state; + enum { + GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT, GSS_AUTHDONE, GSS_AUTHSUCC + } state; #ifdef HAVE_GSSAPI OM_uint32 status; gss_ctx_id_t context; @@ -378,6 +382,10 @@ struct negotiatedata { size_t output_token_length; #endif #endif + bool noauthpersist; + bool havenoauthpersist; + bool havenegdata; + bool havemultiplerequests; }; #endif @@ -387,69 +395,65 @@ struct negotiatedata { */ struct ConnectBits { /* always modify bits.close with the connclose() and connkeep() macros! */ - bool close; /* if set, we close the connection after this request */ - bool reuse; /* if set, this is a re-used connection */ - bool conn_to_host; /* if set, this connection has a "connect to host" - that overrides the host in the URL */ - bool conn_to_port; /* if set, this connection has a "connect to port" - that overrides the port in the URL (remote port) */ - bool proxy; /* if set, this transfer is done through a proxy - any type */ - bool httpproxy; /* if set, this transfer is done through a http proxy */ - bool socksproxy; /* if set, this transfer is done through a socks proxy */ - bool user_passwd; /* do we use user+password for this connection? */ - bool proxy_user_passwd; /* user+password for the proxy? */ - bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 - IP address */ - bool ipv6; /* we communicate with a site using an IPv6 address */ - - bool do_more; /* this is set TRUE if the ->curl_do_more() function is - supposed to be called, after ->curl_do() */ - bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set - the first time on the first connect function call */ - bool protoconnstart;/* the protocol layer has STARTED its operation after - the TCP layer connect */ - - bool retry; /* this connection is about to get closed and then - re-attempted at another connection. */ - bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy. - This is implicit when SSL-protocols are used through - proxies, but can also be enabled explicitly by - apps */ - bool authneg; /* TRUE when the auth phase has started, which means - that we are creating a request with an auth header, - but it is not the final request in the auth - negotiation. */ - bool rewindaftersend;/* TRUE when the sending couldn't be stopped even - though it will be discarded. When the whole send - operation is done, we must call the data rewind - callback. */ - bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out - EPSV doesn't work we disable it for the forthcoming - requests */ - - bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out - EPRT doesn't work we disable it for the forthcoming - requests */ - bool ftp_use_data_ssl; /* Enabled SSL for the data connection */ - bool netrc; /* name+password provided by netrc */ - bool userpwd_in_url; /* name+password found in url */ - bool stream_was_rewound; /* Indicates that the stream was rewound after a - request read past the end of its response byte - boundary */ - bool proxy_connect_closed; /* set true if a proxy disconnected the - connection in a CONNECT request with auth, so - that libcurl should reconnect and continue. */ - bool bound; /* set true if bind() has already been done on this socket/ - connection */ - bool type_set; /* type= was used in the URL */ - bool multiplex; /* connection is multiplexed */ - - bool tcp_fastopen; /* use TCP Fast Open */ - bool tls_enable_npn; /* TLS NPN extension? */ - bool tls_enable_alpn; /* TLS ALPN extension? */ bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy is complete */ - bool socksproxy_connecting; /* connecting through a socks proxy */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bit close:1; /* if set, we close the connection after this request */ + bit reuse:1; /* if set, this is a re-used connection */ + bit conn_to_host:1; /* if set, this connection has a "connect to host" + that overrides the host in the URL */ + bit conn_to_port:1; /* if set, this connection has a "connect to port" + that overrides the port in the URL (remote port) */ + bit proxy:1; /* if set, this transfer is done through a proxy - any type */ + bit httpproxy:1; /* if set, this transfer is done through a http proxy */ + bit socksproxy:1; /* if set, this transfer is done through a socks proxy */ + bit user_passwd:1; /* do we use user+password for this connection? */ + bit proxy_user_passwd:1; /* user+password for the proxy? */ + bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bit ipv6:1; /* we communicate with a site using an IPv6 address */ + bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bit protoconnstart:1;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + bit retry:1; /* this connection is about to get closed and then + re-attempted at another connection. */ + bit tunnel_proxy:1; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bit authneg:1; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ + bit ftp_use_epsv:1; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_eprt:1; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */ + bit netrc:1; /* name+password provided by netrc */ + bit userpwd_in_url:1; /* name+password found in url */ + bit stream_was_rewound:1; /* The stream was rewound after a request read + past the end of its response byte boundary */ + bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection + in a CONNECT request with auth, so that + libcurl should reconnect and continue. */ + bit bound:1; /* set true if bind() has already been done on this socket/ + connection */ + bit type_set:1; /* type= was used in the URL */ + bit multiplex:1; /* connection is multiplexed */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit tls_enable_npn:1; /* TLS NPN extension? */ + bit tls_enable_alpn:1; /* TLS ALPN extension? */ + bit socksproxy_connecting:1; /* connecting through a socks proxy */ + bit connect_only:1; }; struct hostname { @@ -476,14 +480,13 @@ struct hostname { #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) - struct Curl_async { char *hostname; int port; struct Curl_dns_entry *dns; - bool done; /* set TRUE when the lookup is complete */ int status; /* if done is TRUE, this is the status from the callback */ void *os_specific; /* 'struct thread_data' for Windows */ + bit done:1; /* set TRUE when the lookup is complete */ }; #define FIRSTSOCKET 0 @@ -541,25 +544,21 @@ struct dohdata { */ struct SingleRequest { curl_off_t size; /* -1 if unknown at this point */ - curl_off_t *bytecountp; /* return number of bytes read or NULL */ - curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, -1 means unlimited */ - curl_off_t *writebytecountp; /* return number of bytes written or NULL */ - curl_off_t bytecount; /* total number of bytes read */ curl_off_t writebytecount; /* number of bytes written */ - long headerbytecount; /* only count received headers */ - long deductheadercount; /* this amount of bytes doesn't count when we check - if anything has been transferred at the end of a - connection. We use this counter to make only a - 100 reply (without a following second response - code) result in a CURLE_GOT_NOTHING error code */ + curl_off_t headerbytecount; /* only count received headers */ + curl_off_t deductheadercount; /* this amount of bytes doesn't count when we + check if anything has been transferred at + the end of a connection. We use this + counter to make only a 100 reply (without a + following second response code) result in a + CURLE_GOT_NOTHING error code */ struct curltime start; /* transfer started at this time */ struct curltime now; /* current time */ - bool header; /* incoming data has HTTP header */ enum { HEADER_NORMAL, /* no bad header at all */ HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest @@ -575,7 +574,6 @@ struct SingleRequest { char *str_start; /* within buf */ char *end_ptr; /* within buf */ char *p; /* within headerbuff */ - bool content_range; /* set TRUE if Content-Range: was found */ curl_off_t offset; /* possible resume offset read from the Content-Range: header */ int httpcode; /* error code from the 'HTTP/1.? XXX' or @@ -588,19 +586,8 @@ struct SingleRequest { /* See sec 3.5, RFC2616. */ time_t timeofdoc; long bodywrites; - char *buf; - curl_socket_t maxfd; - int keepon; - - bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload - and we're uploading the last chunk */ - - bool ignorebody; /* we read a response-body but we ignore it! */ - bool ignorecl; /* This HTTP response has no body so we ignore the Content- - Length: header */ - char *location; /* This points to an allocated version of the Location: header data */ char *newurl; /* Set to the new URL to use when a redirect or a retry is @@ -610,24 +597,28 @@ struct SingleRequest { still left in the buffer, aimed for upload. */ ssize_t upload_present; - /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a - buffer, so the next read should read from where this pointer points to, - and the 'upload_present' contains the number of bytes available at this - position */ + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ char *upload_fromhere; - - bool chunk; /* if set, this is a chunked transfer-encoding */ - bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding - on upload */ - bool getheader; /* TRUE if header parsing is wanted */ - - bool forbidchunk; /* used only to explicitly forbid chunk-upload for - specific upload buffers. See readmoredata() in - http.c for details. */ - void *protop; /* Allocated protocol-specific data. Each protocol handler makes sure this points to data it needs. */ struct dohdata doh; /* DoH specific data for this request */ + bit header:1; /* incoming data has HTTP header */ + bit content_range:1; /* set TRUE if Content-Range: was found */ + bit upload_done:1; /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + bit ignorebody:1; /* we read a response-body but we ignore it! */ + bit ignorecl:1; /* This HTTP response has no body so we ignore the + Content-Length: header */ + bit chunk:1; /* if set, this is a chunked transfer-encoding */ + bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bit getheader:1; /* TRUE if header parsing is wanted */ + bit forbidchunk:1; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in http.c + for details. */ }; /* @@ -775,13 +766,13 @@ struct http_connect_state { char *line_start; char *ptr; /* where to store more data */ curl_off_t cl; /* size of content to read and ignore */ - bool chunked_encoding; enum { TUNNEL_INIT, /* init/default/no tunnel state */ TUNNEL_CONNECT, /* CONNECT has been sent off */ TUNNEL_COMPLETE /* CONNECT response received completely */ } tunnel_state; - bool close_connection; + bit chunked_encoding:1; + bit close_connection:1; }; /* @@ -898,8 +889,6 @@ struct connectdata { #endif struct ssl_primary_config ssl_config; struct ssl_primary_config proxy_ssl_config; - bool tls_upgraded; - struct ConnectBits bits; /* various state-flags for this connection */ /* connecttime: when connect() is called on the current IP address. Used to @@ -946,7 +935,7 @@ struct connectdata { } allocptr; #ifdef HAVE_GSSAPI - int sec_complete; /* if Kerberos is enabled for this connection */ + bit sec_complete:1; /* if Kerberos is enabled for this connection */ enum protection_level command_prot; enum protection_level data_prot; enum protection_level request_data_prot; @@ -961,14 +950,6 @@ struct connectdata { struct kerberos5data krb5; /* variables into the structure definition, */ #endif /* however, some of them are ftp specific. */ - /* the two following *_inuse fields are only flags, not counters in any way. - If TRUE it means the channel is in use, and if FALSE it means the channel - is up for grabs by one. */ - - bool readchannel_inuse; /* whether the read channel is in use by an easy - handle */ - bool writechannel_inuse; /* whether the write channel is in use by an easy - handle */ struct curl_llist send_pipe; /* List of handles waiting to send on this pipeline */ struct curl_llist recv_pipe; /* List of handles waiting to read their @@ -1002,7 +983,11 @@ struct connectdata { #endif #endif - char syserr_buf [256]; /* buffer for Curl_strerror() */ +#ifdef USE_SPNEGO + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + /* data used for the asynch name resolve callback */ struct Curl_async async; @@ -1045,8 +1030,16 @@ struct connectdata { #ifdef USE_UNIX_SOCKETS char *unix_domain_socket; - bool abstract_unix_socket; + bit abstract_unix_socket:1; #endif + bit tls_upgraded:1; + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + bit readchannel_inuse:1; /* whether the read channel is in use by an easy + handle */ + bit writechannel_inuse:1; /* whether the write channel is in use by an easy + handle */ }; /* The end of connectdata. */ @@ -1061,10 +1054,8 @@ struct PureInfo { int httpversion; /* the http version number X.Y = X*10+Y */ time_t filetime; /* If requested, this is might get set. Set to -1 if the time was unretrievable. */ - bool timecond; /* set to TRUE if the time condition didn't match, which - thus made the document NOT get fetched */ - long header_size; /* size of read header(s) in bytes */ - long request_size; /* the amount of bytes sent in the request(s) */ + curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ unsigned long proxyauthavail; /* what proxy auth types were announced */ unsigned long httpauthavail; /* what host auth types were announced */ long numconnects; /* how many new connection did libcurl created */ @@ -1081,16 +1072,16 @@ struct PureInfo { char conn_primary_ip[MAX_IPADR_LEN]; long conn_primary_port; - char conn_local_ip[MAX_IPADR_LEN]; long conn_local_port; - const char *conn_scheme; unsigned int conn_protocol; - struct curl_certinfo certs; /* info about the certs, only populated in OpenSSL builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ + + bit timecond:1; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ }; @@ -1104,7 +1095,6 @@ struct Progress { curl_off_t current_speed; /* uses the currently fastest transfer */ - bool callback; /* set when progress callback is used */ int width; /* screen width at download start */ int flags; /* see progress.h */ @@ -1125,7 +1115,6 @@ struct Progress { struct curltime t_startop; struct curltime t_acceptdata; - bool is_t_startransfer_set; /* upload speed limit */ struct curltime ul_limit_start; @@ -1139,6 +1128,8 @@ struct Progress { curl_off_t speeder[ CURR_TIME ]; struct curltime speeder_time[ CURR_TIME ]; int speeder_c; + bit callback:1; /* set when progress callback is used */ + bit is_t_startransfer_set:1; }; typedef enum { @@ -1150,7 +1141,6 @@ typedef enum { HTTPREQ_PUT, HTTPREQ_HEAD, HTTPREQ_OPTIONS, - HTTPREQ_CUSTOM, HTTPREQ_LAST /* last in list */ } Curl_HttpReq; @@ -1187,12 +1177,12 @@ struct auth { unsigned long picked; unsigned long avail; /* Bitmask for what the server reports to support for this resource */ - bool done; /* TRUE when the auth phase is done and ready to do the *actual* - request */ - bool multipass; /* TRUE if this is not yet authenticated but within the - auth multipass negotiation */ - bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should - be RFC compliant */ + bit done:1; /* TRUE when the auth phase is done and ready to do the + *actual* request */ + bit multipass:1; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ + bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it + should be RFC compliant */ }; struct Curl_http2_dep { @@ -1263,11 +1253,6 @@ struct UrlState { /* Points to the connection cache */ struct conncache *conn_cache; - /* when curl_easy_perform() is called, the multi handle is "owned" by - the easy handle so curl_easy_cleanup() on such an easy handle will - also close the multi handle! */ - bool multi_owned_by_easy; - /* buffers to store authentication data in, as parsed from input options */ struct curltime keeps_speed; /* for the progress meter really */ @@ -1280,8 +1265,6 @@ struct UrlState { char *ulbuf; /* allocated upload buffer or NULL */ curl_off_t current_speed; /* the ProgressShow() function sets this, bytes / second */ - bool this_is_a_follow; /* this is a followed Location: request */ - bool refused_stream; /* this was refused, try again */ char *first_host; /* host name of the first (not followed) request. if set, this should be the host name that we will sent authorization to, no else. Used to make Location: @@ -1294,29 +1277,17 @@ struct UrlState { unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ - bool errorbuf; /* Set to TRUE if the error buffer is already filled in. - This must be set to FALSE every time _easy_perform() is - called. */ int os_errno; /* filled in with errno whenever an error occurs */ #ifdef HAVE_SIGNAL /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ void (*prev_signal)(int sig); #endif - bool allow_port; /* Is set.use_port allowed to take effect or not. This - is always set TRUE when curl_easy_perform() is called. */ struct digestdata digest; /* state data for host Digest auth */ struct digestdata proxydigest; /* state data for proxy Digest auth */ -#ifdef USE_SPNEGO - struct negotiatedata negotiate; /* state data for host Negotiate auth */ - struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ -#endif - struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ - bool authproblem; /* TRUE if there's some problem authenticating */ - void *resolver; /* resolver state, if it is used in the URL state - ares_channel f.e. */ @@ -1332,27 +1303,18 @@ struct UrlState { /* a place to store the most recently set FTP entrypath */ char *most_recent_ftp_entrypath; - /* set after initial USER failure, to prevent an authentication loop */ - bool ftp_trying_alternative; - bool wildcardmatch; /* enable wildcard matching */ int httpversion; /* the lowest HTTP version*10 reported by any server involved in this request */ - bool expect100header; /* TRUE if we added Expect: 100-continue */ #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ !defined(__SYMBIAN32__) /* do FTP line-end conversions on most platforms */ #define CURL_DO_LINEEND_CONV /* for FTP downloads: track CRLF sequences that span blocks */ - bool prev_block_had_trailing_cr; + bit prev_block_had_trailing_cr:1; /* for FTP downloads: how many CRLFs did we converted to LFs? */ curl_off_t crlf_conversions; #endif - bool slash_removed; /* set TRUE if the 'path' points to a path where the - initial URL slash separator has been taken off */ - bool use_range; - bool rangestringalloc; /* the range string is malloc()'ed */ - char *range; /* range, if used. See README for detailed specification on this syntax. */ curl_off_t resume_from; /* continue [ftp] transfer from here */ @@ -1368,19 +1330,12 @@ struct UrlState { size_t drain; /* Increased when this stream has data to read, even if its socket is not necessarily is readable. Decreased when checked. */ - bool done; /* set to FALSE when Curl_init_do() is called and set to TRUE - when multi_done() is called, to prevent multi_done() to get - invoked twice when the multi interface is used. */ curl_read_callback fread_func; /* read callback/function */ void *in; /* CURLOPT_READDATA */ struct Curl_easy *stream_depends_on; - bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; -#ifdef CURLDEBUG - bool conncache_lock; -#endif CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; #ifndef CURL_DISABLE_HTTP @@ -1390,6 +1345,32 @@ struct UrlState { #endif trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ +#ifdef CURLDEBUG + bit conncache_lock:1; +#endif + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bit multi_owned_by_easy:1; + + bit this_is_a_follow:1; /* this is a followed Location: request */ + bit refused_stream:1; /* this was refused, try again */ + bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + bit allow_port:1; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + bit authproblem:1; /* TRUE if there's some problem authenticating */ + /* set after initial USER failure, to prevent an authentication loop */ + bit ftp_trying_alternative:1; + bit wildcardmatch:1; /* enable wildcard matching */ + bit expect100header:1; /* TRUE if we added Expect: 100-continue */ + bit use_range:1; + bit rangestringalloc:1; /* the range string is malloc()'ed */ + bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ }; @@ -1402,14 +1383,15 @@ struct UrlState { struct DynamicStatic { char *url; /* work URL, copied from UserDefined */ - bool url_alloc; /* URL string is malloc()'ed */ char *referer; /* referer string */ - bool referer_alloc; /* referer string is malloc()ed */ struct curl_slist *cookielist; /* list of cookie files set by curl_easy_setopt(COOKIEFILE) calls */ struct curl_slist *resolve; /* set to point to the set.resolve list when this should be dealt with in pretransfer */ - bool wildcard_resolve; /* Set to true if any resolve change is a wildcard */ + bit url_alloc:1; /* URL string is malloc()'ed */ + bit referer_alloc:1; /* referer string is malloc()ed */ + bit wildcard_resolve:1; /* Set to true if any resolve change is a + wildcard */ }; /* @@ -1502,6 +1484,9 @@ enum dupstring { #endif STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ STRING_DOH, /* CURLOPT_DOH_URL */ +#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ +#endif /* -- end of zero-terminated strings -- */ STRING_LASTZEROTERMINATED, @@ -1539,8 +1524,6 @@ struct UserDefined { int keep_post; /* keep POSTs as POSTs after a 30x request; each bit represents a request, from 301 to 303 */ - bool free_referer; /* set TRUE if 'referer' points to a string we - allocated */ void *postfields; /* if POST, set the fields' values here */ curl_seek_callback seek_func; /* function that seeks the input */ curl_off_t postfieldsize; /* if POST, this might have a size to use instead @@ -1553,8 +1536,6 @@ struct UserDefined { curl_write_callback fwrite_header; /* function that stores headers */ curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ curl_read_callback fread_func_set; /* function that reads the input */ - int is_fread_set; /* boolean, has read callback been set to non-NULL? */ - int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */ curl_progress_callback fprogress; /* OLD and deprecated progress callback */ curl_xferinfo_callback fxferinfo; /* progress callback */ curl_debug_callback fdebug; /* function that write informational data */ @@ -1586,7 +1567,6 @@ struct UserDefined { long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */ long server_response_timeout; /* in milliseconds, 0 means no timeout */ long tftp_blksize; /* in bytes, 0 means use default */ - bool tftp_no_options; /* do not send TFTP options requests */ curl_off_t filesize; /* size of file to upload, -1 means unknown */ long low_speed_limit; /* bytes/second */ long low_speed_time; /* number of seconds */ @@ -1598,9 +1578,6 @@ struct UserDefined { struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ struct curl_httppost *httppost; /* linked list of old POST data */ curl_mimepart mimepost; /* MIME/POST data. */ - bool sep_headers; /* handle host and proxy headers separately */ - bool cookiesession; /* new cookie session? */ - bool crlf; /* convert crlf on ftp upload(?) */ struct curl_slist *quote; /* after connection is established */ struct curl_slist *postquote; /* after the transfer */ struct curl_slist *prequote; /* before the transfer, after type */ @@ -1619,7 +1596,6 @@ struct UserDefined { Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ long httpversion; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ - bool strip_path_slash; /* strip off initial slash from path */ struct ssl_config_data ssl; /* user defined SSL stuff */ struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ struct ssl_general_config general_ssl; /* general user defined SSL stuff */ @@ -1629,87 +1605,33 @@ struct UserDefined { size_t upload_buffer_size; /* size of upload buffer to use, keep it >= CURL_MAX_WRITE_SIZE */ void *private_data; /* application-private data */ - struct curl_slist *http200aliases; /* linked list of aliases for http200 */ - long ipver; /* the CURL_IPRESOLVE_* defines in the public header file 0 - whatever, 1 - v2, 2 - v6 */ - curl_off_t max_filesize; /* Maximum file size to download */ - curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ - int ftp_create_missing_dirs; /* 1 - create directories that don't exist 2 - the same but also allow MKD to fail once */ - curl_sshkeycallback ssh_keyfunc; /* key matching callback */ void *ssh_keyfunc_userp; /* custom pointer to callback */ - bool ssh_compression; /* enable SSH compression */ - -/* Here follows boolean settings that define how to behave during - this session. They are STATIC, set by libcurl users or at least initially - and they don't change during operations. */ - bool get_filetime; /* get the time and get of the remote file */ - bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */ - bool prefer_ascii; /* ASCII rather than binary */ - bool ftp_append; /* append, not overwrite, on upload */ - bool ftp_list_only; /* switch FTP command for listing directories */ - bool ftp_use_port; /* use the FTP PORT command */ - bool hide_progress; /* don't use the progress meter */ - bool http_fail_on_error; /* fail on HTTP error codes >= 400 */ - bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */ - bool http_follow_location; /* follow HTTP redirects */ - bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */ - bool allow_auth_to_other_hosts; - bool include_header; /* include received protocol headers in data output */ - bool http_set_referer; /* is a custom referer used */ - bool http_auto_referer; /* set "correct" referer when following location: */ - bool opt_no_body; /* as set with CURLOPT_NOBODY */ - bool upload; /* upload request */ enum CURL_NETRC_OPTION use_netrc; /* defined in include/curl.h */ - bool verbose; /* output verbosity */ - bool krb; /* Kerberos connection requested */ - bool reuse_forbid; /* forbidden to be reused, close after use */ - bool reuse_fresh; /* do not re-use an existing connection */ - bool ftp_use_epsv; /* if EPSV is to be attempted or not */ - bool ftp_use_eprt; /* if EPRT is to be attempted or not */ - bool ftp_use_pret; /* if PRET is to be used before PASV or not */ - curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or IMAP or POP3 or others! */ curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ curl_ftpccc ftp_ccc; /* FTP CCC options */ - bool no_signal; /* do not use any signal/alarm handler */ - bool global_dns_cache; /* subject for future removal */ - bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */ - bool ignorecl; /* ignore content length */ - bool ftp_skip_ip; /* skip the IP address the FTP server passes on to - us */ - bool connect_only; /* make connection, let application use the socket */ - long ssh_auth_types; /* allowed SSH auth types */ - bool http_te_skip; /* pass the raw body data to the user, even when - transfer-encoded (chunked, compressed) */ - bool http_ce_skip; /* pass the raw body data to the user, even when - content-encoded (chunked, compressed) */ long new_file_perms; /* Permissions to use when creating remote files */ long new_directory_perms; /* Permissions to use when creating remote dirs */ - bool proxy_transfer_mode; /* set transfer mode (;type=) when doing FTP - via an HTTP proxy */ + long ssh_auth_types; /* allowed SSH auth types */ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ unsigned int scope_id; /* Scope id for IPv6 */ long allowed_protocols; long redir_protocols; -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - bool socks5_gssapi_nec; /* Flag to support NEC SOCKS5 server */ -#endif struct curl_slist *mail_rcpt; /* linked list of mail recipients */ - bool sasl_ir; /* Enable/disable SASL initial response */ /* Common RTSP header options */ Curl_RtspReq rtspreq; /* RTSP request type */ long rtspversion; /* like httpversion, for RTSP */ - bool wildcard_enabled; /* enable wildcard matching */ curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer starts */ curl_chunk_end_callback chunk_end; /* called after part transferring @@ -1721,47 +1643,102 @@ struct UserDefined { long gssapi_delegation; /* GSS-API credential delegation, see the documentation of CURLOPT_GSSAPI_DELEGATION */ - bool tcp_keepalive; /* use TCP keepalives */ long tcp_keepidle; /* seconds in idle before sending keepalive probe */ long tcp_keepintvl; /* seconds between TCP keepalive probes */ - bool tcp_fastopen; /* use TCP Fast Open */ - size_t maxconnects; /* Max idle connections in the connection cache */ + size_t maxconnects; /* Max idle connections in the connection cache */ - bool ssl_enable_npn; /* TLS NPN extension? */ - bool ssl_enable_alpn; /* TLS ALPN extension? */ - bool path_as_is; /* allow dotdots? */ - bool pipewait; /* wait for pipe/multiplex status before starting a - new connection */ long expect_100_timeout; /* in milliseconds */ - bool suppress_connect_headers; /* suppress proxy CONNECT response headers - from user callbacks */ - - bool dns_shuffle_addresses; /* whether to shuffle addresses before use */ - struct Curl_easy *stream_depends_on; - bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; - - bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */ - struct Curl_http2_dep *stream_dependents; - bool abstract_unix_socket; - curl_resolver_start_callback resolver_start; /* optional callback called before resolver start */ void *resolver_start_client; /* pointer to pass to resolver start callback */ - bool disallow_username_in_url; /* disallow username in url */ long upkeep_interval_ms; /* Time between calls for connection upkeep. */ - bool doh; /* DNS-over-HTTPS enabled */ - bool doh_get; /* use GET for DoH requests, instead of POST */ - bool http09_allowed; /* allow HTTP/0.9 responses */ multidone_func fmultidone; struct Curl_easy *dohfor; /* this is a DoH request for that transfer */ CURLU *uh; /* URL handle for the current parsed URL */ void *trailer_data; /* pointer to pass to trailer data callback */ curl_trailer_callback trailer_callback; /* trailing data callback */ + bit is_fread_set:1; /* has read callback been set to non-NULL? */ + bit is_fwrite_set:1; /* has write callback been set to non-NULL? */ + bit free_referer:1; /* set TRUE if 'referer' points to a string we + allocated */ + bit tftp_no_options:1; /* do not send TFTP options requests */ + bit sep_headers:1; /* handle host and proxy headers separately */ + bit cookiesession:1; /* new cookie session? */ + bit crlf:1; /* convert crlf on ftp upload(?) */ + bit strip_path_slash:1; /* strip off initial slash from path */ + bit ssh_compression:1; /* enable SSH compression */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + bit get_filetime:1; /* get the time and get of the remote file */ + bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */ + bit prefer_ascii:1; /* ASCII rather than binary */ + bit ftp_append:1; /* append, not overwrite, on upload */ + bit ftp_list_only:1; /* switch FTP command for listing directories */ + bit ftp_use_port:1; /* use the FTP PORT command */ + bit hide_progress:1; /* don't use the progress meter */ + bit http_fail_on_error:1; /* fail on HTTP error codes >= 400 */ + bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */ + bit http_follow_location:1; /* follow HTTP redirects */ + bit http_transfer_encoding:1; /* request compressed HTTP + transfer-encoding */ + bit allow_auth_to_other_hosts:1; + bit include_header:1; /* include received protocol headers in data output */ + bit http_set_referer:1; /* is a custom referer used */ + bit http_auto_referer:1; /* set "correct" referer when following + location: */ + bit opt_no_body:1; /* as set with CURLOPT_NOBODY */ + bit upload:1; /* upload request */ + bit verbose:1; /* output verbosity */ + bit krb:1; /* Kerberos connection requested */ + bit reuse_forbid:1; /* forbidden to be reused, close after use */ + bit reuse_fresh:1; /* do not re-use an existing connection */ + bit ftp_use_epsv:1; /* if EPSV is to be attempted or not */ + bit ftp_use_eprt:1; /* if EPRT is to be attempted or not */ + bit ftp_use_pret:1; /* if PRET is to be used before PASV or not */ + + bit no_signal:1; /* do not use any signal/alarm handler */ + bit global_dns_cache:1; /* subject for future removal */ + bit tcp_nodelay:1; /* whether to enable TCP_NODELAY or not */ + bit ignorecl:1; /* ignore content length */ + bit ftp_skip_ip:1; /* skip the IP address the FTP server passes on to + us */ + bit connect_only:1; /* make connection, let application use the socket */ + bit http_te_skip:1; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bit http_ce_skip:1; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + bit proxy_transfer_mode:1; /* set transfer mode (;type=) when doing + FTP via an HTTP proxy */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */ +#endif + bit sasl_ir:1; /* Enable/disable SASL initial response */ + bit wildcard_enabled:1; /* enable wildcard matching */ + bit tcp_keepalive:1; /* use TCP keepalives */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit ssl_enable_npn:1; /* TLS NPN extension? */ + bit ssl_enable_alpn:1;/* TLS ALPN extension? */ + bit path_as_is:1; /* allow dotdots? */ + bit pipewait:1; /* wait for pipe/multiplex status before starting a + new connection */ + bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers + from user callbacks */ + bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1 + header */ + bit abstract_unix_socket:1; + bit disallow_username_in_url:1; /* disallow username in url */ + bit doh:1; /* DNS-over-HTTPS enabled */ + bit doh_get:1; /* use GET for DoH requests, instead of POST */ + bit http09_allowed:1; /* allow HTTP/0.9 responses */ }; struct Names { @@ -1826,6 +1803,9 @@ struct Curl_easy { NOTE that the 'cookie' field in the UserDefined struct defines if the "engine" is to be used or not. */ +#ifdef USE_ALTSVC + struct altsvcinfo *asi; /* the alt-svc cache */ +#endif struct Progress progress; /* for all the progress meter data */ struct UrlState state; /* struct for fields used for state info and other dynamic purposes */ diff --git a/libs/libcurl/src/vauth/spnego_gssapi.c b/libs/libcurl/src/vauth/spnego_gssapi.c index 4a48bdd208..7c4bd4b595 100644 --- a/libs/libcurl/src/vauth/spnego_gssapi.c +++ b/libs/libcurl/src/vauth/spnego_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -273,6 +273,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego) /* Reset any variables */ nego->status = 0; + nego->state = GSS_AUTHNONE; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; } #endif /* HAVE_GSSAPI && USE_SPNEGO */ diff --git a/libs/libcurl/src/vauth/spnego_sspi.c b/libs/libcurl/src/vauth/spnego_sspi.c index 00d8404652..0171ec52b5 100644 --- a/libs/libcurl/src/vauth/spnego_sspi.c +++ b/libs/libcurl/src/vauth/spnego_sspi.c @@ -248,8 +248,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, free(chlg); if(GSS_ERROR(nego->status)) { + char buffer[STRERROR_LEN]; failf(data, "InitializeSecurityContext failed: %s", - Curl_sspi_strerror(data->conn, nego->status)); + Curl_sspi_strerror(nego->status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; } @@ -342,6 +343,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego) /* Reset any variables */ nego->status = 0; nego->token_max = 0; + nego->state = GSS_AUTHNONE; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; } #endif /* USE_WINDOWS_SSPI && USE_SPNEGO */ diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index e553100c21..9369ae8e3f 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -212,6 +212,10 @@ char *curl_version(void) } #endif + /* Silent scan-build even if librtmp is not enabled. */ + (void) left; + (void) ptr; + initialized = true; return version; } @@ -365,6 +369,9 @@ static curl_version_info_data version_info = { #endif #if defined(HAVE_BROTLI) | CURL_VERSION_BROTLI +#endif +#if defined(USE_ALTSVC) + | CURL_VERSION_ALTSVC #endif , NULL, /* ssl_version */ diff --git a/libs/libcurl/src/vtls/cyassl.c b/libs/libcurl/src/vtls/cyassl.c index ea96cf65e5..c7a3268efa 100644 --- a/libs/libcurl/src/vtls/cyassl.c +++ b/libs/libcurl/src/vtls/cyassl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -67,15 +67,6 @@ and that's a problem since options.h hasn't been included yet. */ #endif #endif -/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC - supported curve extension in options.h. Note ECC is enabled separately. */ -#ifndef HAVE_SUPPORTED_CURVES -#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ - defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) -#define HAVE_SUPPORTED_CURVES -#endif -#endif - #include #include "urldata.h" @@ -364,16 +355,6 @@ cyassl_connect_step1(struct connectdata *conn, } #endif -#ifdef HAVE_SUPPORTED_CURVES - /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically: - https://github.com/wolfSSL/wolfssl/issues/366 - The supported curves below are those also supported by OpenSSL 1.0.2 and - in the same order. */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */ -#endif - /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { CURLcode result = CURLE_OK; diff --git a/libs/libcurl/src/vtls/darwinssl.c b/libs/libcurl/src/vtls/darwinssl.c deleted file mode 100644 index bb251cdb30..0000000000 --- a/libs/libcurl/src/vtls/darwinssl.c +++ /dev/null @@ -1,3259 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2012 - 2017, Nick Zitzmann, . - * Copyright (C) 2012 - 2018, Daniel Stenberg, , 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. - * - ***************************************************************************/ - -/* - * Source file for all iOS and macOS SecureTransport-specific code for the - * TLS/SSL layer. No code but vtls.c should ever call or use these functions. - */ - -#include "curl_setup.h" - -#include "urldata.h" /* for the Curl_easy definition */ -#include "curl_base64.h" -#include "strtok.h" - -#ifdef USE_DARWINSSL - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#endif /* __clang__ */ - -#include - -#include -/* For some reason, when building for iOS, the omnibus header above does - * not include SecureTransport.h as of iOS SDK 5.1. */ -#include -#include -#include - -/* The Security framework has changed greatly between iOS and different macOS - versions, and we will try to support as many of them as we can (back to - Leopard and iOS 5) by using macros and weak-linking. - - In general, you want to build this using the most recent OS SDK, since some - features require curl to be built against the latest SDK. TLS 1.1 and 1.2 - support, for instance, require the macOS 10.8 SDK or later. TLS 1.3 - requires the macOS 10.13 or iOS 11 SDK or later. */ -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 -#error "The darwinssl back-end requires Leopard or later." -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ - -#define CURL_BUILD_IOS 0 -#define CURL_BUILD_IOS_7 0 -#define CURL_BUILD_IOS_9 0 -#define CURL_BUILD_IOS_11 0 -#define CURL_BUILD_MAC 1 -/* This is the maximum API level we are allowed to use when building: */ -#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 -#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 -#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 -#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 -#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 -#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 -#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 -/* These macros mean "the following code is present to allow runtime backward - compatibility with at least this cat or earlier": - (You set this at build-time using the compiler command line option - "-mmacos-version-min.") */ -#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 -#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 -#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 -#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 -#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 - -#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE -#define CURL_BUILD_IOS 1 -#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 -#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 -#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 -#define CURL_BUILD_MAC 0 -#define CURL_BUILD_MAC_10_5 0 -#define CURL_BUILD_MAC_10_6 0 -#define CURL_BUILD_MAC_10_7 0 -#define CURL_BUILD_MAC_10_8 0 -#define CURL_BUILD_MAC_10_9 0 -#define CURL_BUILD_MAC_10_11 0 -#define CURL_BUILD_MAC_10_13 0 -#define CURL_SUPPORT_MAC_10_5 0 -#define CURL_SUPPORT_MAC_10_6 0 -#define CURL_SUPPORT_MAC_10_7 0 -#define CURL_SUPPORT_MAC_10_8 0 -#define CURL_SUPPORT_MAC_10_9 0 - -#else -#error "The darwinssl back-end requires iOS or OS X." -#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ - -#if CURL_BUILD_MAC -#include -#endif /* CURL_BUILD_MAC */ - -#include "urldata.h" -#include "sendf.h" -#include "inet_pton.h" -#include "connect.h" -#include "select.h" -#include "vtls.h" -#include "darwinssl.h" -#include "curl_printf.h" -#include "strdup.h" - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* From MacTypes.h (which we can't include because it isn't present in iOS: */ -#define ioErr -36 -#define paramErr -50 - -struct ssl_backend_data { - SSLContextRef ssl_ctx; - curl_socket_t ssl_sockfd; - bool ssl_direction; /* true if writing, false if reading */ - size_t ssl_write_buffered_length; -}; - -#define BACKEND connssl->backend - -/* pinned public key support tests */ - -/* version 1 supports macOS 10.12+ and iOS 10+ */ -#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ - (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) -#define DARWIN_SSL_PINNEDPUBKEY_V1 1 -#endif - -/* version 2 supports MacOSX 10.7+ */ -#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) -#define DARWIN_SSL_PINNEDPUBKEY_V2 1 -#endif - -#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2) -/* this backend supports CURLOPT_PINNEDPUBLICKEY */ -#define DARWIN_SSL_PINNEDPUBKEY 1 -#endif /* DARWIN_SSL_PINNEDPUBKEY */ - -#ifdef DARWIN_SSL_PINNEDPUBKEY -/* both new and old APIs return rsa keys missing the spki header (not DER) */ -static const unsigned char rsa4096SpkiHeader[] = { - 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; - -static const unsigned char rsa2048SpkiHeader[] = { - 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 -/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ -static const unsigned char ecDsaSecp256r1SpkiHeader[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, - 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, - 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, - 0x42, 0x00}; - -static const unsigned char ecDsaSecp384r1SpkiHeader[] = { - 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, - 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, - 0x00, 0x22, 0x03, 0x62, 0x00}; -#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */ -#endif /* DARWIN_SSL_PINNEDPUBKEY */ - -/* The following two functions were ripped from Apple sample code, - * with some modifications: */ -static OSStatus SocketRead(SSLConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength) /* IN/OUT */ -{ - size_t bytesToGo = *dataLength; - size_t initLen = bytesToGo; - UInt8 *currData = (UInt8 *)data; - /*int sock = *(int *)connection;*/ - struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; - int sock = BACKEND->ssl_sockfd; - OSStatus rtn = noErr; - size_t bytesRead; - ssize_t rrtn; - int theErr; - - *dataLength = 0; - - for(;;) { - bytesRead = 0; - rrtn = read(sock, currData, bytesToGo); - if(rrtn <= 0) { - /* this is guesswork... */ - theErr = errno; - if(rrtn == 0) { /* EOF = server hung up */ - /* the framework will turn this into errSSLClosedNoNotify */ - rtn = errSSLClosedGraceful; - } - else /* do the switch */ - switch(theErr) { - case ENOENT: - /* connection closed */ - rtn = errSSLClosedGraceful; - break; - case ECONNRESET: - rtn = errSSLClosedAbort; - break; - case EAGAIN: - rtn = errSSLWouldBlock; - BACKEND->ssl_direction = false; - break; - default: - rtn = ioErr; - break; - } - break; - } - else { - bytesRead = rrtn; - } - bytesToGo -= bytesRead; - currData += bytesRead; - - if(bytesToGo == 0) { - /* filled buffer with incoming data, done */ - break; - } - } - *dataLength = initLen - bytesToGo; - - return rtn; -} - -static OSStatus SocketWrite(SSLConnectionRef connection, - const void *data, - size_t *dataLength) /* IN/OUT */ -{ - size_t bytesSent = 0; - /*int sock = *(int *)connection;*/ - struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; - int sock = BACKEND->ssl_sockfd; - ssize_t length; - size_t dataLen = *dataLength; - const UInt8 *dataPtr = (UInt8 *)data; - OSStatus ortn; - int theErr; - - *dataLength = 0; - - do { - length = write(sock, - (char *)dataPtr + bytesSent, - dataLen - bytesSent); - } while((length > 0) && - ( (bytesSent += length) < dataLen) ); - - if(length <= 0) { - theErr = errno; - if(theErr == EAGAIN) { - ortn = errSSLWouldBlock; - BACKEND->ssl_direction = true; - } - else { - ortn = ioErr; - } - } - else { - ortn = noErr; - } - *dataLength = bytesSent; - return ortn; -} - -#ifndef CURL_DISABLE_VERBOSE_STRINGS -CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) -{ - switch(cipher) { - /* SSL version 3.0 */ - case SSL_RSA_WITH_NULL_MD5: - return "SSL_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "SSL_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "SSL_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "SSL_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_SHA: - return "SSL_RSA_WITH_IDEA_CBC_SHA"; - break; - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_RSA_WITH_DES_CBC_SHA: - return "SSL_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_DES_CBC_SHA: - return "SSL_DH_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_DES_CBC_SHA: - return "SSL_DH_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "SSL_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_anon_WITH_DES_CBC_SHA: - return "SSL_DH_anon_WITH_DES_CBC_SHA"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: - return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; - break; - /* TLS 1.0 with AES (RFC 3268) - (Apparently these are used in SSLv3 implementations as well.) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; - /* SSL version 2.0 */ - case SSL_RSA_WITH_RC2_CBC_MD5: - return "SSL_RSA_WITH_RC2_CBC_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_MD5: - return "SSL_RSA_WITH_IDEA_CBC_MD5"; - break; - case SSL_RSA_WITH_DES_CBC_MD5: - return "SSL_RSA_WITH_DES_CBC_MD5"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_MD5: - return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; - break; - } - return "SSL_NULL_WITH_NULL_NULL"; -} - -CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) -{ - switch(cipher) { - /* TLS 1.0 with AES (RFC 3268) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; -#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS - /* TLS 1.0 with ECDSA (RFC 4492) */ - case TLS_ECDH_ECDSA_WITH_NULL_SHA: - return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_NULL_SHA: - return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_NULL_SHA: - return "TLS_ECDH_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_NULL_SHA: - return "TLS_ECDHE_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_NULL_SHA: - return "TLS_ECDH_anon_WITH_NULL_SHA"; - break; - case TLS_ECDH_anon_WITH_RC4_128_SHA: - return "TLS_ECDH_anon_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - /* TLS 1.2 (RFC 5246) */ - case TLS_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case TLS_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case TLS_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_WITH_NULL_SHA256: - return "TLS_RSA_WITH_NULL_SHA256"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; - break; - /* TLS 1.2 with AES GCM (RFC 5288) */ - case TLS_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_anon_WITH_AES_128_GCM_SHA256: - return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_GCM_SHA384: - return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; - break; - /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: - return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; - break; -#else - case SSL_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - /* TLS PSK (RFC 4279): */ - case TLS_PSK_WITH_RC4_128_SHA: - return "TLS_PSK_WITH_RC4_128_SHA"; - break; - case TLS_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA: - return "TLS_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA: - return "TLS_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_RC4_128_SHA: - return "TLS_DHE_PSK_WITH_RC4_128_SHA"; - break; - case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_RC4_128_SHA: - return "TLS_RSA_PSK_WITH_RC4_128_SHA"; - break; - case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; - break; - /* More TLS PSK (RFC 4785): */ - case TLS_PSK_WITH_NULL_SHA: - return "TLS_PSK_WITH_NULL_SHA"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA: - return "TLS_DHE_PSK_WITH_NULL_SHA"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA: - return "TLS_RSA_PSK_WITH_NULL_SHA"; - break; - /* Even more TLS PSK (RFC 5487): */ - case TLS_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_PSK_WITH_NULL_SHA256: - return "TLS_PSK_WITH_NULL_SHA256"; - break; - case TLS_PSK_WITH_NULL_SHA384: - return "TLS_PSK_WITH_NULL_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA256: - return "TLS_DHE_PSK_WITH_NULL_SHA256"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA256: - return "TLS_RSA_PSK_WITH_NULL_SHA256"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; -#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ -#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 - /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ - case TLS_AES_128_GCM_SHA256: - return "TLS_AES_128_GCM_SHA256"; - break; - case TLS_AES_256_GCM_SHA384: - return "TLS_AES_256_GCM_SHA384"; - break; - case TLS_CHACHA20_POLY1305_SHA256: - return "TLS_CHACHA20_POLY1305_SHA256"; - break; - case TLS_AES_128_CCM_SHA256: - return "TLS_AES_128_CCM_SHA256"; - break; - case TLS_AES_128_CCM_8_SHA256: - return "TLS_AES_128_CCM_8_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; - break; -#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ - } - return "TLS_NULL_WITH_NULL_NULL"; -} -#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ - -#if CURL_BUILD_MAC -CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) -{ - int mib[2]; - char *os_version; - size_t os_version_len; - char *os_version_major, *os_version_minor; - char *tok_buf; - - /* Get the Darwin kernel version from the kernel using sysctl(): */ - mib[0] = CTL_KERN; - mib[1] = KERN_OSRELEASE; - if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) - return; - os_version = malloc(os_version_len*sizeof(char)); - if(!os_version) - return; - if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { - free(os_version); - return; - } - - /* Parse the version: */ - os_version_major = strtok_r(os_version, ".", &tok_buf); - os_version_minor = strtok_r(NULL, ".", &tok_buf); - *major = atoi(os_version_major); - *minor = atoi(os_version_minor); - free(os_version); -} -#endif /* CURL_BUILD_MAC */ - -/* Apple provides a myriad of ways of getting information about a certificate - into a string. Some aren't available under iOS or newer cats. So here's - a unified function for getting a string describing the certificate that - ought to work in all cats starting with Leopard. */ -CF_INLINE CFStringRef getsubject(SecCertificateRef cert) -{ - CFStringRef server_cert_summary = CFSTR("(null)"); - -#if CURL_BUILD_IOS - /* iOS: There's only one way to do this. */ - server_cert_summary = SecCertificateCopySubjectSummary(cert); -#else -#if CURL_BUILD_MAC_10_7 - /* Lion & later: Get the long description if we can. */ - if(SecCertificateCopyLongDescription != NULL) - server_cert_summary = - SecCertificateCopyLongDescription(NULL, cert, NULL); - else -#endif /* CURL_BUILD_MAC_10_7 */ -#if CURL_BUILD_MAC_10_6 - /* Snow Leopard: Get the certificate summary. */ - if(SecCertificateCopySubjectSummary != NULL) - server_cert_summary = SecCertificateCopySubjectSummary(cert); - else -#endif /* CURL_BUILD_MAC_10_6 */ - /* Leopard is as far back as we go... */ - (void)SecCertificateCopyCommonName(cert, &server_cert_summary); -#endif /* CURL_BUILD_IOS */ - return server_cert_summary; -} - -static CURLcode CopyCertSubject(struct Curl_easy *data, - SecCertificateRef cert, char **certp) -{ - CFStringRef c = getsubject(cert); - CURLcode result = CURLE_OK; - const char *direct; - char *cbuf = NULL; - *certp = NULL; - - if(!c) { - failf(data, "SSL: invalid CA certificate subject"); - return CURLE_PEER_FAILED_VERIFICATION; - } - - /* If the subject is already available as UTF-8 encoded (ie 'direct') then - use that, else convert it. */ - direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8); - if(direct) { - *certp = strdup(direct); - if(!*certp) { - failf(data, "SSL: out of memory"); - result = CURLE_OUT_OF_MEMORY; - } - } - else { - size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; - cbuf = calloc(cbuf_size, 1); - if(cbuf) { - if(!CFStringGetCString(c, cbuf, cbuf_size, - kCFStringEncodingUTF8)) { - failf(data, "SSL: invalid CA certificate subject"); - result = CURLE_PEER_FAILED_VERIFICATION; - } - else - /* pass back the buffer */ - *certp = cbuf; - } - else { - failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size); - result = CURLE_OUT_OF_MEMORY; - } - } - if(result) - free(cbuf); - CFRelease(c); - return result; -} - -#if CURL_SUPPORT_MAC_10_6 -/* The SecKeychainSearch API was deprecated in Lion, and using it will raise - deprecation warnings, so let's not compile this unless it's necessary: */ -static OSStatus CopyIdentityWithLabelOldSchool(char *label, - SecIdentityRef *out_c_a_k) -{ - OSStatus status = errSecItemNotFound; - SecKeychainAttributeList attr_list; - SecKeychainAttribute attr; - SecKeychainSearchRef search = NULL; - SecCertificateRef cert = NULL; - - /* Set up the attribute list: */ - attr_list.count = 1L; - attr_list.attr = &attr; - - /* Set up our lone search criterion: */ - attr.tag = kSecLabelItemAttr; - attr.data = label; - attr.length = (UInt32)strlen(label); - - /* Start searching: */ - status = SecKeychainSearchCreateFromAttributes(NULL, - kSecCertificateItemClass, - &attr_list, - &search); - if(status == noErr) { - status = SecKeychainSearchCopyNext(search, - (SecKeychainItemRef *)&cert); - if(status == noErr && cert) { - /* If we found a certificate, does it have a private key? */ - status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); - CFRelease(cert); - } - } - - if(search) - CFRelease(search); - return status; -} -#endif /* CURL_SUPPORT_MAC_10_6 */ - -static OSStatus CopyIdentityWithLabel(char *label, - SecIdentityRef *out_cert_and_key) -{ - OSStatus status = errSecItemNotFound; - -#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS - CFArrayRef keys_list; - CFIndex keys_list_count; - CFIndex i; - CFStringRef common_name; - - /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. - kSecClassIdentity was introduced in Lion. If both exist, let's use them - to find the certificate. */ - if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { - CFTypeRef keys[5]; - CFTypeRef values[5]; - CFDictionaryRef query_dict; - CFStringRef label_cf = CFStringCreateWithCString(NULL, label, - kCFStringEncodingUTF8); - - /* Set up our search criteria and expected results: */ - values[0] = kSecClassIdentity; /* we want a certificate and a key */ - keys[0] = kSecClass; - values[1] = kCFBooleanTrue; /* we want a reference */ - keys[1] = kSecReturnRef; - values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the - * label matching below worked correctly */ - keys[2] = kSecMatchLimit; - /* identity searches need a SecPolicyRef in order to work */ - values[3] = SecPolicyCreateSSL(false, NULL); - keys[3] = kSecMatchPolicy; - /* match the name of the certificate (doesn't work in macOS 10.12.1) */ - values[4] = label_cf; - keys[4] = kSecAttrLabel; - query_dict = CFDictionaryCreate(NULL, (const void **)keys, - (const void **)values, 5L, - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFRelease(values[3]); - - /* Do we have a match? */ - status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); - - /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, - * we need to find the correct identity ourselves */ - if(status == noErr) { - keys_list_count = CFArrayGetCount(keys_list); - *out_cert_and_key = NULL; - status = 1; - for(i = 0; idata; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - long ssl_version = SSL_CONN_CONFIG(version); - long ssl_version_max = SSL_CONN_CONFIG(version_max); - long max_supported_version_by_os; - - /* macOS 10.5-10.7 supported TLS 1.0 only. - macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2. - macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */ -#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 - if(__builtin_available(macOS 10.13, iOS 11.0, *)) { - max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3; - } - else { - max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; - } -#else - max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; -#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && - HAVE_BUILTIN_AVAILABLE == 1 */ - - switch(ssl_version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - ssl_version = CURL_SSLVERSION_TLSv1_0; - break; - } - - switch(ssl_version_max) { - case CURL_SSLVERSION_MAX_NONE: - case CURL_SSLVERSION_MAX_DEFAULT: - ssl_version_max = max_supported_version_by_os; - break; - } - -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - if(SSLSetProtocolVersionMax != NULL) { - SSLProtocol darwin_ver_min = kTLSProtocol1; - SSLProtocol darwin_ver_max = kTLSProtocol1; - CURLcode result = darwinssl_version_from_curl(&darwin_ver_min, - ssl_version); - if(result) { - failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); - return result; - } - result = darwinssl_version_from_curl(&darwin_ver_max, - ssl_version_max >> 16); - if(result) { - failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); - return result; - } - - (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min); - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max); - return result; - } - else { -#if CURL_SUPPORT_MAC_10_8 - long i = ssl_version; - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocolAll, - false); - for(; i <= (ssl_version_max >> 16); i++) { - switch(i) { - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol1, - true); - break; - case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol11, - true); - break; - case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_TLSv1_3: - failf(data, "Your version of the OS does not support TLSv1.3"); - return CURLE_SSL_CONNECT_ERROR; - } - } - return CURLE_OK; -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - failf(data, "DarwinSSL: cannot set SSL protocol"); - return CURLE_SSL_CONNECT_ERROR; -} - - -static CURLcode darwinssl_connect_step1(struct connectdata *conn, - int sockindex) -{ - struct Curl_easy *data = conn->data; - curl_socket_t sockfd = conn->sock[sockindex]; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); - const bool verifypeer = SSL_CONN_CONFIG(verifypeer); - char * const ssl_cert = SSL_SET_OPTION(cert); - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif /* ENABLE_IPV6 */ - size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; - SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; - OSStatus err = noErr; -#if CURL_BUILD_MAC - int darwinver_maj = 0, darwinver_min = 0; - - GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); -#endif /* CURL_BUILD_MAC */ - -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - if(SSLCreateContext != NULL) { /* use the newer API if available */ - if(BACKEND->ssl_ctx) - CFRelease(BACKEND->ssl_ctx); - BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); - if(!BACKEND->ssl_ctx) { - failf(data, "SSL: couldn't create a context!"); - return CURLE_OUT_OF_MEMORY; - } - } - else { - /* The old ST API does not exist under iOS, so don't compile it: */ -#if CURL_SUPPORT_MAC_10_8 - if(BACKEND->ssl_ctx) - (void)SSLDisposeContext(BACKEND->ssl_ctx); - err = SSLNewContext(false, &(BACKEND->ssl_ctx)); - if(err != noErr) { - failf(data, "SSL: couldn't create a context: OSStatus %d", err); - return CURLE_OUT_OF_MEMORY; - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#else - if(BACKEND->ssl_ctx) - (void)SSLDisposeContext(BACKEND->ssl_ctx); - err = SSLNewContext(false, &(BACKEND->ssl_ctx)); - if(err != noErr) { - failf(data, "SSL: couldn't create a context: OSStatus %d", err); - return CURLE_OUT_OF_MEMORY; - } -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */ - - /* check to see if we've been told to use an explicit SSL/TLS version */ -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - if(SSLSetProtocolVersionMax != NULL) { - switch(conn->ssl_config.version) { - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); -#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 - if(__builtin_available(macOS 10.13, iOS 11.0, *)) { - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13); - } - else { - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); - } -#else - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); -#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && - HAVE_BUILTIN_AVAILABLE == 1 */ - break; - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - CURLcode result = set_ssl_version_min_max(conn, sockindex); - if(result != CURLE_OK) - return result; - break; - } - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3); - break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2); - break; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; - } - } - else { -#if CURL_SUPPORT_MAC_10_8 - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocolAll, - false); - switch(conn->ssl_config.version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol1, - true); - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol11, - true); - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - CURLcode result = set_ssl_version_min_max(conn, sockindex); - if(result != CURLE_OK) - return result; - break; - } - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#else - if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { - failf(data, "Your version of the OS does not support to set maximum" - " SSL/TLS version"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false); - switch(conn->ssl_config.version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kTLSProtocol1, - true); - break; - case CURL_SSLVERSION_TLSv1_1: - failf(data, "Your version of the OS does not support TLSv1.1"); - return CURLE_SSL_CONNECT_ERROR; - case CURL_SSLVERSION_TLSv1_2: - failf(data, "Your version of the OS does not support TLSv1.2"); - return CURLE_SSL_CONNECT_ERROR; - case CURL_SSLVERSION_TLSv1_3: - failf(data, "Your version of the OS does not support TLSv1.3"); - return CURLE_SSL_CONNECT_ERROR; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; - } -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - -#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 - if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { - CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks); - -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { - CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); - } -#endif - - CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); - - /* expects length prefixed preference ordered list of protocols in wire - * format - */ - err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr); - if(err != noErr) - infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", - err); - CFRelease(alpnArr); - } - } -#endif - - if(SSL_SET_OPTION(key)) { - infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " - "Transport. The private key must be in the Keychain.\n"); - } - - if(ssl_cert) { - SecIdentityRef cert_and_key = NULL; - bool is_cert_file = is_file(ssl_cert); - - /* User wants to authenticate with a client cert. Look for it: - If we detect that this is a file on disk, then let's load it. - Otherwise, assume that the user wants to use an identity loaded - from the Keychain. */ - if(is_cert_file) { - if(!SSL_SET_OPTION(cert_type)) - infof(data, "WARNING: SSL: Certificate type not set, assuming " - "PKCS#12 format.\n"); - else if(strncmp(SSL_SET_OPTION(cert_type), "P12", - strlen(SSL_SET_OPTION(cert_type))) != 0) - infof(data, "WARNING: SSL: The Security framework only supports " - "loading identities that are in PKCS#12 format.\n"); - - err = CopyIdentityFromPKCS12File(ssl_cert, - SSL_SET_OPTION(key_passwd), &cert_and_key); - } - else - err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); - - if(err == noErr && cert_and_key) { - SecCertificateRef cert = NULL; - CFTypeRef certs_c[1]; - CFArrayRef certs; - - /* If we found one, print it out: */ - err = SecIdentityCopyCertificate(cert_and_key, &cert); - if(err == noErr) { - char *certp; - CURLcode result = CopyCertSubject(data, cert, &certp); - if(!result) { - infof(data, "Client certificate: %s\n", certp); - free(certp); - } - - CFRelease(cert); - if(result == CURLE_PEER_FAILED_VERIFICATION) - return CURLE_SSL_CERTPROBLEM; - if(result) - return result; - } - certs_c[0] = cert_and_key; - certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, - &kCFTypeArrayCallBacks); - err = SSLSetCertificate(BACKEND->ssl_ctx, certs); - if(certs) - CFRelease(certs); - if(err != noErr) { - failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); - return CURLE_SSL_CERTPROBLEM; - } - CFRelease(cert_and_key); - } - else { - switch(err) { - case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ - failf(data, "SSL: Incorrect password for the certificate \"%s\" " - "and its private key.", ssl_cert); - break; - case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ - failf(data, "SSL: Couldn't make sense of the data in the " - "certificate \"%s\" and its private key.", - ssl_cert); - break; - case -25260: /* errSecPassphraseRequired */ - failf(data, "SSL The certificate \"%s\" requires a password.", - ssl_cert); - break; - case errSecItemNotFound: - failf(data, "SSL: Can't find the certificate \"%s\" and its private " - "key in the Keychain.", ssl_cert); - break; - default: - failf(data, "SSL: Can't load the certificate \"%s\" and its private " - "key: OSStatus %d", ssl_cert, err); - break; - } - return CURLE_SSL_CERTPROBLEM; - } - } - - /* SSL always tries to verify the peer, this only says whether it should - * fail to connect if the verification fails, or if it should continue - * anyway. In the latter case the result of the verification is checked with - * SSL_get_verify_result() below. */ -#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS - /* Snow Leopard introduced the SSLSetSessionOption() function, but due to - a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag - works, it doesn't work as expected under Snow Leopard, Lion or - Mountain Lion. - So we need to call SSLSetEnableCertVerify() on those older cats in order - to disable certificate validation if the user turned that off. - (SecureTransport will always validate the certificate chain by - default.) - Note: - Darwin 11.x.x is Lion (10.7) - Darwin 12.x.x is Mountain Lion (10.8) - Darwin 13.x.x is Mavericks (10.9) - Darwin 14.x.x is Yosemite (10.10) - Darwin 15.x.x is El Capitan (10.11) - */ -#if CURL_BUILD_MAC - if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { -#else - if(SSLSetSessionOption != NULL) { -#endif /* CURL_BUILD_MAC */ - bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; - err = SSLSetSessionOption(BACKEND->ssl_ctx, - kSSLSessionOptionBreakOnServerAuth, - break_on_auth); - if(err != noErr) { - failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } - } - else { -#if CURL_SUPPORT_MAC_10_8 - err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, - conn->ssl_config.verifypeer?true:false); - if(err != noErr) { - failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#else - err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, - conn->ssl_config.verifypeer?true:false); - if(err != noErr) { - failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } -#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ - - if(ssl_cafile && verifypeer) { - bool is_cert_file = is_file(ssl_cafile); - - if(!is_cert_file) { - failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); - return CURLE_SSL_CACERT_BADFILE; - } - } - - /* Configure hostname check. SNI is used if available. - * Both hostname check and SNI require SSLSetPeerDomainName(). - * Also: the verifyhost setting influences SNI usage */ - if(conn->ssl_config.verifyhost) { - err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname, - strlen(hostname)); - - if(err != noErr) { - infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", - err); - } - - if((Curl_inet_pton(AF_INET, hostname, &addr)) - #ifdef ENABLE_IPV6 - || (Curl_inet_pton(AF_INET6, hostname, &addr)) - #endif - ) { - infof(data, "WARNING: using IP address, SNI is being disabled by " - "the OS.\n"); - } - } - else { - infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); - } - - /* Disable cipher suites that ST supports but are not safe. These ciphers - are unlikely to be used in any case since ST gives other ciphers a much - higher priority, but it's probably better that we not connect at all than - to give the user a false sense of security if the server only supports - insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ - err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count); - if(err != noErr) { - failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", - err); - return CURLE_SSL_CIPHER; - } - all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!all_ciphers) { - failf(data, "SSL: Failed to allocate memory for all ciphers"); - return CURLE_OUT_OF_MEMORY; - } - allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!allowed_ciphers) { - Curl_safefree(all_ciphers); - failf(data, "SSL: Failed to allocate memory for allowed ciphers"); - return CURLE_OUT_OF_MEMORY; - } - err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers, - &all_ciphers_count); - if(err != noErr) { - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); - return CURLE_SSL_CIPHER; - } - for(i = 0UL ; i < all_ciphers_count ; i++) { -#if CURL_BUILD_MAC - /* There's a known bug in early versions of Mountain Lion where ST's ECC - ciphers (cipher suite 0xC001 through 0xC032) simply do not work. - Work around the problem here by disabling those ciphers if we are - running in an affected version of OS X. */ - if(darwinver_maj == 12 && darwinver_min <= 3 && - all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { - continue; - } -#endif /* CURL_BUILD_MAC */ - switch(all_ciphers[i]) { - /* Disable NULL ciphersuites: */ - case SSL_NULL_WITH_NULL_NULL: - case SSL_RSA_WITH_NULL_MD5: - case SSL_RSA_WITH_NULL_SHA: - case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ - case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ - case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ - case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ - case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ - case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ - case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ - case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ - case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ - case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ - case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ - case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ - case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ - /* Disable anonymous ciphersuites: */ - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - case SSL_DH_anon_WITH_RC4_128_MD5: - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_anon_WITH_DES_CBC_SHA: - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ - case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ - case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ - case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ - case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ - case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ - case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ - case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ - case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ - /* Disable weak key ciphersuites: */ - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_RSA_WITH_DES_CBC_SHA: - case SSL_DH_DSS_WITH_DES_CBC_SHA: - case SSL_DH_RSA_WITH_DES_CBC_SHA: - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - /* Disable IDEA: */ - case SSL_RSA_WITH_IDEA_CBC_SHA: - case SSL_RSA_WITH_IDEA_CBC_MD5: - /* Disable RC4: */ - case SSL_RSA_WITH_RC4_128_MD5: - case SSL_RSA_WITH_RC4_128_SHA: - case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ - case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ - case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ - case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ - case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ - case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ - case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ - break; - default: /* enable everything else */ - allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; - break; - } - } - err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers, - allowed_ciphers_count); - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); - if(err != noErr) { - failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); - return CURLE_SSL_CIPHER; - } - -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - /* We want to enable 1/n-1 when using a CBC cipher unless the user - specifically doesn't want us doing that: */ - if(SSLSetSessionOption != NULL) { - /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ - SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, - !data->set.ssl.enable_beast); - SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, - data->set.ssl.falsestart); /* false start support */ - } -#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ - - /* Check if there's a cached ID we can/should use here! */ - if(SSL_SET_OPTION(primary.sessionid)) { - char *ssl_sessionid; - size_t ssl_sessionid_len; - - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, - &ssl_sessionid_len, sockindex)) { - /* we got a session id, use it! */ - err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); - Curl_ssl_sessionid_unlock(conn); - if(err != noErr) { - failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } - /* Informational message */ - infof(data, "SSL re-using session ID\n"); - } - /* If there isn't one, then let's make one up! This has to be done prior - to starting the handshake. */ - else { - CURLcode result; - ssl_sessionid = - aprintf("%s:%d:%d:%s:%hu", ssl_cafile, - verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); - ssl_sessionid_len = strlen(ssl_sessionid); - - err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); - if(err != noErr) { - Curl_ssl_sessionid_unlock(conn); - failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } - - result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, - sockindex); - Curl_ssl_sessionid_unlock(conn); - if(result) { - failf(data, "failed to store ssl session"); - return result; - } - } - } - - err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite); - if(err != noErr) { - failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); - return CURLE_SSL_CONNECT_ERROR; - } - - /* pass the raw socket into the SSL layers */ - /* We need to store the FD in a constant memory address, because - * SSLSetConnection() will not copy that address. I've found that - * conn->sock[sockindex] may change on its own. */ - BACKEND->ssl_sockfd = sockfd; - err = SSLSetConnection(BACKEND->ssl_ctx, connssl); - if(err != noErr) { - failf(data, "SSL: SSLSetConnection() failed: %d", err); - return CURLE_SSL_CONNECT_ERROR; - } - - connssl->connecting_state = ssl_connect_2; - return CURLE_OK; -} - -static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) -{ - char *sep_start, *sep_end, *cert_start, *cert_end; - size_t i, j, err; - size_t len; - unsigned char *b64; - - /* Jump through the separators at the beginning of the certificate. */ - sep_start = strstr(in, "-----"); - if(sep_start == NULL) - return 0; - cert_start = strstr(sep_start + 1, "-----"); - if(cert_start == NULL) - return -1; - - cert_start += 5; - - /* Find separator after the end of the certificate. */ - cert_end = strstr(cert_start, "-----"); - if(cert_end == NULL) - return -1; - - sep_end = strstr(cert_end + 1, "-----"); - if(sep_end == NULL) - return -1; - sep_end += 5; - - len = cert_end - cert_start; - b64 = malloc(len + 1); - if(!b64) - return -1; - - /* Create base64 string without linefeeds. */ - for(i = 0, j = 0; i < len; i++) { - if(cert_start[i] != '\r' && cert_start[i] != '\n') - b64[j++] = cert_start[i]; - } - b64[j] = '\0'; - - err = Curl_base64_decode((const char *)b64, out, outlen); - free(b64); - if(err) { - free(*out); - return -1; - } - - return sep_end - in; -} - -static int read_cert(const char *file, unsigned char **out, size_t *outlen) -{ - int fd; - ssize_t n, len = 0, cap = 512; - unsigned char buf[512], *data; - - fd = open(file, 0); - if(fd < 0) - return -1; - - data = malloc(cap); - if(!data) { - close(fd); - return -1; - } - - for(;;) { - n = read(fd, buf, sizeof(buf)); - if(n < 0) { - close(fd); - free(data); - return -1; - } - else if(n == 0) { - close(fd); - break; - } - - if(len + n >= cap) { - cap *= 2; - data = Curl_saferealloc(data, cap); - if(!data) { - close(fd); - return -1; - } - } - - memcpy(data + len, buf, n); - len += n; - } - data[len] = '\0'; - - *out = data; - *outlen = len; - - return 0; -} - -static int append_cert_to_array(struct Curl_easy *data, - unsigned char *buf, size_t buflen, - CFMutableArrayRef array) -{ - CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); - char *certp; - CURLcode result; - if(!certdata) { - failf(data, "SSL: failed to allocate array for CA certificate"); - return CURLE_OUT_OF_MEMORY; - } - - SecCertificateRef cacert = - SecCertificateCreateWithData(kCFAllocatorDefault, certdata); - CFRelease(certdata); - if(!cacert) { - failf(data, "SSL: failed to create SecCertificate from CA certificate"); - return CURLE_SSL_CACERT_BADFILE; - } - - /* Check if cacert is valid. */ - result = CopyCertSubject(data, cacert, &certp); - switch(result) { - case CURLE_OK: - break; - case CURLE_PEER_FAILED_VERIFICATION: - return CURLE_SSL_CACERT_BADFILE; - case CURLE_OUT_OF_MEMORY: - default: - return result; - } - free(certp); - - CFArrayAppendValue(array, cacert); - CFRelease(cacert); - - return CURLE_OK; -} - -static int verify_cert(const char *cafile, struct Curl_easy *data, - SSLContextRef ctx) -{ - int n = 0, rc; - long res; - unsigned char *certbuf, *der; - size_t buflen, derlen, offset = 0; - - if(read_cert(cafile, &certbuf, &buflen) < 0) { - failf(data, "SSL: failed to read or invalid CA certificate"); - return CURLE_SSL_CACERT_BADFILE; - } - - /* - * Certbuf now contains the contents of the certificate file, which can be - * - a single DER certificate, - * - a single PEM certificate or - * - a bunch of PEM certificates (certificate bundle). - * - * Go through certbuf, and convert any PEM certificate in it into DER - * format. - */ - CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - if(array == NULL) { - free(certbuf); - failf(data, "SSL: out of memory creating CA certificate array"); - return CURLE_OUT_OF_MEMORY; - } - - while(offset < buflen) { - n++; - - /* - * Check if the certificate is in PEM format, and convert it to DER. If - * this fails, we assume the certificate is in DER format. - */ - res = pem_to_der((const char *)certbuf + offset, &der, &derlen); - if(res < 0) { - free(certbuf); - CFRelease(array); - failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", - n, offset); - return CURLE_SSL_CACERT_BADFILE; - } - offset += res; - - if(res == 0 && offset == 0) { - /* This is not a PEM file, probably a certificate in DER format. */ - rc = append_cert_to_array(data, certbuf, buflen, array); - free(certbuf); - if(rc != CURLE_OK) { - CFRelease(array); - return rc; - } - break; - } - else if(res == 0) { - /* No more certificates in the bundle. */ - free(certbuf); - break; - } - - rc = append_cert_to_array(data, der, derlen, array); - free(der); - if(rc != CURLE_OK) { - free(certbuf); - CFRelease(array); - return rc; - } - } - - SecTrustRef trust; - OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(trust == NULL) { - failf(data, "SSL: error getting certificate chain"); - CFRelease(array); - return CURLE_PEER_FAILED_VERIFICATION; - } - else if(ret != noErr) { - CFRelease(array); - failf(data, "SSLCopyPeerTrust() returned error %d", ret); - return CURLE_PEER_FAILED_VERIFICATION; - } - - ret = SecTrustSetAnchorCertificates(trust, array); - if(ret != noErr) { - CFRelease(array); - CFRelease(trust); - failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret); - return CURLE_PEER_FAILED_VERIFICATION; - } - ret = SecTrustSetAnchorCertificatesOnly(trust, true); - if(ret != noErr) { - CFRelease(array); - CFRelease(trust); - failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret); - return CURLE_PEER_FAILED_VERIFICATION; - } - - SecTrustResultType trust_eval = 0; - ret = SecTrustEvaluate(trust, &trust_eval); - CFRelease(array); - CFRelease(trust); - if(ret != noErr) { - failf(data, "SecTrustEvaluate() returned error %d", ret); - return CURLE_PEER_FAILED_VERIFICATION; - } - - switch(trust_eval) { - case kSecTrustResultUnspecified: - case kSecTrustResultProceed: - return CURLE_OK; - - case kSecTrustResultRecoverableTrustFailure: - case kSecTrustResultDeny: - default: - failf(data, "SSL: certificate verification failed (result: %d)", - trust_eval); - return CURLE_PEER_FAILED_VERIFICATION; - } -} - -#ifdef DARWIN_SSL_PINNEDPUBKEY -static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, - SSLContextRef ctx, - const char *pinnedpubkey) -{ /* Scratch */ - size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; - unsigned char *pubkey = NULL, *realpubkey = NULL; - const unsigned char *spkiHeader = NULL; - CFDataRef publicKeyBits = NULL; - - /* Result is returned to caller */ - CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - - /* if a path wasn't specified, don't pin */ - if(!pinnedpubkey) - return CURLE_OK; - - - if(!ctx) - return result; - - do { - SecTrustRef trust; - OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(ret != noErr || trust == NULL) - break; - - SecKeyRef keyRef = SecTrustCopyPublicKey(trust); - CFRelease(trust); - if(keyRef == NULL) - break; - -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 - - publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); - CFRelease(keyRef); - if(publicKeyBits == NULL) - break; - -#elif DARWIN_SSL_PINNEDPUBKEY_V2 - - OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, - &publicKeyBits); - CFRelease(keyRef); - if(success != errSecSuccess || publicKeyBits == NULL) - break; - -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ - - pubkeylen = CFDataGetLength(publicKeyBits); - pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); - - switch(pubkeylen) { - case 526: - /* 4096 bit RSA pubkeylen == 526 */ - spkiHeader = rsa4096SpkiHeader; - break; - case 270: - /* 2048 bit RSA pubkeylen == 270 */ - spkiHeader = rsa2048SpkiHeader; - break; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 - case 65: - /* ecDSA secp256r1 pubkeylen == 65 */ - spkiHeader = ecDsaSecp256r1SpkiHeader; - spkiHeaderLength = 26; - break; - case 97: - /* ecDSA secp384r1 pubkeylen == 97 */ - spkiHeader = ecDsaSecp384r1SpkiHeader; - spkiHeaderLength = 23; - break; - default: - infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); -#elif DARWIN_SSL_PINNEDPUBKEY_V2 - default: - /* ecDSA secp256r1 pubkeylen == 91 header already included? - * ecDSA secp384r1 header already included too - * we assume rest of algorithms do same, so do nothing - */ - result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, - pubkeylen); -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ - continue; /* break from loop */ - } - - realpubkeylen = pubkeylen + spkiHeaderLength; - realpubkey = malloc(realpubkeylen); - if(!realpubkey) - break; - - memcpy(realpubkey, spkiHeader, spkiHeaderLength); - memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); - - result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, - realpubkeylen); - - } while(0); - - Curl_safefree(realpubkey); - if(publicKeyBits != NULL) - CFRelease(publicKeyBits); - - return result; -} -#endif /* DARWIN_SSL_PINNEDPUBKEY */ - -static CURLcode -darwinssl_connect_step2(struct connectdata *conn, int sockindex) -{ - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - OSStatus err; - SSLCipherSuite cipher; - SSLProtocol protocol = 0; - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - - DEBUGASSERT(ssl_connect_2 == connssl->connecting_state - || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state); - - /* Here goes nothing: */ - err = SSLHandshake(BACKEND->ssl_ctx); - - if(err != noErr) { - switch(err) { - case errSSLWouldBlock: /* they're not done with us yet */ - connssl->connecting_state = BACKEND->ssl_direction ? - ssl_connect_2_writing : ssl_connect_2_reading; - return CURLE_OK; - - /* The below is errSSLServerAuthCompleted; it's not defined in - Leopard's headers */ - case -9841: - if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, - BACKEND->ssl_ctx); - if(res != CURLE_OK) - return res; - } - /* the documentation says we need to call SSLHandshake() again */ - return darwinssl_connect_step2(conn, sockindex); - - /* Problem with encrypt / decrypt */ - case errSSLPeerDecodeError: - failf(data, "Decode failed"); - break; - case errSSLDecryptionFail: - case errSSLPeerDecryptionFail: - failf(data, "Decryption failed"); - break; - case errSSLPeerDecryptError: - failf(data, "A decryption error occurred"); - break; - case errSSLBadCipherSuite: - failf(data, "A bad SSL cipher suite was encountered"); - break; - case errSSLCrypto: - failf(data, "An underlying cryptographic error was encountered"); - break; -#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 - case errSSLWeakPeerEphemeralDHKey: - failf(data, "Indicates a weak ephemeral Diffie-Hellman key"); - break; -#endif - - /* Problem with the message record validation */ - case errSSLBadRecordMac: - case errSSLPeerBadRecordMac: - failf(data, "A record with a bad message authentication code (MAC) " - "was encountered"); - break; - case errSSLRecordOverflow: - case errSSLPeerRecordOverflow: - failf(data, "A record overflow occurred"); - break; - - /* Problem with zlib decompression */ - case errSSLPeerDecompressFail: - failf(data, "Decompression failed"); - break; - - /* Problem with access */ - case errSSLPeerAccessDenied: - failf(data, "Access was denied"); - break; - case errSSLPeerInsufficientSecurity: - failf(data, "There is insufficient security for this operation"); - break; - - /* These are all certificate problems with the server: */ - case errSSLXCertChainInvalid: - failf(data, "SSL certificate problem: Invalid certificate chain"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLUnknownRootCert: - failf(data, "SSL certificate problem: Untrusted root certificate"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLNoRootCert: - failf(data, "SSL certificate problem: No root certificate"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLCertNotYetValid: - failf(data, "SSL certificate problem: The certificate chain had a " - "certificate that is not yet valid"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLCertExpired: - case errSSLPeerCertExpired: - failf(data, "SSL certificate problem: Certificate chain had an " - "expired certificate"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLBadCert: - case errSSLPeerBadCert: - failf(data, "SSL certificate problem: Couldn't understand the server " - "certificate format"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLPeerUnsupportedCert: - failf(data, "SSL certificate problem: An unsupported certificate " - "format was encountered"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLPeerCertRevoked: - failf(data, "SSL certificate problem: The certificate was revoked"); - return CURLE_PEER_FAILED_VERIFICATION; - case errSSLPeerCertUnknown: - failf(data, "SSL certificate problem: The certificate is unknown"); - return CURLE_PEER_FAILED_VERIFICATION; - - /* These are all certificate problems with the client: */ - case errSecAuthFailed: - failf(data, "SSL authentication failed"); - break; - case errSSLPeerHandshakeFail: - failf(data, "SSL peer handshake failed, the server most likely " - "requires a client certificate to connect"); - break; - case errSSLPeerUnknownCA: - failf(data, "SSL server rejected the client certificate due to " - "the certificate being signed by an unknown certificate " - "authority"); - break; - - /* This error is raised if the server's cert didn't match the server's - host name: */ - case errSSLHostNameMismatch: - failf(data, "SSL certificate peer verification failed, the " - "certificate did not match \"%s\"\n", conn->host.dispname); - return CURLE_PEER_FAILED_VERIFICATION; - - /* Problem with SSL / TLS negotiation */ - case errSSLNegotiation: - failf(data, "Could not negotiate an SSL cipher suite with the server"); - break; - case errSSLBadConfiguration: - failf(data, "A configuration error occurred"); - break; - case errSSLProtocol: - failf(data, "SSL protocol error"); - break; - case errSSLPeerProtocolVersion: - failf(data, "A bad protocol version was encountered"); - break; - case errSSLPeerNoRenegotiation: - failf(data, "No renegotiation is allowed"); - break; - - /* Generic handshake errors: */ - case errSSLConnectionRefused: - failf(data, "Server dropped the connection during the SSL handshake"); - break; - case errSSLClosedAbort: - failf(data, "Server aborted the SSL handshake"); - break; - case errSSLClosedGraceful: - failf(data, "The connection closed gracefully"); - break; - case errSSLClosedNoNotify: - failf(data, "The server closed the session with no notification"); - break; - /* Sometimes paramErr happens with buggy ciphers: */ - case paramErr: - case errSSLInternal: - case errSSLPeerInternalError: - failf(data, "Internal SSL engine error encountered during the " - "SSL handshake"); - break; - case errSSLFatalAlert: - failf(data, "Fatal SSL engine error encountered during the SSL " - "handshake"); - break; - /* Unclassified error */ - case errSSLBufferOverflow: - failf(data, "An insufficient buffer was provided"); - break; - case errSSLIllegalParam: - failf(data, "An illegal parameter was encountered"); - break; - case errSSLModuleAttach: - failf(data, "Module attach failure"); - break; - case errSSLSessionNotFound: - failf(data, "An attempt to restore an unknown session failed"); - break; - case errSSLPeerExportRestriction: - failf(data, "An export restriction occurred"); - break; - case errSSLPeerUserCancelled: - failf(data, "The user canceled the operation"); - break; - case errSSLPeerUnexpectedMsg: - failf(data, "Peer rejected unexpected message"); - break; -#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 - /* Treaing non-fatal error as fatal like before */ - case errSSLClientHelloReceived: - failf(data, "A non-fatal result for providing a server name " - "indication"); - break; -#endif - - /* Error codes defined in the enum but should never be returned. - We list them here just in case. */ -#if CURL_BUILD_MAC_10_6 - /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ - case errSSLClientCertRequested: - failf(data, "The server has requested a client certificate"); - break; -#endif -#if CURL_BUILD_MAC_10_9 - /* Alias for errSSLLast, end of error range */ - case errSSLUnexpectedRecord: - failf(data, "Unexpected (skipped) record in DTLS"); - break; -#endif - default: - /* May also return codes listed in Security Framework Result Codes */ - failf(data, "Unknown SSL protocol error in connection to %s:%d", - hostname, err); - break; - } - return CURLE_SSL_CONNECT_ERROR; - } - else { - /* we have been connected fine, we're not waiting for anything else. */ - connssl->connecting_state = ssl_connect_3; - -#ifdef DARWIN_SSL_PINNEDPUBKEY - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { - CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); - if(result) { - failf(data, "SSL: public key does not match pinned public key!"); - return result; - } - } -#endif /* DARWIN_SSL_PINNEDPUBKEY */ - - /* Informational message */ - (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); - (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol); - switch(protocol) { - case kSSLProtocol2: - infof(data, "SSL 2.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); - break; - case kSSLProtocol3: - infof(data, "SSL 3.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); - break; - case kTLSProtocol1: - infof(data, "TLS 1.0 connection using %s\n", - TLSCipherNameForNumber(cipher)); - break; -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - case kTLSProtocol11: - infof(data, "TLS 1.1 connection using %s\n", - TLSCipherNameForNumber(cipher)); - break; - case kTLSProtocol12: - infof(data, "TLS 1.2 connection using %s\n", - TLSCipherNameForNumber(cipher)); - break; -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 - case kTLSProtocol13: - infof(data, "TLS 1.3 connection using %s\n", - TLSCipherNameForNumber(cipher)); - break; -#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ - default: - infof(data, "Unknown protocol connection\n"); - break; - } - -#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 - if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { - CFArrayRef alpnArr = NULL; - CFStringRef chosenProtocol = NULL; - err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); - - if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) - chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); - -#ifdef USE_NGHTTP2 - if(chosenProtocol && - !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), - 0)) { - conn->negnpn = CURL_HTTP_VERSION_2; - } - else -#endif - if(chosenProtocol && - !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) { - conn->negnpn = CURL_HTTP_VERSION_1_1; - } - else - infof(data, "ALPN, server did not agree to a protocol\n"); - - /* chosenProtocol is a reference to the string within alpnArr - and doesn't need to be freed separately */ - if(alpnArr) - CFRelease(alpnArr); - } - } -#endif - - return CURLE_OK; - } -} - -#ifndef CURL_DISABLE_VERBOSE_STRINGS -/* This should be called during step3 of the connection at the earliest */ -static void -show_verbose_server_cert(struct connectdata *conn, - int sockindex) -{ - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - CFArrayRef server_certs = NULL; - SecCertificateRef server_cert; - OSStatus err; - CFIndex i, count; - SecTrustRef trust = NULL; - - if(!BACKEND->ssl_ctx) - return; - -#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS -#if CURL_BUILD_IOS -#pragma unused(server_certs) - err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); - /* For some reason, SSLCopyPeerTrust() can return noErr and yet return - a null trust, so be on guard for that: */ - if(err == noErr && trust) { - count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; - server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } - } - CFRelease(trust); - } -#else - /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. - The function SecTrustGetCertificateAtIndex() is officially present - in Lion, but it is unfortunately also present in Snow Leopard as - private API and doesn't work as expected. So we have to look for - a different symbol to make sure this code is only executed under - Lion or later. */ - if(SecTrustEvaluateAsync != NULL) { -#pragma unused(server_certs) - err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); - /* For some reason, SSLCopyPeerTrust() can return noErr and yet return - a null trust, so be on guard for that: */ - if(err == noErr && trust) { - count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; - server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } - } - CFRelease(trust); - } - } - else { -#if CURL_SUPPORT_MAC_10_8 - err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); - /* Just in case SSLCopyPeerCertificates() returns null too... */ - if(err == noErr && server_certs) { - count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; - server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, - i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } - } - CFRelease(server_certs); - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#endif /* CURL_BUILD_IOS */ -#else -#pragma unused(trust) - err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); - if(err == noErr) { - count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; - server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } - } - CFRelease(server_certs); - } -#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ -} -#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ - -static CURLcode -darwinssl_connect_step3(struct connectdata *conn, - int sockindex) -{ - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - /* There is no step 3! - * Well, okay, if verbose mode is on, let's print the details of the - * server certificates. */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - if(data->set.verbose) - show_verbose_server_cert(conn, sockindex); -#endif - - connssl->connecting_state = ssl_connect_done; - return CURLE_OK; -} - -static Curl_recv darwinssl_recv; -static Curl_send darwinssl_send; - -static CURLcode -darwinssl_connect_common(struct connectdata *conn, - int sockindex, - bool nonblocking, - bool *done) -{ - CURLcode result; - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; - int what; - - /* check if the connection has already been established */ - if(ssl_connection_complete == connssl->state) { - *done = TRUE; - return CURLE_OK; - } - - if(ssl_connect_1 == connssl->connecting_state) { - /* Find out how much more time we're allowed */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - result = darwinssl_connect_step1(conn, sockindex); - if(result) - return result; - } - - while(ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state) { - - /* check allowed time left */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* if ssl is expecting something, check if it's available. */ - if(connssl->connecting_state == ssl_connect_2_reading || - connssl->connecting_state == ssl_connect_2_writing) { - - curl_socket_t writefd = ssl_connect_2_writing == - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading == - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - - what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, - nonblocking?0:timeout_ms); - if(what < 0) { - /* fatal error */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - return CURLE_SSL_CONNECT_ERROR; - } - else if(0 == what) { - if(nonblocking) { - *done = FALSE; - return CURLE_OK; - } - else { - /* timeout */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - } - /* socket is readable or writable */ - } - - /* Run transaction, and return to the caller if it failed or if this - * connection is done nonblocking and this loop would execute again. This - * permits the owner of a multi handle to abort a connection attempt - * before step2 has completed while ensuring that a client using select() - * or epoll() will always have a valid fdset to wait on. - */ - result = darwinssl_connect_step2(conn, sockindex); - if(result || (nonblocking && - (ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state))) - return result; - - } /* repeat step2 until all transactions are done. */ - - - if(ssl_connect_3 == connssl->connecting_state) { - result = darwinssl_connect_step3(conn, sockindex); - if(result) - return result; - } - - if(ssl_connect_done == connssl->connecting_state) { - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = darwinssl_recv; - conn->send[sockindex] = darwinssl_send; - *done = TRUE; - } - else - *done = FALSE; - - /* Reset our connect state machine */ - connssl->connecting_state = ssl_connect_1; - - return CURLE_OK; -} - -static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) -{ - return darwinssl_connect_common(conn, sockindex, TRUE, done); -} - -static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex) -{ - CURLcode result; - bool done = FALSE; - - result = darwinssl_connect_common(conn, sockindex, FALSE, &done); - - if(result) - return result; - - DEBUGASSERT(done); - - return CURLE_OK; -} - -static void Curl_darwinssl_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(BACKEND->ssl_ctx) { - (void)SSLClose(BACKEND->ssl_ctx); -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - if(SSLCreateContext != NULL) - CFRelease(BACKEND->ssl_ctx); -#if CURL_SUPPORT_MAC_10_8 - else - (void)SSLDisposeContext(BACKEND->ssl_ctx); -#endif /* CURL_SUPPORT_MAC_10_8 */ -#else - (void)SSLDisposeContext(BACKEND->ssl_ctx); -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - BACKEND->ssl_ctx = NULL; - } - BACKEND->ssl_sockfd = 0; -} - -static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; - ssize_t nread; - int what; - int rc; - char buf[120]; - - if(!BACKEND->ssl_ctx) - return 0; - - if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) - return 0; - - Curl_darwinssl_close(conn, sockindex); - - rc = 0; - - what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); - - for(;;) { - if(what < 0) { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - rc = -1; - break; - } - - if(!what) { /* timeout */ - failf(data, "SSL shutdown timeout"); - break; - } - - /* Something to read, let's do it and hope that it is the close - notify alert from the server. No way to SSL_Read now, so use read(). */ - - nread = read(conn->sock[sockindex], buf, sizeof(buf)); - - if(nread < 0) { - failf(data, "read: %s", strerror(errno)); - rc = -1; - } - - if(nread <= 0) - break; - - what = SOCKET_READABLE(conn->sock[sockindex], 0); - } - - return rc; -} - -static void Curl_darwinssl_session_free(void *ptr) -{ - /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a - cached session ID inside the Security framework. There is a private - function that does this, but I don't want to have to explain to you why I - got your application rejected from the App Store due to the use of a - private API, so the best we can do is free up our own char array that we - created way back in darwinssl_connect_step1... */ - Curl_safefree(ptr); -} - -static size_t Curl_darwinssl_version(char *buffer, size_t size) -{ - return msnprintf(buffer, size, "SecureTransport"); -} - -/* - * This function uses SSLGetSessionState to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -static int Curl_darwinssl_check_cxn(struct connectdata *conn) -{ - struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; - OSStatus err; - SSLSessionState state; - - if(BACKEND->ssl_ctx) { - err = SSLGetSessionState(BACKEND->ssl_ctx, &state); - if(err == noErr) - return state == kSSLConnected || state == kSSLHandshake; - return -1; - } - return 0; -} - -static bool Curl_darwinssl_data_pending(const struct connectdata *conn, - int connindex) -{ - const struct ssl_connect_data *connssl = &conn->ssl[connindex]; - OSStatus err; - size_t buffer; - - if(BACKEND->ssl_ctx) { /* SSL is in use */ - err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer); - if(err == noErr) - return buffer > 0UL; - return false; - } - else - return false; -} - -static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM, - unsigned char *entropy, size_t length) -{ - /* arc4random_buf() isn't available on cats older than Lion, so let's - do this manually for the benefit of the older cats. */ - size_t i; - u_int32_t random_number = 0; - - (void)data; - - for(i = 0 ; i < length ; i++) { - if(i % sizeof(u_int32_t) == 0) - random_number = arc4random(); - entropy[i] = random_number & 0xFF; - random_number >>= 8; - } - i = random_number = 0; - return CURLE_OK; -} - -static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ - (void)md5len; - (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); - return CURLE_OK; -} - -static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) -{ - assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); - (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); - return CURLE_OK; -} - -static bool Curl_darwinssl_false_start(void) -{ -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - if(SSLSetSessionOption != NULL) - return TRUE; -#endif - return FALSE; -} - -static ssize_t darwinssl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) -{ - /*struct Curl_easy *data = conn->data;*/ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - size_t processed = 0UL; - OSStatus err; - - /* The SSLWrite() function works a little differently than expected. The - fourth argument (processed) is currently documented in Apple's - documentation as: "On return, the length, in bytes, of the data actually - written." - - Now, one could interpret that as "written to the socket," but actually, - it returns the amount of data that was written to a buffer internal to - the SSLContextRef instead. So it's possible for SSLWrite() to return - errSSLWouldBlock and a number of bytes "written" because those bytes were - encrypted and written to a buffer, not to the socket. - - So if this happens, then we need to keep calling SSLWrite() over and - over again with no new data until it quits returning errSSLWouldBlock. */ - - /* Do we have buffered data to write from the last time we were called? */ - if(BACKEND->ssl_write_buffered_length) { - /* Write the buffered data: */ - err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed); - switch(err) { - case noErr: - /* processed is always going to be 0 because we didn't write to - the buffer, so return how much was written to the socket */ - processed = BACKEND->ssl_write_buffered_length; - BACKEND->ssl_write_buffered_length = 0UL; - break; - case errSSLWouldBlock: /* argh, try again */ - *curlcode = CURLE_AGAIN; - return -1L; - default: - failf(conn->data, "SSLWrite() returned error %d", err); - *curlcode = CURLE_SEND_ERROR; - return -1L; - } - } - else { - /* We've got new data to write: */ - err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed); - if(err != noErr) { - switch(err) { - case errSSLWouldBlock: - /* Data was buffered but not sent, we have to tell the caller - to try sending again, and remember how much was buffered */ - BACKEND->ssl_write_buffered_length = len; - *curlcode = CURLE_AGAIN; - return -1L; - default: - failf(conn->data, "SSLWrite() returned error %d", err); - *curlcode = CURLE_SEND_ERROR; - return -1L; - } - } - } - return (ssize_t)processed; -} - -static ssize_t darwinssl_recv(struct connectdata *conn, - int num, - char *buf, - size_t buffersize, - CURLcode *curlcode) -{ - /*struct Curl_easy *data = conn->data;*/ - struct ssl_connect_data *connssl = &conn->ssl[num]; - size_t processed = 0UL; - OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed); - - if(err != noErr) { - switch(err) { - case errSSLWouldBlock: /* return how much we read (if anything) */ - if(processed) - return (ssize_t)processed; - *curlcode = CURLE_AGAIN; - return -1L; - break; - - /* errSSLClosedGraceful - server gracefully shut down the SSL session - errSSLClosedNoNotify - server hung up on us instead of sending a - closure alert notice, read() is returning 0 - Either way, inform the caller that the server disconnected. */ - case errSSLClosedGraceful: - case errSSLClosedNoNotify: - *curlcode = CURLE_OK; - return -1L; - break; - - default: - failf(conn->data, "SSLRead() return error %d", err); - *curlcode = CURLE_RECV_ERROR; - return -1L; - break; - } - } - return (ssize_t)processed; -} - -static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) -{ - (void)info; - return BACKEND->ssl_ctx; -} - -const struct Curl_ssl Curl_ssl_darwinssl = { - { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */ - -#ifdef DARWIN_SSL_PINNEDPUBKEY - SSLSUPP_PINNEDPUBKEY, -#else - 0, -#endif /* DARWIN_SSL_PINNEDPUBKEY */ - - sizeof(struct ssl_backend_data), - - Curl_none_init, /* init */ - Curl_none_cleanup, /* cleanup */ - Curl_darwinssl_version, /* version */ - Curl_darwinssl_check_cxn, /* check_cxn */ - Curl_darwinssl_shutdown, /* shutdown */ - Curl_darwinssl_data_pending, /* data_pending */ - Curl_darwinssl_random, /* random */ - Curl_none_cert_status_request, /* cert_status_request */ - Curl_darwinssl_connect, /* connect */ - Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */ - Curl_darwinssl_get_internals, /* get_internals */ - Curl_darwinssl_close, /* close_one */ - Curl_none_close_all, /* close_all */ - Curl_darwinssl_session_free, /* session_free */ - Curl_none_set_engine, /* set_engine */ - Curl_none_set_engine_default, /* set_engine_default */ - Curl_none_engines_list, /* engines_list */ - Curl_darwinssl_false_start, /* false_start */ - Curl_darwinssl_md5sum, /* md5sum */ - Curl_darwinssl_sha256sum /* sha256sum */ -}; - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif /* USE_DARWINSSL */ diff --git a/libs/libcurl/src/vtls/darwinssl.h b/libs/libcurl/src/vtls/darwinssl.h deleted file mode 100644 index 23c7f705cb..0000000000 --- a/libs/libcurl/src/vtls/darwinssl.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef HEADER_CURL_DARWINSSL_H -#define HEADER_CURL_DARWINSSL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2012 - 2014, Nick Zitzmann, . - * Copyright (C) 2012 - 2017, Daniel Stenberg, , 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_DARWINSSL - -extern const struct Curl_ssl Curl_ssl_darwinssl; - -#endif /* USE_DARWINSSL */ -#endif /* HEADER_CURL_DARWINSSL_H */ diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index 9035ec483e..e224861c45 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1423,11 +1423,6 @@ gtls_connect_step3(struct connectdata *conn, size = sizeof(certbuf); gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); infof(data, "\t issuer: %s\n", certbuf); - - /* compression algorithm (if any) */ - ptr = gnutls_compression_get_name(gnutls_compression_get(session)); - /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ - infof(data, "\t compression: %s\n", ptr); #endif gnutls_x509_crt_deinit(x509_cert); diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index bb6a757bf2..27a9402cbc 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -716,6 +716,8 @@ mbed_connect_step3(struct connectdata *conn, ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); if(ret) { + if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) + mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; @@ -729,6 +731,7 @@ mbed_connect_step3(struct connectdata *conn, retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { + mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); failf(data, "failed to store ssl session"); return retcode; @@ -813,9 +816,14 @@ static void Curl_mbedtls_session_free(void *ptr) static size_t Curl_mbedtls_version(char *buffer, size_t size) { +#ifdef MBEDTLS_VERSION_C + /* if mbedtls_version_get_number() is available it is better */ unsigned int version = mbedtls_version_get_number(); return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, (version>>16)&0xff, (version>>8)&0xff); +#else + return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); +#endif } static CURLcode Curl_mbedtls_random(struct Curl_easy *data, diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 9d11b89e59..eff5c2106c 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -65,6 +65,10 @@ #include #include +#ifdef USE_AMISSL +#include "amigaos.h" +#endif + #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) #include #endif @@ -820,8 +824,11 @@ int cert_stuff(struct connectdata *conn, fail: EVP_PKEY_free(pri); X509_free(x509); +#ifdef USE_AMISSL + sk_X509_pop_free(ca, Curl_amiga_X509_free); +#else sk_X509_pop_free(ca, X509_free); - +#endif if(!cert_done) return 0; /* failure! */ break; @@ -831,15 +838,15 @@ int cert_stuff(struct connectdata *conn, return 0; } - file_type = do_file_type(key_type); + if(!key_file) + key_file = cert_file; + else + file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(cert_done) break; - if(!key_file) - /* cert & key can only be in PEM case in the same file */ - key_file = cert_file; /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { @@ -2808,6 +2815,12 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } +#ifdef SSL_ERROR_WANT_ASYNC + if(SSL_ERROR_WANT_ASYNC == detail) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } +#endif else { /* untreated error */ unsigned long errdetail; diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index c8574f56c1..39ac080e80 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -323,6 +323,9 @@ get_alg_id_by_name(char *name) #endif #ifdef CALG_ECDSA CIPHEROPTION(CALG_ECDSA); +#endif +#ifdef CALG_ECDH_EPHEM + CIPHEROPTION(CALG_ECDH_EPHEM); #endif return 0; } @@ -433,8 +436,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + hostname, conn->remote_port)); if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, VERSION_LESS_THAN_EQUAL)) { @@ -494,12 +498,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; - infof(data, "schannel: re-using existing credential handle\n"); + DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); /* increment the reference counter of the credential/session handle */ BACKEND->cred->refcount++; - infof(data, "schannel: incremented credential handle refcount = %d\n", - BACKEND->cred->refcount); + DEBUGF(infof(data, + "schannel: incremented credential handle refcount = %d\n", + BACKEND->cred->refcount)); } Curl_ssl_sessionid_unlock(conn); } @@ -522,26 +527,28 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation " - "checks\n"); + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks\n")); } else { schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - infof(data, "schannel: checking server certificate revocation\n"); + DEBUGF(infof(data, + "schannel: checking server certificate revocation\n")); } } else { schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation checks\n"); + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks\n")); } if(!conn->ssl_config.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates.\n"); + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.\n")); } switch(conn->ssl_config.version) { @@ -680,8 +687,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) CertFreeCertificateContext(client_certs[0]); if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: AcquireCredentialsHandle failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); Curl_safefree(BACKEND->cred); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: @@ -796,15 +804,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_unicodefree(host_name); if(sspi_status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; Curl_safefree(BACKEND->ctxt); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -819,13 +828,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } - infof(data, "schannel: sending initial handshake data: " - "sending %lu bytes...\n", outbuf.cbBuffer); + DEBUGF(infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer)); /* send initial handshake data which is now stored in output buffer */ result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, @@ -837,8 +846,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - infof(data, "schannel: sent initial handshake data: " - "sent %zd bytes\n", written); + DEBUGF(infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written)); BACKEND->recv_unrecoverable_err = CURLE_OK; BACKEND->recv_sspi_close_notify = false; @@ -874,8 +883,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred || !BACKEND->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -934,8 +944,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(result == CURLE_AGAIN) { if(connssl->connecting_state != ssl_connect_2_writing) connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: failed to receive handshake, " - "need more data\n"); + DEBUGF(infof(data, "schannel: failed to receive handshake, " + "need more data\n")); return CURLE_OK; } else if((result != CURLE_OK) || (nread == 0)) { @@ -947,11 +957,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* increase encrypted data buffer offset */ BACKEND->encdata_offset += nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* setup input buffers */ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), @@ -994,7 +1005,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { BACKEND->encdata_is_incomplete = true; connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: received incomplete message, need more data\n"); + DEBUGF(infof(data, + "schannel: received incomplete message, need more data\n")); return CURLE_OK; } @@ -1005,7 +1017,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; connssl->connecting_state = ssl_connect_2_writing; - infof(data, "schannel: a client certificate has been requested\n"); + DEBUGF(infof(data, + "schannel: a client certificate has been requested\n")); return CURLE_OK; } @@ -1014,8 +1027,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) for(i = 0; i < 3; i++) { /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { - infof(data, "schannel: sending next handshake data: " - "sending %lu bytes...\n", outbuf[i].cbBuffer); + DEBUGF(infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer)); /* send handshake token to server */ result = Curl_write_plain(conn, conn->sock[sockindex], @@ -1036,14 +1049,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) } } else { + char buffer[STRERROR_LEN]; switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -1058,14 +1072,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } /* check if there was additional remaining encrypted data */ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* There are two cases where we could be getting extra data here: 1) If we're renegotiating a connection and the handshake is already @@ -1104,7 +1119,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* check if the handshake is complete */ if(sspi_status == SEC_E_OK) { connssl->connecting_state = ssl_connect_3; - infof(data, "schannel: SSL/TLS handshake complete\n"); + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } pubkey_ptr = SSL_IS_PROXY() ? @@ -1190,7 +1205,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; -#ifndef CURL_DISABLE_VERBOSE_STRINGS +#ifdef DEBUGBUILD const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; #endif @@ -1200,8 +1215,9 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred) return CURLE_SSL_CONNECT_ERROR; @@ -1266,7 +1282,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) sockindex)); if(incache) { if(old_cred != BACKEND->cred) { - infof(data, "schannel: old credential handle is stale, removing\n"); + DEBUGF(infof(data, + "schannel: old credential handle is stale, removing\n")); /* we're not taking old_cred ownership here, no refcount++ is needed */ Curl_ssl_delsessionid(conn, (void *)old_cred); incache = FALSE; @@ -1284,7 +1301,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) else { /* this cred session is now also referenced by sessionid cache */ BACKEND->cred->refcount++; - infof(data, "schannel: stored credential handle in session cache\n"); + DEBUGF(infof(data, + "schannel: stored credential handle in session cache\n")); } } Curl_ssl_sessionid_unlock(conn); @@ -1615,7 +1633,7 @@ schannel_recv(struct connectdata *conn, int sockindex, * handled in the cleanup. */ - infof(data, "schannel: client wants to read %zu bytes\n", len); + DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); *err = CURLE_OK; if(len && len <= BACKEND->decdata_offset) { @@ -1660,12 +1678,13 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_buffer = reallocated_buffer; BACKEND->encdata_length = reallocated_length; size = BACKEND->encdata_length - BACKEND->encdata_offset; - infof(data, "schannel: encdata_buffer resized %zu\n", - BACKEND->encdata_length); + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + BACKEND->encdata_length)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* read encrypted data from socket */ *err = Curl_read_plain(conn->sock[sockindex], @@ -1675,7 +1694,8 @@ schannel_recv(struct connectdata *conn, int sockindex, if(*err) { nread = -1; if(*err == CURLE_AGAIN) - infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n"); + DEBUGF(infof(data, + "schannel: Curl_read_plain returned CURLE_AGAIN\n")); else if(*err == CURLE_RECV_ERROR) infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); else @@ -1683,17 +1703,18 @@ schannel_recv(struct connectdata *conn, int sockindex, } else if(nread == 0) { BACKEND->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); + DEBUGF(infof(data, "schannel: server closed the connection\n")); } else if(nread > 0) { BACKEND->encdata_offset += (size_t)nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* decrypt loop */ while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && @@ -1721,8 +1742,8 @@ schannel_recv(struct connectdata *conn, int sockindex, /* check for successfully decrypted data, even before actual renegotiation or shutdown of the connection context */ if(inbuf[1].BufferType == SECBUFFER_DATA) { - infof(data, "schannel: decrypted data length: %lu\n", - inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* increase buffer in order to fit the received amount of data */ size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? @@ -1754,15 +1775,16 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->decdata_offset += size; } - infof(data, "schannel: decrypted data added: %zu\n", size); - infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted cached: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); } /* check for remaining encrypted data */ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", - inbuf[3].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer)); /* check if the remaining data is less than the total amount * and therefore begins after the already processed data @@ -1776,8 +1798,9 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_offset = inbuf[3].cbBuffer; } - infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted cached: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); } else { /* reset encrypted buffer offset, because there is no data remaining */ @@ -1831,22 +1854,25 @@ schannel_recv(struct connectdata *conn, int sockindex, goto cleanup; } else { + char buffer[STRERROR_LEN]; *err = CURLE_RECV_ERROR; infof(data, "schannel: failed to read data from server: %s\n", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); goto cleanup; } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); cleanup: /* Warning- there is no guarantee the encdata state is valid at this point */ - infof(data, "schannel: schannel_recv cleanup\n"); + DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); /* Error if the connection has closed without a close_notify. Behavior here is a matter of debate. We don't want to be vulnerable to a @@ -1879,10 +1905,10 @@ cleanup: memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, BACKEND->decdata_offset - size); BACKEND->decdata_offset -= size; - - infof(data, "schannel: decrypted data returned %zu\n", size); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); *err = CURLE_OK; return (ssize_t)size; } @@ -1960,6 +1986,8 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + DEBUGASSERT(data); + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", hostname, conn->remote_port); @@ -1979,9 +2007,11 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, &BuffDesc); - if(sspi_status != SEC_E_OK) + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: ApplyControlToken failure: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + } host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) @@ -2023,7 +2053,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) /* free SSPI Schannel API security context handle */ if(BACKEND->ctxt) { - infof(data, "schannel: clear security context handle\n"); + DEBUGF(infof(data, "schannel: clear security context handle\n")); s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); Curl_safefree(BACKEND->ctxt); } @@ -2035,11 +2065,9 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) * might not have an associated transfer so the check for conn->data is * necessary. */ - if(conn->data) - Curl_ssl_sessionid_lock(conn); + Curl_ssl_sessionid_lock(conn); Curl_schannel_session_free(BACKEND->cred); - if(conn->data) - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(conn); BACKEND->cred = NULL; } @@ -2101,7 +2129,7 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, const char *pinnedpubkey) { - SECURITY_STATUS status; + SECURITY_STATUS sspi_status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CERT_CONTEXT *pCertContextServer = NULL; @@ -2118,13 +2146,15 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, return CURLE_OK; do { - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); break; /* failed */ } diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index 680f6ec5d6..5a09e969e8 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -96,9 +96,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); if(!ca_file_tstr) { + char buffer[STRERROR_LEN]; failf(data, "schannel: invalid path name for CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -116,17 +117,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, FILE_ATTRIBUTE_NORMAL, NULL); if(ca_file_handle == INVALID_HANDLE_VALUE) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to open CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } if(!GetFileSizeEx(ca_file_handle, &file_size)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to determine size of CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -153,10 +156,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to read from CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -215,11 +218,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL, NULL, (const void **)&cert_context)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to extract certificate from CA file " "'%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -243,10 +247,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL); CertFreeCertificateContext(cert_context); if(!add_cert_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to add certificate from CA file '%s' " "to certificate store: %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -408,7 +414,7 @@ cleanup: CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) { - SECURITY_STATUS status; + SECURITY_STATUS sspi_status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result = CURLE_OK; @@ -420,13 +426,15 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) conn->http_proxy.host.name : conn->host.name; - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; } @@ -450,8 +458,9 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CERT_STORE_CREATE_NEW_FLAG, NULL); if(!trust_store) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate store: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } else { @@ -477,9 +486,10 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CertCreateCertificateChainEngine( (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); if(!create_engine_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate chain engine: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } } @@ -500,8 +510,9 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: CertGetCertificateChain failed: %s", - Curl_sspi_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); pChainContext = NULL; result = CURLE_PEER_FAILED_VERIFICATION; } diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c new file mode 100644 index 0000000000..971dd78e6a --- /dev/null +++ b/libs/libcurl/src/vtls/sectransp.c @@ -0,0 +1,3259 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2017, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , 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. + * + ***************************************************************************/ + +/* + * Source file for all iOS and macOS SecureTransport-specific code for the + * TLS/SSL layer. No code but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#include "urldata.h" /* for the Curl_easy definition */ +#include "curl_base64.h" +#include "strtok.h" + +#ifdef USE_SECTRANSP + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#endif /* __clang__ */ + +#include + +#include +/* For some reason, when building for iOS, the omnibus header above does + * not include SecureTransport.h as of iOS SDK 5.1. */ +#include +#include +#include + +/* The Security framework has changed greatly between iOS and different macOS + versions, and we will try to support as many of them as we can (back to + Leopard and iOS 5) by using macros and weak-linking. + + In general, you want to build this using the most recent OS SDK, since some + features require curl to be built against the latest SDK. TLS 1.1 and 1.2 + support, for instance, require the macOS 10.8 SDK or later. TLS 1.3 + requires the macOS 10.13 or iOS 11 SDK or later. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error "The Secure Transport back-end requires Leopard or later." +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ + +#define CURL_BUILD_IOS 0 +#define CURL_BUILD_IOS_7 0 +#define CURL_BUILD_IOS_9 0 +#define CURL_BUILD_IOS_11 0 +#define CURL_BUILD_MAC 1 +/* This is the maximum API level we are allowed to use when building: */ +#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 +#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 +#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +/* These macros mean "the following code is present to allow runtime backward + compatibility with at least this cat or earlier": + (You set this at build-time using the compiler command line option + "-mmacos-version-min.") */ +#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 +#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 +#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 +#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 +#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 + +#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE +#define CURL_BUILD_IOS 1 +#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 +#define CURL_BUILD_MAC 0 +#define CURL_BUILD_MAC_10_5 0 +#define CURL_BUILD_MAC_10_6 0 +#define CURL_BUILD_MAC_10_7 0 +#define CURL_BUILD_MAC_10_8 0 +#define CURL_BUILD_MAC_10_9 0 +#define CURL_BUILD_MAC_10_11 0 +#define CURL_BUILD_MAC_10_13 0 +#define CURL_SUPPORT_MAC_10_5 0 +#define CURL_SUPPORT_MAC_10_6 0 +#define CURL_SUPPORT_MAC_10_7 0 +#define CURL_SUPPORT_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_9 0 + +#else +#error "The Secure Transport back-end requires iOS or macOS." +#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ + +#if CURL_BUILD_MAC +#include +#endif /* CURL_BUILD_MAC */ + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "vtls.h" +#include "sectransp.h" +#include "curl_printf.h" +#include "strdup.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* From MacTypes.h (which we can't include because it isn't present in iOS: */ +#define ioErr -36 +#define paramErr -50 + +struct ssl_backend_data { + SSLContextRef ssl_ctx; + curl_socket_t ssl_sockfd; + bool ssl_direction; /* true if writing, false if reading */ + size_t ssl_write_buffered_length; +}; + +#define BACKEND connssl->backend + +/* pinned public key support tests */ + +/* version 1 supports macOS 10.12+ and iOS 10+ */ +#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ + (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) +#define SECTRANSP_PINNEDPUBKEY_V1 1 +#endif + +/* version 2 supports MacOSX 10.7+ */ +#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define SECTRANSP_PINNEDPUBKEY_V2 1 +#endif + +#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define SECTRANSP_PINNEDPUBKEY 1 +#endif /* SECTRANSP_PINNEDPUBKEY */ + +#ifdef SECTRANSP_PINNEDPUBKEY +/* both new and old APIs return rsa keys missing the spki header (not DER) */ +static const unsigned char rsa4096SpkiHeader[] = { + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; + +static const unsigned char rsa2048SpkiHeader[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 +/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ +static const unsigned char ecDsaSecp256r1SpkiHeader[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00}; + +static const unsigned char ecDsaSecp384r1SpkiHeader[] = { + 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, + 0x00, 0x22, 0x03, 0x62, 0x00}; +#endif /* SECTRANSP_PINNEDPUBKEY_V1 */ +#endif /* SECTRANSP_PINNEDPUBKEY */ + +/* The following two functions were ripped from Apple sample code, + * with some modifications: */ +static OSStatus SocketRead(SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + OSStatus rtn = noErr; + size_t bytesRead; + ssize_t rrtn; + int theErr; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + rrtn = read(sock, currData, bytesToGo); + if(rrtn <= 0) { + /* this is guesswork... */ + theErr = errno; + if(rrtn == 0) { /* EOF = server hung up */ + /* the framework will turn this into errSSLClosedNoNotify */ + rtn = errSSLClosedGraceful; + } + else /* do the switch */ + switch(theErr) { + case ENOENT: + /* connection closed */ + rtn = errSSLClosedGraceful; + break; + case ECONNRESET: + rtn = errSSLClosedAbort; + break; + case EAGAIN: + rtn = errSSLWouldBlock; + BACKEND->ssl_direction = false; + break; + default: + rtn = ioErr; + break; + } + break; + } + else { + bytesRead = rrtn; + } + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + + return rtn; +} + +static OSStatus SocketWrite(SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + ssize_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + int theErr; + + *dataLength = 0; + + do { + length = write(sock, + (char *)dataPtr + bytesSent, + dataLen - bytesSent); + } while((length > 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + theErr = errno; + if(theErr == EAGAIN) { + ortn = errSSLWouldBlock; + BACKEND->ssl_direction = true; + } + else { + ortn = ioErr; + } + } + else { + ortn = noErr; + } + *dataLength = bytesSent; + return ortn; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* SSL version 3.0 */ + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + break; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + break; + /* TLS 1.0 with AES (RFC 3268) + (Apparently these are used in SSLv3 implementations as well.) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; + /* SSL version 2.0 */ + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + break; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + break; + } + return "SSL_NULL_WITH_NULL_NULL"; +} + +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* TLS 1.0 with AES (RFC 3268) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* TLS 1.0 with ECDSA (RFC 4492) */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + break; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 (RFC 5246) */ + case TLS_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case TLS_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case TLS_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_WITH_NULL_SHA256: + return "TLS_RSA_WITH_NULL_SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + break; + /* TLS 1.2 with AES GCM (RFC 5288) */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: + return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + break; + /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; + break; +#else + case SSL_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* TLS PSK (RFC 4279): */ + case TLS_PSK_WITH_RC4_128_SHA: + return "TLS_PSK_WITH_RC4_128_SHA"; + break; + case TLS_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + return "TLS_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_RC4_128_SHA: + return "TLS_DHE_PSK_WITH_RC4_128_SHA"; + break; + case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_RC4_128_SHA: + return "TLS_RSA_PSK_WITH_RC4_128_SHA"; + break; + case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; + break; + /* More TLS PSK (RFC 4785): */ + case TLS_PSK_WITH_NULL_SHA: + return "TLS_PSK_WITH_NULL_SHA"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA: + return "TLS_DHE_PSK_WITH_NULL_SHA"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA: + return "TLS_RSA_PSK_WITH_NULL_SHA"; + break; + /* Even more TLS PSK (RFC 5487): */ + case TLS_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_PSK_WITH_NULL_SHA256: + return "TLS_PSK_WITH_NULL_SHA256"; + break; + case TLS_PSK_WITH_NULL_SHA384: + return "TLS_PSK_WITH_NULL_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA256: + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA256: + return "TLS_RSA_PSK_WITH_NULL_SHA256"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ + case TLS_AES_128_GCM_SHA256: + return "TLS_AES_128_GCM_SHA256"; + break; + case TLS_AES_256_GCM_SHA384: + return "TLS_AES_256_GCM_SHA384"; + break; + case TLS_CHACHA20_POLY1305_SHA256: + return "TLS_CHACHA20_POLY1305_SHA256"; + break; + case TLS_AES_128_CCM_SHA256: + return "TLS_AES_128_CCM_SHA256"; + break; + case TLS_AES_128_CCM_8_SHA256: + return "TLS_AES_128_CCM_8_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + } + return "TLS_NULL_WITH_NULL_NULL"; +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +#if CURL_BUILD_MAC +CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) +{ + int mib[2]; + char *os_version; + size_t os_version_len; + char *os_version_major, *os_version_minor; + char *tok_buf; + + /* Get the Darwin kernel version from the kernel using sysctl(): */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) + return; + os_version = malloc(os_version_len*sizeof(char)); + if(!os_version) + return; + if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { + free(os_version); + return; + } + + /* Parse the version: */ + os_version_major = strtok_r(os_version, ".", &tok_buf); + os_version_minor = strtok_r(NULL, ".", &tok_buf); + *major = atoi(os_version_major); + *minor = atoi(os_version_minor); + free(os_version); +} +#endif /* CURL_BUILD_MAC */ + +/* Apple provides a myriad of ways of getting information about a certificate + into a string. Some aren't available under iOS or newer cats. So here's + a unified function for getting a string describing the certificate that + ought to work in all cats starting with Leopard. */ +CF_INLINE CFStringRef getsubject(SecCertificateRef cert) +{ + CFStringRef server_cert_summary = CFSTR("(null)"); + +#if CURL_BUILD_IOS + /* iOS: There's only one way to do this. */ + server_cert_summary = SecCertificateCopySubjectSummary(cert); +#else +#if CURL_BUILD_MAC_10_7 + /* Lion & later: Get the long description if we can. */ + if(SecCertificateCopyLongDescription != NULL) + server_cert_summary = + SecCertificateCopyLongDescription(NULL, cert, NULL); + else +#endif /* CURL_BUILD_MAC_10_7 */ +#if CURL_BUILD_MAC_10_6 + /* Snow Leopard: Get the certificate summary. */ + if(SecCertificateCopySubjectSummary != NULL) + server_cert_summary = SecCertificateCopySubjectSummary(cert); + else +#endif /* CURL_BUILD_MAC_10_6 */ + /* Leopard is as far back as we go... */ + (void)SecCertificateCopyCommonName(cert, &server_cert_summary); +#endif /* CURL_BUILD_IOS */ + return server_cert_summary; +} + +static CURLcode CopyCertSubject(struct Curl_easy *data, + SecCertificateRef cert, char **certp) +{ + CFStringRef c = getsubject(cert); + CURLcode result = CURLE_OK; + const char *direct; + char *cbuf = NULL; + *certp = NULL; + + if(!c) { + failf(data, "SSL: invalid CA certificate subject"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* If the subject is already available as UTF-8 encoded (ie 'direct') then + use that, else convert it. */ + direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8); + if(direct) { + *certp = strdup(direct); + if(!*certp) { + failf(data, "SSL: out of memory"); + result = CURLE_OUT_OF_MEMORY; + } + } + else { + size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; + cbuf = calloc(cbuf_size, 1); + if(cbuf) { + if(!CFStringGetCString(c, cbuf, cbuf_size, + kCFStringEncodingUTF8)) { + failf(data, "SSL: invalid CA certificate subject"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + /* pass back the buffer */ + *certp = cbuf; + } + else { + failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size); + result = CURLE_OUT_OF_MEMORY; + } + } + if(result) + free(cbuf); + CFRelease(c); + return result; +} + +#if CURL_SUPPORT_MAC_10_6 +/* The SecKeychainSearch API was deprecated in Lion, and using it will raise + deprecation warnings, so let's not compile this unless it's necessary: */ +static OSStatus CopyIdentityWithLabelOldSchool(char *label, + SecIdentityRef *out_c_a_k) +{ + OSStatus status = errSecItemNotFound; + SecKeychainAttributeList attr_list; + SecKeychainAttribute attr; + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + + /* Set up the attribute list: */ + attr_list.count = 1L; + attr_list.attr = &attr; + + /* Set up our lone search criterion: */ + attr.tag = kSecLabelItemAttr; + attr.data = label; + attr.length = (UInt32)strlen(label); + + /* Start searching: */ + status = SecKeychainSearchCreateFromAttributes(NULL, + kSecCertificateItemClass, + &attr_list, + &search); + if(status == noErr) { + status = SecKeychainSearchCopyNext(search, + (SecKeychainItemRef *)&cert); + if(status == noErr && cert) { + /* If we found a certificate, does it have a private key? */ + status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); + CFRelease(cert); + } + } + + if(search) + CFRelease(search); + return status; +} +#endif /* CURL_SUPPORT_MAC_10_6 */ + +static OSStatus CopyIdentityWithLabel(char *label, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; + + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. + kSecClassIdentity was introduced in Lion. If both exist, let's use them + to find the certificate. */ + if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { + CFTypeRef keys[5]; + CFTypeRef values[5]; + CFDictionaryRef query_dict; + CFStringRef label_cf = CFStringCreateWithCString(NULL, label, + kCFStringEncodingUTF8); + + /* Set up our search criteria and expected results: */ + values[0] = kSecClassIdentity; /* we want a certificate and a key */ + keys[0] = kSecClass; + values[1] = kCFBooleanTrue; /* we want a reference */ + keys[1] = kSecReturnRef; + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ + keys[2] = kSecMatchLimit; + /* identity searches need a SecPolicyRef in order to work */ + values[3] = SecPolicyCreateSSL(false, NULL); + keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; + query_dict = CFDictionaryCreate(NULL, (const void **)keys, + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[3]); + + /* Do we have a match? */ + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + status = 1; + for(i = 0; idata; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long max_supported_version_by_os; + + /* macOS 10.5-10.7 supported TLS 1.0 only. + macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2. + macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */ +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3; + } + else { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; + } +#else + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = max_supported_version_by_os; + break; + } + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + SSLProtocol darwin_ver_min = kTLSProtocol1; + SSLProtocol darwin_ver_max = kTLSProtocol1; + CURLcode result = sectransp_version_from_curl(&darwin_ver_min, + ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = sectransp_version_from_curl(&darwin_ver_max, + ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max); + return result; + } + else { +#if CURL_SUPPORT_MAC_10_8 + long i = ssl_version; + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + for(; i <= (ssl_version_max >> 16); i++) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + failf(data, "Secure Transport: cannot set SSL protocol"); + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode sectransp_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) { /* use the newer API if available */ + if(BACKEND->ssl_ctx) + CFRelease(BACKEND->ssl_ctx); + BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!BACKEND->ssl_ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + } + else { + /* The old ST API does not exist under iOS, so don't compile it: */ +#if CURL_SUPPORT_MAC_10_8 + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + + /* check to see if we've been told to use an explicit SSL/TLS version */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13); + } + else { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); + } +#else + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { + failf(data, "Your version of the OS does not support to set maximum" + " SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks); + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr); + if(err != noErr) + infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", + err); + CFRelease(alpnArr); + } + } +#endif + + if(SSL_SET_OPTION(key)) { + infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " + "Transport. The private key must be in the Keychain.\n"); + } + + if(ssl_cert) { + SecIdentityRef cert_and_key = NULL; + bool is_cert_file = is_file(ssl_cert); + + /* User wants to authenticate with a client cert. Look for it: + If we detect that this is a file on disk, then let's load it. + Otherwise, assume that the user wants to use an identity loaded + from the Keychain. */ + if(is_cert_file) { + if(!SSL_SET_OPTION(cert_type)) + infof(data, "WARNING: SSL: Certificate type not set, assuming " + "PKCS#12 format.\n"); + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) + infof(data, "WARNING: SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format.\n"); + + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); + } + else + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); + + if(err == noErr && cert_and_key) { + SecCertificateRef cert = NULL; + CFTypeRef certs_c[1]; + CFArrayRef certs; + + /* If we found one, print it out: */ + err = SecIdentityCopyCertificate(cert_and_key, &cert); + if(err == noErr) { + char *certp; + CURLcode result = CopyCertSubject(data, cert, &certp); + if(!result) { + infof(data, "Client certificate: %s\n", certp); + free(certp); + } + + CFRelease(cert); + if(result == CURLE_PEER_FAILED_VERIFICATION) + return CURLE_SSL_CERTPROBLEM; + if(result) + return result; + } + certs_c[0] = cert_and_key; + certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, + &kCFTypeArrayCallBacks); + err = SSLSetCertificate(BACKEND->ssl_ctx, certs); + if(certs) + CFRelease(certs); + if(err != noErr) { + failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); + return CURLE_SSL_CERTPROBLEM; + } + CFRelease(cert_and_key); + } + else { + switch(err) { + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; + } + return CURLE_SSL_CERTPROBLEM; + } + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* Snow Leopard introduced the SSLSetSessionOption() function, but due to + a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag + works, it doesn't work as expected under Snow Leopard, Lion or + Mountain Lion. + So we need to call SSLSetEnableCertVerify() on those older cats in order + to disable certificate validation if the user turned that off. + (SecureTransport will always validate the certificate chain by + default.) + Note: + Darwin 11.x.x is Lion (10.7) + Darwin 12.x.x is Mountain Lion (10.8) + Darwin 13.x.x is Mavericks (10.9) + Darwin 14.x.x is Yosemite (10.10) + Darwin 15.x.x is El Capitan (10.11) + */ +#if CURL_BUILD_MAC + if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { +#else + if(SSLSetSessionOption != NULL) { +#endif /* CURL_BUILD_MAC */ + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; + err = SSLSetSessionOption(BACKEND->ssl_ctx, + kSSLSessionOptionBreakOnServerAuth, + break_on_auth); + if(err != noErr) { + failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + + if(ssl_cafile && verifypeer) { + bool is_cert_file = is_file(ssl_cafile); + + if(!is_cert_file) { + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Configure hostname check. SNI is used if available. + * Both hostname check and SNI require SSLSetPeerDomainName(). + * Also: the verifyhost setting influences SNI usage */ + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname, + strlen(hostname)); + + if(err != noErr) { + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + err); + } + + if((Curl_inet_pton(AF_INET, hostname, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, hostname, &addr)) + #endif + ) { + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); + } + } + else { + infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + } + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", + err); + return CURLE_SSL_CIPHER; + } + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!all_ciphers) { + failf(data, "SSL: Failed to allocate memory for all ciphers"); + return CURLE_OUT_OF_MEMORY; + } + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!allowed_ciphers) { + Curl_safefree(all_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers, + &all_ciphers_count); + if(err != noErr) { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + return CURLE_SSL_CIPHER; + } + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + switch(all_ciphers[i]) { + /* Disable NULL ciphersuites: */ + case SSL_NULL_WITH_NULL_NULL: + case SSL_RSA_WITH_NULL_MD5: + case SSL_RSA_WITH_NULL_SHA: + case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ + case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ + case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ + case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ + case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ + case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ + case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ + case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ + case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ + case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ + /* Disable anonymous ciphersuites: */ + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + case SSL_DH_anon_WITH_RC4_128_MD5: + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_anon_WITH_DES_CBC_SHA: + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ + case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ + case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ + case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ + case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ + /* Disable weak key ciphersuites: */ + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_RSA_WITH_DES_CBC_SHA: + case SSL_DH_DSS_WITH_DES_CBC_SHA: + case SSL_DH_RSA_WITH_DES_CBC_SHA: + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + /* Disable IDEA: */ + case SSL_RSA_WITH_IDEA_CBC_SHA: + case SSL_RSA_WITH_IDEA_CBC_MD5: + /* Disable RC4: */ + case SSL_RSA_WITH_RC4_128_MD5: + case SSL_RSA_WITH_RC4_128_SHA: + case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ + case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ + case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ + case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ + case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ + case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ + break; + default: /* enable everything else */ + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + break; + } + } + err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* We want to enable 1/n-1 when using a CBC cipher unless the user + specifically doesn't want us doing that: */ + if(SSLSetSessionOption != NULL) { + /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + !data->set.ssl.enable_beast); + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, + data->set.ssl.falsestart); /* false start support */ + } +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + char *ssl_sessionid; + size_t ssl_sessionid_len; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + &ssl_sessionid_len, sockindex)) { + /* we got a session id, use it! */ + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + Curl_ssl_sessionid_unlock(conn); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + /* If there isn't one, then let's make one up! This has to be done prior + to starting the handshake. */ + else { + CURLcode result; + ssl_sessionid = + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); + ssl_sessionid_len = strlen(ssl_sessionid); + + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + } + + err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite); + if(err != noErr) { + failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* pass the raw socket into the SSL layers */ + /* We need to store the FD in a constant memory address, because + * SSLSetConnection() will not copy that address. I've found that + * conn->sock[sockindex] may change on its own. */ + BACKEND->ssl_sockfd = sockfd; + err = SSLSetConnection(BACKEND->ssl_ctx, connssl); + if(err != noErr) { + failf(data, "SSL: SSLSetConnection() failed: %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) +{ + char *sep_start, *sep_end, *cert_start, *cert_end; + size_t i, j, err; + size_t len; + unsigned char *b64; + + /* Jump through the separators at the beginning of the certificate. */ + sep_start = strstr(in, "-----"); + if(sep_start == NULL) + return 0; + cert_start = strstr(sep_start + 1, "-----"); + if(cert_start == NULL) + return -1; + + cert_start += 5; + + /* Find separator after the end of the certificate. */ + cert_end = strstr(cert_start, "-----"); + if(cert_end == NULL) + return -1; + + sep_end = strstr(cert_end + 1, "-----"); + if(sep_end == NULL) + return -1; + sep_end += 5; + + len = cert_end - cert_start; + b64 = malloc(len + 1); + if(!b64) + return -1; + + /* Create base64 string without linefeeds. */ + for(i = 0, j = 0; i < len; i++) { + if(cert_start[i] != '\r' && cert_start[i] != '\n') + b64[j++] = cert_start[i]; + } + b64[j] = '\0'; + + err = Curl_base64_decode((const char *)b64, out, outlen); + free(b64); + if(err) { + free(*out); + return -1; + } + + return sep_end - in; +} + +static int read_cert(const char *file, unsigned char **out, size_t *outlen) +{ + int fd; + ssize_t n, len = 0, cap = 512; + unsigned char buf[512], *data; + + fd = open(file, 0); + if(fd < 0) + return -1; + + data = malloc(cap); + if(!data) { + close(fd); + return -1; + } + + for(;;) { + n = read(fd, buf, sizeof(buf)); + if(n < 0) { + close(fd); + free(data); + return -1; + } + else if(n == 0) { + close(fd); + break; + } + + if(len + n >= cap) { + cap *= 2; + data = Curl_saferealloc(data, cap); + if(!data) { + close(fd); + return -1; + } + } + + memcpy(data + len, buf, n); + len += n; + } + data[len] = '\0'; + + *out = data; + *outlen = len; + + return 0; +} + +static int append_cert_to_array(struct Curl_easy *data, + unsigned char *buf, size_t buflen, + CFMutableArrayRef array) +{ + CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); + char *certp; + CURLcode result; + if(!certdata) { + failf(data, "SSL: failed to allocate array for CA certificate"); + return CURLE_OUT_OF_MEMORY; + } + + SecCertificateRef cacert = + SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + CFRelease(certdata); + if(!cacert) { + failf(data, "SSL: failed to create SecCertificate from CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* Check if cacert is valid. */ + result = CopyCertSubject(data, cacert, &certp); + switch(result) { + case CURLE_OK: + break; + case CURLE_PEER_FAILED_VERIFICATION: + return CURLE_SSL_CACERT_BADFILE; + case CURLE_OUT_OF_MEMORY: + default: + return result; + } + free(certp); + + CFArrayAppendValue(array, cacert); + CFRelease(cacert); + + return CURLE_OK; +} + +static int verify_cert(const char *cafile, struct Curl_easy *data, + SSLContextRef ctx) +{ + int n = 0, rc; + long res; + unsigned char *certbuf, *der; + size_t buflen, derlen, offset = 0; + + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* + * Certbuf now contains the contents of the certificate file, which can be + * - a single DER certificate, + * - a single PEM certificate or + * - a bunch of PEM certificates (certificate bundle). + * + * Go through certbuf, and convert any PEM certificate in it into DER + * format. + */ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + if(array == NULL) { + free(certbuf); + failf(data, "SSL: out of memory creating CA certificate array"); + return CURLE_OUT_OF_MEMORY; + } + + while(offset < buflen) { + n++; + + /* + * Check if the certificate is in PEM format, and convert it to DER. If + * this fails, we assume the certificate is in DER format. + */ + res = pem_to_der((const char *)certbuf + offset, &der, &derlen); + if(res < 0) { + free(certbuf); + CFRelease(array); + failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", + n, offset); + return CURLE_SSL_CACERT_BADFILE; + } + offset += res; + + if(res == 0 && offset == 0) { + /* This is not a PEM file, probably a certificate in DER format. */ + rc = append_cert_to_array(data, certbuf, buflen, array); + free(certbuf); + if(rc != CURLE_OK) { + CFRelease(array); + return rc; + } + break; + } + else if(res == 0) { + /* No more certificates in the bundle. */ + free(certbuf); + break; + } + + rc = append_cert_to_array(data, der, derlen, array); + free(der); + if(rc != CURLE_OK) { + free(certbuf); + CFRelease(array); + return rc; + } + } + + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(trust == NULL) { + failf(data, "SSL: error getting certificate chain"); + CFRelease(array); + return CURLE_PEER_FAILED_VERIFICATION; + } + else if(ret != noErr) { + CFRelease(array); + failf(data, "SSLCopyPeerTrust() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + ret = SecTrustSetAnchorCertificates(trust, array); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + ret = SecTrustSetAnchorCertificatesOnly(trust, true); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + SecTrustResultType trust_eval = 0; + ret = SecTrustEvaluate(trust, &trust_eval); + CFRelease(array); + CFRelease(trust); + if(ret != noErr) { + failf(data, "SecTrustEvaluate() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + switch(trust_eval) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + return CURLE_OK; + + case kSecTrustResultRecoverableTrustFailure: + case kSecTrustResultDeny: + default: + failf(data, "SSL: certificate verification failed (result: %d)", + trust_eval); + return CURLE_PEER_FAILED_VERIFICATION; + } +} + +#ifdef SECTRANSP_PINNEDPUBKEY +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + SSLContextRef ctx, + const char *pinnedpubkey) +{ /* Scratch */ + size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; + unsigned char *pubkey = NULL, *realpubkey = NULL; + const unsigned char *spkiHeader = NULL; + CFDataRef publicKeyBits = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + + if(!ctx) + return result; + + do { + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(ret != noErr || trust == NULL) + break; + + SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + CFRelease(trust); + if(keyRef == NULL) + break; + +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + + publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); + CFRelease(keyRef); + if(publicKeyBits == NULL) + break; + +#elif SECTRANSP_PINNEDPUBKEY_V2 + + OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); + CFRelease(keyRef); + if(success != errSecSuccess || publicKeyBits == NULL) + break; + +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + + pubkeylen = CFDataGetLength(publicKeyBits); + pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); + + switch(pubkeylen) { + case 526: + /* 4096 bit RSA pubkeylen == 526 */ + spkiHeader = rsa4096SpkiHeader; + break; + case 270: + /* 2048 bit RSA pubkeylen == 270 */ + spkiHeader = rsa2048SpkiHeader; + break; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + case 65: + /* ecDSA secp256r1 pubkeylen == 65 */ + spkiHeader = ecDsaSecp256r1SpkiHeader; + spkiHeaderLength = 26; + break; + case 97: + /* ecDSA secp384r1 pubkeylen == 97 */ + spkiHeader = ecDsaSecp384r1SpkiHeader; + spkiHeaderLength = 23; + break; + default: + infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); +#elif SECTRANSP_PINNEDPUBKEY_V2 + default: + /* ecDSA secp256r1 pubkeylen == 91 header already included? + * ecDSA secp384r1 header already included too + * we assume rest of algorithms do same, so do nothing + */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, + pubkeylen); +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + continue; /* break from loop */ + } + + realpubkeylen = pubkeylen + spkiHeaderLength; + realpubkey = malloc(realpubkeylen); + if(!realpubkey) + break; + + memcpy(realpubkey, spkiHeader, spkiHeaderLength); + memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); + + result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, + realpubkeylen); + + } while(0); + + Curl_safefree(realpubkey); + if(publicKeyBits != NULL) + CFRelease(publicKeyBits); + + return result; +} +#endif /* SECTRANSP_PINNEDPUBKEY */ + +static CURLcode +sectransp_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + OSStatus err; + SSLCipherSuite cipher; + SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + /* Here goes nothing: */ + err = SSLHandshake(BACKEND->ssl_ctx); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* they're not done with us yet */ + connssl->connecting_state = BACKEND->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; + return CURLE_OK; + + /* The below is errSSLServerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, + BACKEND->ssl_ctx); + if(res != CURLE_OK) + return res; + } + /* the documentation says we need to call SSLHandshake() again */ + return sectransp_connect_step2(conn, sockindex); + + /* Problem with encrypt / decrypt */ + case errSSLPeerDecodeError: + failf(data, "Decode failed"); + break; + case errSSLDecryptionFail: + case errSSLPeerDecryptionFail: + failf(data, "Decryption failed"); + break; + case errSSLPeerDecryptError: + failf(data, "A decryption error occurred"); + break; + case errSSLBadCipherSuite: + failf(data, "A bad SSL cipher suite was encountered"); + break; + case errSSLCrypto: + failf(data, "An underlying cryptographic error was encountered"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + case errSSLWeakPeerEphemeralDHKey: + failf(data, "Indicates a weak ephemeral Diffie-Hellman key"); + break; +#endif + + /* Problem with the message record validation */ + case errSSLBadRecordMac: + case errSSLPeerBadRecordMac: + failf(data, "A record with a bad message authentication code (MAC) " + "was encountered"); + break; + case errSSLRecordOverflow: + case errSSLPeerRecordOverflow: + failf(data, "A record overflow occurred"); + break; + + /* Problem with zlib decompression */ + case errSSLPeerDecompressFail: + failf(data, "Decompression failed"); + break; + + /* Problem with access */ + case errSSLPeerAccessDenied: + failf(data, "Access was denied"); + break; + case errSSLPeerInsufficientSecurity: + failf(data, "There is insufficient security for this operation"); + break; + + /* These are all certificate problems with the server: */ + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertNotYetValid: + failf(data, "SSL certificate problem: The certificate chain had a " + "certificate that is not yet valid"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertExpired: + case errSSLPeerCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLBadCert: + case errSSLPeerBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerUnsupportedCert: + failf(data, "SSL certificate problem: An unsupported certificate " + "format was encountered"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertRevoked: + failf(data, "SSL certificate problem: The certificate was revoked"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertUnknown: + failf(data, "SSL certificate problem: The certificate is unknown"); + return CURLE_PEER_FAILED_VERIFICATION; + + /* These are all certificate problems with the client: */ + case errSecAuthFailed: + failf(data, "SSL authentication failed"); + break; + case errSSLPeerHandshakeFail: + failf(data, "SSL peer handshake failed, the server most likely " + "requires a client certificate to connect"); + break; + case errSSLPeerUnknownCA: + failf(data, "SSL server rejected the client certificate due to " + "the certificate being signed by an unknown certificate " + "authority"); + break; + + /* This error is raised if the server's cert didn't match the server's + host name: */ + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer verification failed, the " + "certificate did not match \"%s\"\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + + /* Problem with SSL / TLS negotiation */ + case errSSLNegotiation: + failf(data, "Could not negotiate an SSL cipher suite with the server"); + break; + case errSSLBadConfiguration: + failf(data, "A configuration error occurred"); + break; + case errSSLProtocol: + failf(data, "SSL protocol error"); + break; + case errSSLPeerProtocolVersion: + failf(data, "A bad protocol version was encountered"); + break; + case errSSLPeerNoRenegotiation: + failf(data, "No renegotiation is allowed"); + break; + + /* Generic handshake errors: */ + case errSSLConnectionRefused: + failf(data, "Server dropped the connection during the SSL handshake"); + break; + case errSSLClosedAbort: + failf(data, "Server aborted the SSL handshake"); + break; + case errSSLClosedGraceful: + failf(data, "The connection closed gracefully"); + break; + case errSSLClosedNoNotify: + failf(data, "The server closed the session with no notification"); + break; + /* Sometimes paramErr happens with buggy ciphers: */ + case paramErr: + case errSSLInternal: + case errSSLPeerInternalError: + failf(data, "Internal SSL engine error encountered during the " + "SSL handshake"); + break; + case errSSLFatalAlert: + failf(data, "Fatal SSL engine error encountered during the SSL " + "handshake"); + break; + /* Unclassified error */ + case errSSLBufferOverflow: + failf(data, "An insufficient buffer was provided"); + break; + case errSSLIllegalParam: + failf(data, "An illegal parameter was encountered"); + break; + case errSSLModuleAttach: + failf(data, "Module attach failure"); + break; + case errSSLSessionNotFound: + failf(data, "An attempt to restore an unknown session failed"); + break; + case errSSLPeerExportRestriction: + failf(data, "An export restriction occurred"); + break; + case errSSLPeerUserCancelled: + failf(data, "The user canceled the operation"); + break; + case errSSLPeerUnexpectedMsg: + failf(data, "Peer rejected unexpected message"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + /* Treaing non-fatal error as fatal like before */ + case errSSLClientHelloReceived: + failf(data, "A non-fatal result for providing a server name " + "indication"); + break; +#endif + + /* Error codes defined in the enum but should never be returned. + We list them here just in case. */ +#if CURL_BUILD_MAC_10_6 + /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ + case errSSLClientCertRequested: + failf(data, "The server has requested a client certificate"); + break; +#endif +#if CURL_BUILD_MAC_10_9 + /* Alias for errSSLLast, end of error range */ + case errSSLUnexpectedRecord: + failf(data, "Unexpected (skipped) record in DTLS"); + break; +#endif + default: + /* May also return codes listed in Security Framework Result Codes */ + failf(data, "Unknown SSL protocol error in connection to %s:%d", + hostname, err); + break; + } + return CURLE_SSL_CONNECT_ERROR; + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + +#ifdef SECTRANSP_PINNEDPUBKEY + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { + CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } +#endif /* SECTRANSP_PINNEDPUBKEY */ + + /* Informational message */ + (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol); + switch(protocol) { + case kSSLProtocol2: + infof(data, "SSL 2.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kSSLProtocol3: + infof(data, "SSL 3.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kTLSProtocol1: + infof(data, "TLS 1.0 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + case kTLSProtocol11: + infof(data, "TLS 1.1 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; + case kTLSProtocol12: + infof(data, "TLS 1.2 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + case kTLSProtocol13: + infof(data, "TLS 1.3 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + default: + infof(data, "Unknown protocol connection\n"); + break; + } + +#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFArrayRef alpnArr = NULL; + CFStringRef chosenProtocol = NULL; + err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); + + if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) + chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); + +#ifdef USE_NGHTTP2 + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), + 0)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + /* chosenProtocol is a reference to the string within alpnArr + and doesn't need to be freed separately */ + if(alpnArr) + CFRelease(alpnArr); + } + } +#endif + + return CURLE_OK; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* This should be called during step3 of the connection at the earliest */ +static void +show_verbose_server_cert(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CFArrayRef server_certs = NULL; + SecCertificateRef server_cert; + OSStatus err; + CFIndex i, count; + SecTrustRef trust = NULL; + + if(!BACKEND->ssl_ctx) + return; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS +#if CURL_BUILD_IOS +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } +#else + /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. + The function SecTrustGetCertificateAtIndex() is officially present + in Lion, but it is unfortunately also present in Snow Leopard as + private API and doesn't work as expected. So we have to look for + a different symbol to make sure this code is only executed under + Lion or later. */ + if(SecTrustEvaluateAsync != NULL) { +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + /* Just in case SSLCopyPeerCertificates() returns null too... */ + if(err == noErr && server_certs) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, + i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_IOS */ +#else +#pragma unused(trust) + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + if(err == noErr) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +static CURLcode +sectransp_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) + show_verbose_server_cert(conn, sockindex); +#endif + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + +static Curl_recv sectransp_recv; +static Curl_send sectransp_send; + +static CURLcode +sectransp_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = sectransp_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = sectransp_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + + if(ssl_connect_3 == connssl->connecting_state) { + result = sectransp_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = sectransp_recv; + conn->send[sockindex] = sectransp_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return sectransp_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = sectransp_connect_common(conn, sockindex, FALSE, &done); + + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static void Curl_sectransp_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->ssl_ctx) { + (void)SSLClose(BACKEND->ssl_ctx); +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) + CFRelease(BACKEND->ssl_ctx); +#if CURL_SUPPORT_MAC_10_8 + else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_SUPPORT_MAC_10_8 */ +#else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_ctx = NULL; + } + BACKEND->ssl_sockfd = 0; +} + +static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!BACKEND->ssl_ctx) + return 0; + + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; + + Curl_sectransp_close(conn, sockindex); + + rc = 0; + + what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to SSL_Read now, so use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + +static void Curl_sectransp_session_free(void *ptr) +{ + /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a + cached session ID inside the Security framework. There is a private + function that does this, but I don't want to have to explain to you why I + got your application rejected from the App Store due to the use of a + private API, so the best we can do is free up our own char array that we + created way back in sectransp_connect_step1... */ + Curl_safefree(ptr); +} + +static size_t Curl_sectransp_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "SecureTransport"); +} + +/* + * This function uses SSLGetSessionState to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_sectransp_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + OSStatus err; + SSLSessionState state; + + if(BACKEND->ssl_ctx) { + err = SSLGetSessionState(BACKEND->ssl_ctx, &state); + if(err == noErr) + return state == kSSLConnected || state == kSSLHandshake; + return -1; + } + return 0; +} + +static bool Curl_sectransp_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + OSStatus err; + size_t buffer; + + if(BACKEND->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer); + if(err == noErr) + return buffer > 0UL; + return false; + } + else + return false; +} + +static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) +{ + /* arc4random_buf() isn't available on cats older than Lion, so let's + do this manually for the benefit of the older cats. */ + size_t i; + u_int32_t random_number = 0; + + (void)data; + + for(i = 0 ; i < length ; i++) { + if(i % sizeof(u_int32_t) == 0) + random_number = arc4random(); + entropy[i] = random_number & 0xFF; + random_number >>= 8; + } + i = random_number = 0; + return CURLE_OK; +} + +static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + (void)md5len; + (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); + return CURLE_OK; +} + +static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); + (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); + return CURLE_OK; +} + +static bool Curl_sectransp_false_start(void) +{ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + if(SSLSetSessionOption != NULL) + return TRUE; +#endif + return FALSE; +} + +static ssize_t sectransp_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + size_t processed = 0UL; + OSStatus err; + + /* The SSLWrite() function works a little differently than expected. The + fourth argument (processed) is currently documented in Apple's + documentation as: "On return, the length, in bytes, of the data actually + written." + + Now, one could interpret that as "written to the socket," but actually, + it returns the amount of data that was written to a buffer internal to + the SSLContextRef instead. So it's possible for SSLWrite() to return + errSSLWouldBlock and a number of bytes "written" because those bytes were + encrypted and written to a buffer, not to the socket. + + So if this happens, then we need to keep calling SSLWrite() over and + over again with no new data until it quits returning errSSLWouldBlock. */ + + /* Do we have buffered data to write from the last time we were called? */ + if(BACKEND->ssl_write_buffered_length) { + /* Write the buffered data: */ + err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed); + switch(err) { + case noErr: + /* processed is always going to be 0 because we didn't write to + the buffer, so return how much was written to the socket */ + processed = BACKEND->ssl_write_buffered_length; + BACKEND->ssl_write_buffered_length = 0UL; + break; + case errSSLWouldBlock: /* argh, try again */ + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + else { + /* We've got new data to write: */ + err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed); + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: + /* Data was buffered but not sent, we have to tell the caller + to try sending again, and remember how much was buffered */ + BACKEND->ssl_write_buffered_length = len; + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + } + return (ssize_t)processed; +} + +static ssize_t sectransp_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[num]; + size_t processed = 0UL; + OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* return how much we read (if anything) */ + if(processed) + return (ssize_t)processed; + *curlcode = CURLE_AGAIN; + return -1L; + break; + + /* errSSLClosedGraceful - server gracefully shut down the SSL session + errSSLClosedNoNotify - server hung up on us instead of sending a + closure alert notice, read() is returning 0 + Either way, inform the caller that the server disconnected. */ + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + *curlcode = CURLE_OK; + return -1L; + break; + + default: + failf(conn->data, "SSLRead() return error %d", err); + *curlcode = CURLE_RECV_ERROR; + return -1L; + break; + } + } + return (ssize_t)processed; +} + +static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->ssl_ctx; +} + +const struct Curl_ssl Curl_ssl_sectransp = { + { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ + +#ifdef SECTRANSP_PINNEDPUBKEY + SSLSUPP_PINNEDPUBKEY, +#else + 0, +#endif /* SECTRANSP_PINNEDPUBKEY */ + + sizeof(struct ssl_backend_data), + + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_sectransp_version, /* version */ + Curl_sectransp_check_cxn, /* check_cxn */ + Curl_sectransp_shutdown, /* shutdown */ + Curl_sectransp_data_pending, /* data_pending */ + Curl_sectransp_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_sectransp_connect, /* connect */ + Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_sectransp_get_internals, /* get_internals */ + Curl_sectransp_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_sectransp_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_sectransp_false_start, /* false_start */ + Curl_sectransp_md5sum, /* md5sum */ + Curl_sectransp_sha256sum /* sha256sum */ +}; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* USE_SECTRANSP */ diff --git a/libs/libcurl/src/vtls/sectransp.h b/libs/libcurl/src/vtls/sectransp.h new file mode 100644 index 0000000000..5cec797b33 --- /dev/null +++ b/libs/libcurl/src/vtls/sectransp.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , 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_SECTRANSP + +extern const struct Curl_ssl Curl_ssl_sectransp; + +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index 5e75f92e99..8a405c05cd 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -248,7 +248,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex) conn->ssl[sockindex].use = TRUE; conn->ssl[sockindex].state = ssl_connection_negotiating; - result = Curl_ssl->connect(conn, sockindex); + result = Curl_ssl->connect_blocking(conn, sockindex); if(!result) Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ @@ -513,7 +513,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) } #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ defined(USE_MBEDTLS) || defined(USE_CYASSL) int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -546,7 +546,7 @@ int Curl_ssl_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */ +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ #endif void Curl_ssl_close(struct connectdata *conn, int sockindex) @@ -557,7 +557,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex) CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) { - if(Curl_ssl->shutdown(conn, sockindex)) + if(Curl_ssl->shut_down(conn, sockindex)) return CURLE_SSL_SHUTDOWN_FAILED; conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ @@ -1114,7 +1114,7 @@ static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) { if(multissl_init(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->connect(conn, sockindex); + return Curl_ssl->connect_blocking(conn, sockindex); } static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, @@ -1172,8 +1172,8 @@ const struct Curl_ssl *Curl_ssl = &Curl_ssl_multi; #elif defined(USE_CYASSL) &Curl_ssl_cyassl; -#elif defined(USE_DARWINSSL) - &Curl_ssl_darwinssl; +#elif defined(USE_SECTRANSP) + &Curl_ssl_sectransp; #elif defined(USE_GNUTLS) &Curl_ssl_gnutls; #elif defined(USE_GSKIT) @@ -1198,8 +1198,8 @@ static const struct Curl_ssl *available_backends[] = { #if defined(USE_CYASSL) &Curl_ssl_cyassl, #endif -#if defined(USE_DARWINSSL) - &Curl_ssl_darwinssl, +#if defined(USE_SECTRANSP) + &Curl_ssl_sectransp, #endif #if defined(USE_GNUTLS) &Curl_ssl_gnutls, diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index 1f163631f7..2a87ca1f72 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,7 @@ struct Curl_ssl { size_t (*version)(char *buffer, size_t size); int (*check_cxn)(struct connectdata *cxn); - int (*shutdown)(struct connectdata *conn, int sockindex); + int (*shut_down)(struct connectdata *conn, int sockindex); bool (*data_pending)(const struct connectdata *conn, int connindex); @@ -56,7 +56,7 @@ struct Curl_ssl { size_t length); bool (*cert_status_request)(void); - CURLcode (*connect)(struct connectdata *conn, int sockindex); + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, bool *done); void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); @@ -105,7 +105,7 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, #include "polarssl.h" /* PolarSSL versions */ #include "cyassl.h" /* CyaSSL versions */ #include "schannel.h" /* Schannel SSPI version */ -#include "darwinssl.h" /* SecureTransport (Darwin) version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ #include "mbedtls.h" /* mbedTLS versions */ #include "mesalink.h" /* MesaLink versions */ diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/warnless.c index 05d9038dc3..cfd5e8e141 100644 --- a/libs/libcurl/src/warnless.c +++ b/libs/libcurl/src/warnless.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -400,44 +400,6 @@ unsigned short curlx_uitous(unsigned int uinum) #endif } -/* -** unsigned int to unsigned char -*/ - -unsigned char curlx_uitouc(unsigned int uinum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_UCHAR); - return (unsigned char) (uinum & (unsigned int) CURL_MASK_UCHAR); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** unsigned int to signed int -*/ - -int curlx_uitosi(unsigned int uinum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_SINT); - return (int) (uinum & (unsigned int) CURL_MASK_SINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - /* ** signed int to unsigned size_t */ diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/warnless.h index 284ea1e752..ea4c4395dc 100644 --- a/libs/libcurl/src/warnless.h +++ b/libs/libcurl/src/warnless.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -57,10 +57,6 @@ int curlx_sztosi(ssize_t sznum); unsigned short curlx_uitous(unsigned int uinum); -unsigned char curlx_uitouc(unsigned int uinum); - -int curlx_uitosi(unsigned int uinum); - size_t curlx_sitouz(int sinum); #ifdef USE_WINSOCK diff --git a/libs/libcurl/src/x509asn1.c b/libs/libcurl/src/x509asn1.c index 746e1e8e8d..25231921c4 100644 --- a/libs/libcurl/src/x509asn1.c +++ b/libs/libcurl/src/x509asn1.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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,7 @@ static const char *getASN1Element(curl_asn1Element *elem, if an error occurs. */ if(!beg || !end || beg >= end || !*beg || (size_t)(end - beg) > CURL_ASN1_MAX) - return (const char *) NULL; + return NULL; /* Process header byte. */ elem->header = beg; @@ -129,12 +129,12 @@ static const char *getASN1Element(curl_asn1Element *elem, elem->class = (b >> 6) & 3; b &= 0x1F; if(b == 0x1F) - return (const char *) NULL; /* Long tag values not supported here. */ + return NULL; /* Long tag values not supported here. */ elem->tag = b; /* Process length. */ if(beg >= end) - return (const char *) NULL; + return NULL; b = (unsigned char) *beg++; if(!(b & 0x80)) len = b; @@ -142,69 +142,72 @@ static const char *getASN1Element(curl_asn1Element *elem, /* Unspecified length. Since we have all the data, we can determine the effective length by skipping element until an end element is found. */ if(!elem->constructed) - return (const char *) NULL; + return NULL; elem->beg = beg; while(beg < end && *beg) { beg = getASN1Element(&lelem, beg, end); if(!beg) - return (const char *) NULL; + return NULL; } if(beg >= end) - return (const char *) NULL; + return NULL; elem->end = beg; return beg + 1; } else if((unsigned)b > (size_t)(end - beg)) - return (const char *) NULL; /* Does not fit in source. */ + return NULL; /* Does not fit in source. */ else { /* Get long length. */ len = 0; do { if(len & 0xFF000000L) - return (const char *) NULL; /* Lengths > 32 bits are not supported. */ + return NULL; /* Lengths > 32 bits are not supported. */ len = (len << 8) | (unsigned char) *beg++; } while(--b); } if(len > (size_t)(end - beg)) - return (const char *) NULL; /* Element data does not fit in source. */ + return NULL; /* Element data does not fit in source. */ elem->beg = beg; elem->end = beg + len; return elem->end; } +/* + * Search the null terminated OID or OID identifier in local table. + * Return the table entry pointer or NULL if not found. + */ static const curl_OID * searchOID(const char *oid) { const curl_OID *op; - - /* Search the null terminated OID or OID identifier in local table. - Return the table entry pointer or NULL if not found. */ - for(op = OIDtable; op->numoid; op++) if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid)) return op; - return (const curl_OID *) NULL; + return NULL; } +/* + * Convert an ASN.1 Boolean value into its string representation. Return the + * dynamically allocated string, or NULL if source is not an ASN.1 Boolean + * value. + */ + static const char *bool2str(const char *beg, const char *end) { - /* Convert an ASN.1 Boolean value into its string representation. - Return the dynamically allocated string, or NULL if source is not an - ASN.1 Boolean value. */ - if(end - beg != 1) - return (const char *) NULL; + return NULL; return strdup(*beg? "TRUE": "FALSE"); } +/* + * Convert an ASN.1 octet string to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *octet2str(const char *beg, const char *end) { size_t n = end - beg; char *buf = NULL; - /* Convert an ASN.1 octet string to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(n <= (SIZE_T_MAX - 1) / 3) { buf = malloc(3 * n + 1); if(buf) @@ -220,21 +223,22 @@ static const char *bit2str(const char *beg, const char *end) Return the dynamically allocated string, or NULL if an error occurs. */ if(++beg > end) - return (const char *) NULL; + return NULL; return octet2str(beg, end); } +/* + * Convert an ASN.1 integer value into its string representation. + * Return the dynamically allocated string, or NULL if source is not an + * ASN.1 integer value. + */ static const char *int2str(const char *beg, const char *end) { unsigned long val = 0; size_t n = end - beg; - /* Convert an ASN.1 integer value into its string representation. - Return the dynamically allocated string, or NULL if source is not an - ASN.1 integer value. */ - if(!n) - return (const char *) NULL; + return NULL; if(n > 4) return octet2str(beg, end); @@ -249,6 +253,13 @@ static const char *int2str(const char *beg, const char *end) return curl_maprintf("%s%lx", val >= 10? "0x": "", val); } +/* + * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the + * destination buffer dynamically. The allocation size will normally be too + * large: this is to avoid buffer overflows. + * Terminate the string with a nul byte and return the converted + * string length. + */ static ssize_t utf8asn1str(char **to, int type, const char *from, const char *end) { @@ -259,13 +270,7 @@ utf8asn1str(char **to, int type, const char *from, const char *end) unsigned int wc; char *buf; - /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the - destination buffer dynamically. The allocation size will normally be too - large: this is to avoid buffer overflows. - Terminate the string with a nul byte and return the converted - string length. */ - - *to = (char *) NULL; + *to = NULL; switch(type) { case CURL_ASN1_BMP_STRING: size = 2; @@ -341,96 +346,105 @@ utf8asn1str(char **to, int type, const char *from, const char *end) return outlength; } +/* + * Convert an ASN.1 String into its UTF-8 string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *string2str(int type, const char *beg, const char *end) { char *buf; - - /* Convert an ASN.1 String into its UTF-8 string representation. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(utf8asn1str(&buf, type, beg, end) < 0) - return (const char *) NULL; + return NULL; return buf; } -static int encodeUint(char *buf, int n, unsigned int x) +/* + * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at + * buf. Return the total number of encoded digits, even if larger than + * `buflen'. + */ +static size_t encodeUint(char *buf, size_t buflen, unsigned int x) { - int i = 0; + size_t i = 0; unsigned int y = x / 10; - /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'. - Return the total number of encoded digits, even if larger than `n'. */ - if(y) { - i += encodeUint(buf, n, y); + i = encodeUint(buf, buflen, y); x -= y * 10; } - if(i < n) + if(i < buflen) buf[i] = (char) ('0' + x); i++; - if(i < n) + if(i < buflen) buf[i] = '\0'; /* Store a terminator if possible. */ return i; } -static int encodeOID(char *buf, int n, const char *beg, const char *end) +/* + * Convert an ASN.1 OID into its dotted string representation. + * Store the result in th `n'-byte buffer at `buf'. + * Return the converted string length, or 0 on errors. + */ +static size_t encodeOID(char *buf, size_t buflen, + const char *beg, const char *end) { - int i = 0; + size_t i; unsigned int x; unsigned int y; - /* Convert an ASN.1 OID into its dotted string representation. - Store the result in th `n'-byte buffer at `buf'. - Return the converted string length, or -1 if an error occurs. */ - /* Process the first two numbers. */ y = *(const unsigned char *) beg++; x = y / 40; y -= x * 40; - i += encodeUint(buf + i, n - i, x); - if(i < n) + i = encodeUint(buf, buflen, x); + if(i < buflen) buf[i] = '.'; i++; - i += encodeUint(buf + i, n - i, y); + if(i >= buflen) + i += encodeUint(NULL, 0, y); + else + i += encodeUint(buf + i, buflen - i, y); /* Process the trailing numbers. */ while(beg < end) { - if(i < n) + if(i < buflen) buf[i] = '.'; i++; x = 0; do { if(x & 0xFF000000) - return -1; + return 0; y = *(const unsigned char *) beg++; x = (x << 7) | (y & 0x7F); } while(y & 0x80); - i += encodeUint(buf + i, n - i, x); + if(i >= buflen) + i += encodeUint(NULL, 0, x); + else + i += encodeUint(buf + i, buflen - i, x); } - if(i < n) + if(i < buflen) buf[i] = '\0'; return i; } +/* + * Convert an ASN.1 OID into its dotted or symbolic string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ + static const char *OID2str(const char *beg, const char *end, bool symbolic) { - char *buf = (char *) NULL; - const curl_OID * op; - int n; - - /* Convert an ASN.1 OID into its dotted or symbolic string representation. - Return the dynamically allocated string, or NULL if an error occurs. */ - + char *buf = NULL; if(beg < end) { - n = encodeOID((char *) NULL, -1, beg, end); - if(n >= 0) { - buf = malloc(n + 1); + size_t buflen = encodeOID(NULL, 0, beg, end); + if(buflen) { + buf = malloc(buflen + 1); /* one extra for the zero byte */ if(buf) { - encodeOID(buf, n, beg, end); - buf[n] = '\0'; + encodeOID(buf, buflen, beg, end); + buf[buflen] = '\0'; if(symbolic) { - op = searchOID(buf); + const curl_OID *op = searchOID(buf); if(op) { free(buf); buf = strdup(op->textoid); @@ -470,7 +484,7 @@ static const char *GTime2str(const char *beg, const char *end) sec2 = fracp[-1]; break; default: - return (const char *) NULL; + return NULL; } /* Scan for timezone, measure fractional seconds. */ @@ -506,15 +520,16 @@ static const char *GTime2str(const char *beg, const char *end) sep, tzl, tzp); } +/* + * Convert an ASN.1 UTC time to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *UTime2str(const char *beg, const char *end) { const char *tzp; size_t tzl; const char *sec; - /* Convert an ASN.1 UTC time to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++) ; /* Get the seconds. */ @@ -525,12 +540,12 @@ static const char *UTime2str(const char *beg, const char *end) case 2: break; default: - return (const char *) NULL; + return NULL; } /* Process timezone. */ if(tzp >= end) - return (const char *) NULL; + return NULL; if(*tzp == 'Z') { tzp = "GMT"; end = tzp + 3; @@ -545,13 +560,14 @@ static const char *UTime2str(const char *beg, const char *end) tzl, tzp); } +/* + * Convert an ASN.1 element to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *ASN1tostr(curl_asn1Element *elem, int type) { - /* Convert an ASN.1 element to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(elem->constructed) - return (const char *) NULL; /* No conversion of structured elements. */ + return NULL; /* No conversion of structured elements. */ if(!type) type = elem->tag; /* Type not forced: use element tag as type. */ @@ -585,10 +601,14 @@ static const char *ASN1tostr(curl_asn1Element *elem, int type) return string2str(type, elem->beg, elem->end); } - return (const char *) NULL; /* Unsupported. */ + return NULL; /* Unsupported. */ } -static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) +/* + * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at + * `buf'. Return the total string length, even if larger than `buflen'. + */ +static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn) { curl_asn1Element rdn; curl_asn1Element atv; @@ -600,9 +620,6 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) const char *p3; const char *str; - /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'. - Return the total string length, even if larger than `n'. */ - for(p1 = dn->beg; p1 < dn->end;) { p1 = getASN1Element(&rdn, p1, dn->end); if(!p1) @@ -626,7 +643,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) for(p3 = str; isupper(*p3); p3++) ; for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } @@ -634,14 +651,14 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) /* Encode attribute name. */ for(p3 = str; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } free((char *) str); /* Generate equal sign. */ - if(l < n) + if(l < buflen) buf[l] = '='; l++; @@ -650,7 +667,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) if(!str) return -1; for(p3 = str; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } @@ -661,28 +678,30 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) return l; } +/* + * Convert an ASN.1 distinguished name into a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *DNtostr(curl_asn1Element *dn) { - char *buf = (char *) NULL; - ssize_t n = encodeDN(buf, 0, dn); - - /* Convert an ASN.1 distinguished name into a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ + char *buf = NULL; + ssize_t buflen = encodeDN(NULL, 0, dn); - if(n >= 0) { - buf = malloc(n + 1); + if(buflen >= 0) { + buf = malloc(buflen + 1); if(buf) { - encodeDN(buf, n + 1, dn); - buf[n] = '\0'; + encodeDN(buf, buflen + 1, dn); + buf[buflen] = '\0'; } } - return (const char *) buf; + return buf; } /* - * X509 parser. + * ASN.1 parse an X509 certificate into structure subfields. + * Syntax is assumed to have already been checked by the SSL backend. + * See RFC 5280. */ - int Curl_parseX509(curl_X509certificate *cert, const char *beg, const char *end) { @@ -691,10 +710,6 @@ int Curl_parseX509(curl_X509certificate *cert, const char *ccp; static const char defaultVersion = 0; /* v1. */ - /* ASN.1 parse an X509 certificate into structure subfields. - Syntax is assumed to have already been checked by the SSL backend. - See RFC 5280. */ - cert->certificate.header = NULL; cert->certificate.beg = beg; cert->certificate.end = end; @@ -801,13 +816,14 @@ int Curl_parseX509(curl_X509certificate *cert, return 0; } + +/* + * Copy at most 64-characters, terminate with a newline and returns the + * effective number of stored characters. + */ static size_t copySubstring(char *to, const char *from) { size_t i; - - /* Copy at most 64-characters, terminate with a newline and returns the - effective number of stored characters. */ - for(i = 0; i < 64; i++) { to[i] = *from; if(!*from++) @@ -1104,15 +1120,15 @@ static const char *checkOID(const char *beg, const char *end, ccp = getASN1Element(&e, beg, end); if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER) - return (const char *) NULL; + return NULL; p = OID2str(e.beg, e.end, FALSE); if(!p) - return (const char *) NULL; + return NULL; matched = !strcmp(p, oid); free((char *) p); - return matched? ccp: (const char *) NULL; + return matched? ccp: NULL; } CURLcode Curl_verifyhost(struct connectdata *conn, -- cgit v1.2.3