summaryrefslogtreecommitdiff
path: root/libs/libcurl/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src')
-rw-r--r--libs/libcurl/src/Makefile.Watcom2
-rw-r--r--libs/libcurl/src/Makefile.b32185
-rw-r--r--libs/libcurl/src/Makefile.in38
-rw-r--r--libs/libcurl/src/Makefile.inc4
-rw-r--r--libs/libcurl/src/Makefile.netware27
-rw-r--r--libs/libcurl/src/asyn-ares.c33
-rw-r--r--libs/libcurl/src/asyn-thread.c11
-rw-r--r--libs/libcurl/src/asyn.h9
-rw-r--r--libs/libcurl/src/base64.c26
-rw-r--r--libs/libcurl/src/checksrc.pl118
-rw-r--r--libs/libcurl/src/conncache.c2
-rw-r--r--libs/libcurl/src/connect.c8
-rw-r--r--libs/libcurl/src/cookie.c67
-rw-r--r--libs/libcurl/src/curl_config.h.in6
-rw-r--r--libs/libcurl/src/curl_gssapi.c6
-rw-r--r--libs/libcurl/src/curl_multibyte.c12
-rw-r--r--libs/libcurl/src/curl_ntlm_core.c34
-rw-r--r--libs/libcurl/src/curl_printf.h16
-rw-r--r--libs/libcurl/src/curl_setup.h2
-rw-r--r--libs/libcurl/src/curlx.h11
-rw-r--r--libs/libcurl/src/doh.c43
-rw-r--r--libs/libcurl/src/easy.c10
-rw-r--r--libs/libcurl/src/escape.c2
-rw-r--r--libs/libcurl/src/file.c25
-rw-r--r--libs/libcurl/src/ftp.c30
-rw-r--r--libs/libcurl/src/ftplistparser.c2
-rw-r--r--libs/libcurl/src/hostcheck.c5
-rw-r--r--libs/libcurl/src/hostip4.c4
-rw-r--r--libs/libcurl/src/hostip6.c2
-rw-r--r--libs/libcurl/src/http.c78
-rw-r--r--libs/libcurl/src/http2.c10
-rw-r--r--libs/libcurl/src/http2.h4
-rw-r--r--libs/libcurl/src/http_negotiate.c8
-rw-r--r--libs/libcurl/src/if2ip.c6
-rw-r--r--libs/libcurl/src/imap.c4
-rw-r--r--libs/libcurl/src/inet_ntop.c12
-rw-r--r--libs/libcurl/src/ldap.c15
-rw-r--r--libs/libcurl/src/libcurl.plist6
-rw-r--r--libs/libcurl/src/libcurl.rc12
-rw-r--r--libs/libcurl/src/md4.c1
-rw-r--r--libs/libcurl/src/md5.c7
-rw-r--r--libs/libcurl/src/memdebug.c4
-rw-r--r--libs/libcurl/src/mprintf.c2
-rw-r--r--libs/libcurl/src/multi.c66
-rw-r--r--libs/libcurl/src/multiif.h10
-rw-r--r--libs/libcurl/src/netrc.c11
-rw-r--r--libs/libcurl/src/netrc.h2
-rw-r--r--libs/libcurl/src/openldap.c4
-rw-r--r--libs/libcurl/src/openssl.c3661
-rw-r--r--libs/libcurl/src/openssl.h37
-rw-r--r--libs/libcurl/src/pop3.c14
-rw-r--r--libs/libcurl/src/progress.c36
-rw-r--r--libs/libcurl/src/security.c4
-rw-r--r--libs/libcurl/src/sendf.c15
-rw-r--r--libs/libcurl/src/setopt.c6
-rw-r--r--libs/libcurl/src/socks_gssapi.c6
-rw-r--r--libs/libcurl/src/socks_sspi.c8
-rw-r--r--libs/libcurl/src/ssh-libssh.c24
-rw-r--r--libs/libcurl/src/ssh.c26
-rw-r--r--libs/libcurl/src/strerror.c26
-rw-r--r--libs/libcurl/src/telnet.c30
-rw-r--r--libs/libcurl/src/tftp.c14
-rw-r--r--libs/libcurl/src/transfer.c47
-rw-r--r--libs/libcurl/src/url.c160
-rw-r--r--libs/libcurl/src/urlapi-int.h5
-rw-r--r--libs/libcurl/src/urlapi.c61
-rw-r--r--libs/libcurl/src/urldata.h2
-rw-r--r--libs/libcurl/src/vauth/digest.c10
-rw-r--r--libs/libcurl/src/vauth/ntlm.c222
-rw-r--r--libs/libcurl/src/version.c36
-rw-r--r--libs/libcurl/src/vtls/axtls.c741
-rw-r--r--libs/libcurl/src/vtls/axtls.h33
-rw-r--r--libs/libcurl/src/vtls/cyassl.c8
-rw-r--r--libs/libcurl/src/vtls/darwinssl.c26
-rw-r--r--libs/libcurl/src/vtls/gskit.c2
-rw-r--r--libs/libcurl/src/vtls/gtls.c26
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c6
-rw-r--r--libs/libcurl/src/vtls/mesalink.c6
-rw-r--r--libs/libcurl/src/vtls/nss.c72
-rw-r--r--libs/libcurl/src/vtls/openssl.c252
-rw-r--r--libs/libcurl/src/vtls/polarssl.c8
-rw-r--r--libs/libcurl/src/vtls/schannel.c83
-rw-r--r--libs/libcurl/src/vtls/schannel.h4
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c4
-rw-r--r--libs/libcurl/src/vtls/vtls.c16
-rw-r--r--libs/libcurl/src/vtls/vtls.h1
-rw-r--r--libs/libcurl/src/x509asn1.c2
87 files changed, 1237 insertions, 5505 deletions
diff --git a/libs/libcurl/src/Makefile.Watcom b/libs/libcurl/src/Makefile.Watcom
index 5f335cedbd..942cd0c7b4 100644
--- a/libs/libcurl/src/Makefile.Watcom
+++ b/libs/libcurl/src/Makefile.Watcom
@@ -157,7 +157,7 @@ CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H -I"$(LIBSSH2_ROOT)/include" -I"$(LIBSSH
!endif
!ifdef %use_ssl
-CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I"$(OPENSSL_ROOT)/inc32"
+CFLAGS += -wcd=138 -dUSE_OPENSSL -I"$(OPENSSL_ROOT)/inc32"
!endif
!ifdef %use_ares
diff --git a/libs/libcurl/src/Makefile.b32 b/libs/libcurl/src/Makefile.b32
deleted file mode 100644
index 5b5b5fa9fc..0000000000
--- a/libs/libcurl/src/Makefile.b32
+++ /dev/null
@@ -1,185 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2000, Jaepil Kim, <pit@paradise.net.nz>.
-# Copyright (C) 2001 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-#***************************************************************************
-
-############################################################
-#
-# Makefile.b32 - Borland's C++ Compiler 5.X
-#
-# 'BCCDIR' has to be set up to point to the base directory
-# of the compiler, i.e. SET BCCDIR = c:\Borland\BCC55
-#
-############################################################
-
-!if "$(__MAKE__)" == ""
-!error __MAKE__ not defined. Use Borlands's MAKE to process this makefile.
-!endif
-
-# Borland's $(MAKEDIR) expands to the path where make.exe is located,
-# use this feature to define BCCDIR when user has not defined BCCDIR.
-!ifndef BCCDIR
-BCCDIR = $(MAKEDIR)\..
-!endif
-
-# Edit the path below to point to the base of your Zlib sources.
-!ifndef ZLIB_PATH
-ZLIB_PATH = ..\..\zlib-1.2.8
-!endif
-
-# Edit the path below to point to the base of your OpenSSL package.
-!ifndef OPENSSL_PATH
-OPENSSL_PATH = ..\..\openssl-1.0.2a
-!endif
-
-# Set libcurl static lib, dll and import lib
-LIBCURL_LIB = libcurl.lib
-LIBCURL_DLL = libcurl.dll
-LIBCURL_IMPLIB = libcurl_imp.lib
-
-# Setup environment
-PP_CMD = cpp32 -q -P-
-CC_CMD = bcc32 -q -c
-LD = bcc32
-RM = del 2>NUL
-MKDIR = md
-RMDIR = rd /q
-LIB = tlib
-IMPLIB = implib
-
-CC_FLAGS = -5 -O2 -tWM -w -w-aus -w-ccc -w-dup -w-prc -w-pro -w-rch -w-sig -w-spa -w-inl -w-pia -w-pin -Dinline=__inline
-LIBFLAGS = /C /P32
-LDFLAGS = -q -lq -laa -tWD
-
-SRCDIR = .;.\vauth;.\vtls
-OBJDIR = .\BCC_objs
-INCDIRS = -I.;.\lib;..\include
-LINKLIB = $(BCCDIR)\lib\cw32mt.lib $(BCCDIR)\lib\ws2_32.lib
-DEFINES = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL
-
-# By default SSPI support is enabled for BCC
-!ifndef DISABLE_SSPI
-DEFINES = $(DEFINES) -DUSE_WINDOWS_SSPI
-!endif
-
-# By default LDAP support is disabled for BCC
-!ifndef WITH_LDAP
-DEFINES = $(DEFINES) -DCURL_DISABLE_LDAP
-!endif
-
-# ZLIB support is enabled setting WITH_ZLIB=1
-!ifdef WITH_ZLIB
-DEFINES = $(DEFINES) -DHAVE_LIBZ -DHAVE_ZLIB_H
-INCDIRS = $(INCDIRS);$(ZLIB_PATH)
-LINKLIB = $(LINKLIB) $(ZLIB_PATH)\zlib.lib
-!endif
-
-# SSL support is enabled setting WITH_SSL=1
-!ifdef WITH_SSL
-DEFINES = $(DEFINES) -DUSE_OPENSSL
-INCDIRS = $(INCDIRS);$(OPENSSL_PATH)\inc32;$(OPENSSL_PATH)\inc32\openssl
-LINKLIB = $(LINKLIB) $(OPENSSL_PATH)\out32\ssleay32.lib $(OPENSSL_PATH)\out32\libeay32.lib
-!endif
-
-.autodepend
-
-.path.c = $(SRCDIR)
-.path.obj = $(OBJDIR)
-.path.int = $(OBJDIR)
-
-# Makefile.inc provides the CSOURCES and HHEADERS defines
-!include Makefile.inc
-
-# Borland's command line librarian program TLIB version 4.5 is not capable
-# of building a library when any of its objects contains an hyphen in its
-# name, due to a command line parsing bug. In order to workaround this, we
-# build source files with hyphens in their name as objects with underscores
-# using explicit compilation build rules instead of implicit ones.
-
-NOHYPHEN1 = $(CSOURCES:-=_)
-NOHYPHEN2 = $(NOHYPHEN1:vauth/=)
-NOHYPHEN3 = $(NOHYPHEN2:vtls/=)
-
-OBJECTS = $(NOHYPHEN3:.c=.obj)
-PREPROCESSED = $(NOHYPHEN3:.c=.int)
-
-# Borland's command line compiler (BCC32) version 5.5.1 integrated
-# preprocessor has a bug which results in silently generating wrong
-# definitions for libcurl macros such as CURL_OFF_T_C, on the other
-# hand Borland's command line preprocessor (CPP32) version 5.5.1 does
-# not have the bug and achieves proper results. In order to avoid the
-# silent bug we first preprocess source files and later compile the
-# preprocessed result.
-
-.c.obj:
- @-$(RM) $(@R).int
- $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(<)
- $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
-
-all: $(OBJDIR) $(LIBCURL_LIB) $(LIBCURL_DLL)
-
-asyn_ares.obj: asyn-ares.c
- @-$(RM) $(@R).int
- $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
- $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
-
-asyn_thread.obj: asyn-thread.c
- @-$(RM) $(@R).int
- $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
- $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
-
-non_ascii.obj: non-ascii.c
- @-$(RM) $(@R).int
- $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
- $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
-
-clean:
- cd $(OBJDIR)
- @-$(RM) $(OBJECTS)
- @-$(RM) $(PREPROCESSED)
- cd ..
- @-$(RMDIR) $(OBJDIR)
- @-$(RM) $(LIBCURL_LIB)
- @-$(RM) $(LIBCURL_IMPLIB)
- @-$(RM) libcurl.tds
-
-$(OBJDIR):
- @-$(RMDIR) $(OBJDIR)
- @-$(MKDIR) $(OBJDIR)
-
-$(LIBCURL_LIB): $(OBJECTS)
- @-$(RM) $(LIBCURL_LIB)
- $(LIB) $(LIBFLAGS) $@ @&&!
-+$(**: = &^
-+)
-!
-
-$(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB)
- @-$(RM) $(LIBCURL_DLL)
- @-$(RM) $(LIBCURL_IMPLIB)
- $(LD) $(LDFLAGS) -e$(LIBCURL_DLL) @&&!
-$(**: = ^
-)
-!
- $(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL)
-
-
-# End of Makefile.b32
diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in
index c93fec818f..43c5d442b4 100644
--- a/libs/libcurl/src/Makefile.in
+++ b/libs/libcurl/src/Makefile.in
@@ -243,8 +243,8 @@ am__objects_3 = vtls/libcurl_la-openssl.lo vtls/libcurl_la-gtls.lo \
vtls/libcurl_la-vtls.lo vtls/libcurl_la-nss.lo \
vtls/libcurl_la-polarssl.lo \
vtls/libcurl_la-polarssl_threadlock.lo \
- vtls/libcurl_la-axtls.lo vtls/libcurl_la-cyassl.lo \
- vtls/libcurl_la-schannel.lo vtls/libcurl_la-schannel_verify.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-mbedtls.lo vtls/libcurl_la-mesalink.lo
am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3)
@@ -325,8 +325,7 @@ am__objects_9 = vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-gtls.lo \
vtls/libcurlu_la-vtls.lo vtls/libcurlu_la-nss.lo \
vtls/libcurlu_la-polarssl.lo \
vtls/libcurlu_la-polarssl_threadlock.lo \
- vtls/libcurlu_la-axtls.lo vtls/libcurlu_la-cyassl.lo \
- vtls/libcurlu_la-schannel.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-mbedtls.lo vtls/libcurlu_la-mesalink.lo
@@ -594,7 +593,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.Plo \
vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo \
vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo \
vauth/$(DEPDIR)/libcurlu_la-vauth.Plo \
- vtls/$(DEPDIR)/libcurl_la-axtls.Plo \
vtls/$(DEPDIR)/libcurl_la-cyassl.Plo \
vtls/$(DEPDIR)/libcurl_la-darwinssl.Plo \
vtls/$(DEPDIR)/libcurl_la-gskit.Plo \
@@ -608,7 +606,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-amigaos.Plo \
vtls/$(DEPDIR)/libcurl_la-schannel.Plo \
vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo \
vtls/$(DEPDIR)/libcurl_la-vtls.Plo \
- vtls/$(DEPDIR)/libcurlu_la-axtls.Plo \
vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo \
vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo \
vtls/$(DEPDIR)/libcurlu_la-gskit.Plo \
@@ -806,7 +803,6 @@ STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
-USE_AXTLS = @USE_AXTLS@
USE_CYASSL = @USE_CYASSL@
USE_DARWINSSL = @USE_DARWINSSL@
USE_GNUTLS = @USE_GNUTLS@
@@ -964,12 +960,12 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \
LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
- vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.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
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
- vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
+ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \
vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \
vtls/mbedtls.h vtls/mesalink.h
@@ -1170,8 +1166,6 @@ vtls/libcurl_la-polarssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurl_la-axtls.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-cyassl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-schannel.lo: vtls/$(am__dirstamp) \
@@ -1225,8 +1219,6 @@ vtls/libcurlu_la-polarssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurlu_la-axtls.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-cyassl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-schannel.lo: vtls/$(am__dirstamp) \
@@ -1501,7 +1493,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo@am__quote@ # am--include-marker
@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-axtls.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
@@ -1515,7 +1506,6 @@ distclean-compile:
@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-vtls.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-axtls.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
@@ -2463,13 +2453,6 @@ vtls/libcurl_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.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-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c
-vtls/libcurl_la-axtls.lo: vtls/axtls.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-axtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-axtls.Tpo -c -o vtls/libcurl_la-axtls.lo `test -f 'vtls/axtls.c' || echo '$(srcdir)/'`vtls/axtls.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-axtls.Tpo vtls/$(DEPDIR)/libcurl_la-axtls.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/axtls.c' object='vtls/libcurl_la-axtls.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-axtls.lo `test -f 'vtls/axtls.c' || echo '$(srcdir)/'`vtls/axtls.c
-
vtls/libcurl_la-cyassl.lo: vtls/cyassl.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-cyassl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-cyassl.Tpo -c -o vtls/libcurl_la-cyassl.lo `test -f 'vtls/cyassl.c' || echo '$(srcdir)/'`vtls/cyassl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-cyassl.Tpo vtls/$(DEPDIR)/libcurl_la-cyassl.Plo
@@ -3422,13 +3405,6 @@ vtls/libcurlu_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.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-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c
-vtls/libcurlu_la-axtls.lo: vtls/axtls.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-axtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-axtls.Tpo -c -o vtls/libcurlu_la-axtls.lo `test -f 'vtls/axtls.c' || echo '$(srcdir)/'`vtls/axtls.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-axtls.Tpo vtls/$(DEPDIR)/libcurlu_la-axtls.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/axtls.c' object='vtls/libcurlu_la-axtls.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-axtls.lo `test -f 'vtls/axtls.c' || echo '$(srcdir)/'`vtls/axtls.c
-
vtls/libcurlu_la-cyassl.lo: vtls/cyassl.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-cyassl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-cyassl.Tpo -c -o vtls/libcurlu_la-cyassl.lo `test -f 'vtls/cyassl.c' || echo '$(srcdir)/'`vtls/cyassl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-cyassl.Tpo vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo
@@ -3865,7 +3841,6 @@ distclean: distclean-am
-rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo
-rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo
-rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-axtls.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
@@ -3879,7 +3854,6 @@ distclean: distclean-am
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-axtls.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
@@ -4184,7 +4158,6 @@ maintainer-clean: maintainer-clean-am
-rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo
-rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo
-rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-axtls.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
@@ -4198,7 +4171,6 @@ maintainer-clean: maintainer-clean-am
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-axtls.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
diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc
index 4aa0422591..54acd6cea1 100644
--- a/libs/libcurl/src/Makefile.inc
+++ b/libs/libcurl/src/Makefile.inc
@@ -28,12 +28,12 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \
LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
- vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.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
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
- vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
+ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \
vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \
vtls/mbedtls.h vtls/mesalink.h
diff --git a/libs/libcurl/src/Makefile.netware b/libs/libcurl/src/Makefile.netware
index fa6beec00f..29885a19ea 100644
--- a/libs/libcurl/src/Makefile.netware
+++ b/libs/libcurl/src/Makefile.netware
@@ -6,7 +6,7 @@
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2004 - 2015, Guenter Knauf
-# Copyright (C) 2001 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 2001 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -49,11 +49,6 @@ ifndef LIBSSH2_PATH
LIBSSH2_PATH = ../../libssh2-1.5.0
endif
-# Edit the path below to point to the base of your axTLS package.
-ifndef AXTLS_PATH
-AXTLS_PATH = ../../axTLS-1.2.7
-endif
-
# Edit the path below to point to the base of your libidn package.
ifndef LIBIDN_PATH
LIBIDN_PATH = ../../libidn-1.18
@@ -230,10 +225,6 @@ WITH_SSH2 = 1
WITH_SSL = 1
WITH_ZLIB = 1
endif
-ifeq ($(findstring -axtls,$(CFG)),-axtls)
-WITH_AXTLS = 1
-WITH_SSL =
-else
ifeq ($(findstring -ssl,$(CFG)),-ssl)
WITH_SSL = 1
ifeq ($(findstring -srp,$(CFG)),-srp)
@@ -242,7 +233,6 @@ WITH_SRP = 1
endif
endif
endif
-endif
ifeq ($(findstring -zlib,$(CFG)),-zlib)
WITH_ZLIB = 1
endif
@@ -280,16 +270,6 @@ ifdef WITH_SSL
IMPORTS += GetProcessSwitchCount RunningProcess
INSTDEP += ca-bundle.crt
else
-ifdef WITH_AXTLS
- INCLUDES += -I$(AXTLS_PATH)/inc
- ifdef LINK_STATIC
- LDLIBS += $(AXTLS_PATH)/lib/libaxtls.$(LIBEXT)
- else
- MODULES += libaxtls.nlm
- IMPORTS += $(AXTLS_PATH)/lib/libaxtls.imp
- endif
- INSTDEP += ca-bundle.crt
-endif
endif
ifdef WITH_ZLIB
INCLUDES += -I$(ZLIB_PATH)
@@ -652,7 +632,6 @@ ifdef WITH_ZLIB
@echo $(DL)#define HAVE_LIBZ 1$(DL) >> $@
endif
ifdef WITH_SSL
- @echo $(DL)#define USE_SSLEAY 1$(DL) >> $@
@echo $(DL)#define USE_OPENSSL 1$(DL) >> $@
@echo $(DL)#define HAVE_OPENSSL_X509_H 1$(DL) >> $@
@echo $(DL)#define HAVE_OPENSSL_SSL_H 1$(DL) >> $@
@@ -665,16 +644,12 @@ ifdef WITH_SSL
@echo $(DL)#define HAVE_LIBCRYPTO 1$(DL) >> $@
@echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@
ifdef WITH_SRP
- @echo $(DL)#define HAVE_SSLEAY_SRP 1$(DL) >> $@
@echo $(DL)#define USE_TLS_SRP 1$(DL) >> $@
endif
ifdef WITH_SPNEGO
@echo $(DL)#define HAVE_SPNEGO 1$(DL) >> $@
endif
else
-ifdef WITH_AXTLS
- @echo $(DL)#define USE_AXTLS 1$(DL) >> $@
-endif
endif
ifdef WITH_SSH2
@echo $(DL)#define USE_LIBSSH2 1$(DL) >> $@
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index 5cfb2602df..6a49566c86 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -119,6 +119,17 @@ void Curl_resolver_global_cleanup(void)
#endif
}
+
+static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
+ int readable, int writable)
+{
+ struct Curl_easy *easy = data;
+ if(!readable && !writable) {
+ DEBUGASSERT(easy);
+ Curl_multi_closed(easy, socket_fd);
+ }
+}
+
/*
* Curl_resolver_init()
*
@@ -126,9 +137,14 @@ void Curl_resolver_global_cleanup(void)
* URL-state specific environment ('resolver' member of the UrlState
* structure). Fills the passed pointer by the initialized ares_channel.
*/
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
- int status = ares_init((ares_channel*)resolver);
+ int status;
+ struct ares_options options;
+ int optmask = ARES_OPT_SOCK_STATE_CB;
+ options.sock_state_cb = Curl_ares_sock_state_cb;
+ options.sock_state_cb_data = easy;
+ status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
if(status == ARES_ENOMEM)
return CURLE_OUT_OF_MEMORY;
@@ -159,12 +175,15 @@ void Curl_resolver_cleanup(void *resolver)
* environment ('resolver' member of the UrlState structure). Duplicates the
* 'from' ares channel and passes the resulting channel to the 'to' pointer.
*/
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
{
- /* Clone the ares channel for the new handle */
- if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
- return CURLE_FAILED_INIT;
- return CURLE_OK;
+ (void)from;
+ /*
+ * it would be better to call ares_dup instead, but right now
+ * it is not possible to set 'sock_state_cb_data' outside of
+ * ares_init_options
+ */
+ return Curl_resolver_init(easy, to);
}
static void destroy_async_data(struct Curl_async *async);
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c
index 2a59294e5c..74208d7ec5 100644
--- a/libs/libcurl/src/asyn-thread.c
+++ b/libs/libcurl/src/asyn-thread.c
@@ -108,8 +108,9 @@ void Curl_resolver_global_cleanup(void)
* URL-state specific environment ('resolver' member of the UrlState
* structure).
*/
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
+ (void)easy;
*resolver = calloc(1, sizeof(struct resdata));
if(!*resolver)
return CURLE_OUT_OF_MEMORY;
@@ -132,10 +133,10 @@ void Curl_resolver_cleanup(void *resolver)
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific
* environment ('resolver' member of the UrlState structure).
*/
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
{
(void)from;
- return Curl_resolver_init(to);
+ return Curl_resolver_init(easy, to);
}
static void destroy_async_data(struct Curl_async *);
@@ -276,7 +277,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
char service[12];
int rc;
- snprintf(service, sizeof(service), "%d", tsd->port);
+ msnprintf(service, sizeof(service), "%d", tsd->port);
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
@@ -678,7 +679,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
hints.ai_family = pf;
hints.ai_socktype = conn->socktype;
- snprintf(sbuf, sizeof(sbuf), "%d", port);
+ msnprintf(sbuf, sizeof(sbuf), "%d", port);
reslv->start = Curl_now();
/* fire up a new resolver thread! */
diff --git a/libs/libcurl/src/asyn.h b/libs/libcurl/src/asyn.h
index 3adc3664a2..43625bc3be 100644
--- a/libs/libcurl/src/asyn.h
+++ b/libs/libcurl/src/asyn.h
@@ -60,7 +60,7 @@ void Curl_resolver_global_cleanup(void);
* Returning anything else than CURLE_OK fails curl_easy_init() with the
* correspondent code.
*/
-CURLcode Curl_resolver_init(void **resolver);
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
/*
* Curl_resolver_cleanup()
@@ -79,7 +79,8 @@ void Curl_resolver_cleanup(void *resolver);
* pointer. Returning anything else than CURLE_OK causes failed
* curl_easy_duphandle() call.
*/
-int Curl_resolver_duphandle(void **to, void *from);
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
+ void *from);
/*
* Curl_resolver_cancel().
@@ -150,8 +151,8 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_getsock(x,y,z) 0
-#define Curl_resolver_duphandle(x,y) CURLE_OK
-#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_duphandle(x,y,z) CURLE_OK
+#define Curl_resolver_init(x,y) CURLE_OK
#define Curl_resolver_global_init() CURLE_OK
#define Curl_resolver_global_cleanup() Curl_nop_stmt
#define Curl_resolver_cleanup(x) Curl_nop_stmt
diff --git a/libs/libcurl/src/base64.c b/libs/libcurl/src/base64.c
index 6370e4cdfb..431b643573 100644
--- a/libs/libcurl/src/base64.c
+++ b/libs/libcurl/src/base64.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -233,24 +233,24 @@ static CURLcode base64_encode(const char *table64,
switch(inputparts) {
case 1: /* only one byte read */
- snprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
+ msnprintf(output, 5, "%c%c==",
+ table64[obuf[0]],
+ table64[obuf[1]]);
break;
case 2: /* two bytes read */
- snprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
+ msnprintf(output, 5, "%c%c%c=",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]]);
break;
default:
- snprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]]);
+ msnprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]]);
break;
}
output += 4;
diff --git a/libs/libcurl/src/checksrc.pl b/libs/libcurl/src/checksrc.pl
index 15e9aff8ee..965f0bab1d 100644
--- a/libs/libcurl/src/checksrc.pl
+++ b/libs/libcurl/src/checksrc.pl
@@ -35,6 +35,7 @@ my $suppressed; # whitelisted problems
my $file;
my $dir=".";
my $wlist="";
+my @alist;
my $windows_os = $^O eq 'MSWin32' || $^O eq 'msys' || $^O eq 'cygwin';
my $verbose;
my %whitelist;
@@ -44,6 +45,10 @@ my %ignore_set;
my %ignore_used;
my @ignore_line;
+my %warnings_extended = (
+ 'COPYRIGHTYEAR' => 'copyright year incorrect',
+ );
+
my %warnings = (
'LONGLINE' => "Line longer than $max_column",
'TABS' => 'TAB characters not allowed',
@@ -74,6 +79,7 @@ my %warnings = (
'SEMINOSPACE' => 'semicolon without following space',
'MULTISPACE' => 'multiple spaces used when not suitable',
'SIZEOFNOPAREN' => 'use of sizeof without parentheses',
+ 'SNPRINTF' => 'use of snprintf',
);
sub readwhitelist {
@@ -86,6 +92,35 @@ sub readwhitelist {
close(W);
}
+# Reads the .checksrc in $dir for any extended warnings to enable locally.
+# Currently there is no support for disabling warnings from the standard set,
+# and since that's already handled via !checksrc! commands there is probably
+# little use to add it.
+sub readlocalfile {
+ my $i = 0;
+
+ open(my $rcfile, "<", "$dir/.checksrc") or return;
+
+ while(<$rcfile>) {
+ $i++;
+
+ # Lines starting with '#' are considered comments
+ if (/^\s*(#.*)/) {
+ next;
+ }
+ elsif (/^\s*enable ([A-Z]+)$/) {
+ if(!defined($warnings_extended{$1})) {
+ print STDERR "invalid warning specified in .checksrc: \"$1\"\n";
+ next;
+ }
+ $warnings{$1} = $warnings_extended{$1};
+ }
+ else {
+ die "Invalid format in $dir/.checksrc on line $i\n";
+ }
+ }
+}
+
sub checkwarn {
my ($name, $num, $col, $file, $line, $msg, $error) = @_;
@@ -153,6 +188,11 @@ while(1) {
$file = shift @ARGV;
next;
}
+ elsif($file =~ /-A(.+)/) {
+ push @alist, $1;
+ $file = shift @ARGV;
+ next;
+ }
elsif($file =~ /-i([1-9])/) {
$indent = $1 + 0;
$file = shift @ARGV;
@@ -174,6 +214,7 @@ while(1) {
if(!$file) {
print "checksrc.pl [option] <file1> [file2] ...\n";
print " Options:\n";
+ print " -A[rule] Accept this violation, can be used multiple times\n";
print " -D[DIR] Directory to prepend file names\n";
print " -h Show help output\n";
print " -W[file] Whitelist the given file - ignore all its flaws\n";
@@ -187,6 +228,7 @@ if(!$file) {
}
readwhitelist();
+readlocalfile();
do {
if("$wlist" !~ / $file /) {
@@ -198,6 +240,17 @@ do {
} while($file);
+sub accept_violations {
+ for my $r (@alist) {
+ if(!$warnings{$r}) {
+ print "'$r' is not a warning to accept!\n";
+ exit;
+ }
+ $ignore{$r}=999999;
+ $ignore_used{$r}=0;
+ }
+}
+
sub checksrc_clear {
undef %ignore;
undef %ignore_set;
@@ -295,8 +348,9 @@ sub scanfile {
open(R, "<$file") || die "failed to open $file";
my $incomment=0;
- my $copyright=0;
+ my @copyright=();
checksrc_clear(); # for file based ignores
+ accept_violations();
while(<R>) {
$windows_os ? $_ =~ s/\r?\n$// : chomp;
@@ -310,9 +364,16 @@ sub scanfile {
checksrc($cmd, $line, $file, $l)
}
- # check for a copyright statement
- if(!$copyright && ($l =~ /copyright .* \d\d\d\d/i)) {
- $copyright=1;
+ # check for a copyright statement and save the years
+ if($l =~ /\* +copyright .* \d\d\d\d/i) {
+ while($l =~ /([\d]{4})/g) {
+ push @copyright, {
+ year => $1,
+ line => $line,
+ col => index($l, $1),
+ code => $l
+ };
+ }
}
# detect long lines
@@ -511,6 +572,13 @@ sub scanfile {
"use of $2 is banned");
}
+ # scan for use of snprintf for curl-internals reasons
+ if($l =~ /^(.*\W)(v?snprintf)\s*\(/x) {
+ checkwarn("SNPRINTF",
+ $line, length($1), $file, $ol,
+ "use of $2 is banned");
+ }
+
# scan for use of non-binary fopen without the macro
if($l =~ /^(.*\W)fopen\s*\([^,]*, *\"([^"]*)/) {
my $mode = $2;
@@ -623,9 +691,49 @@ sub scanfile {
$prevl = $ol;
}
- if(!$copyright) {
+ if(!scalar(@copyright)) {
checkwarn("COPYRIGHT", 1, 0, $file, "", "Missing copyright statement", 1);
}
+
+ # COPYRIGHTYEAR is a extended warning so we must first see if it has been
+ # enabled in .checksrc
+ if(defined($warnings{"COPYRIGHTYEAR"})) {
+ # The check for updated copyrightyear is overly complicated in order to
+ # not punish current hacking for past sins. The copyright years are
+ # right now a bit behind, so enforcing copyright year checking on all
+ # files would cause hundreds of errors. Instead we only look at files
+ # which are tracked in the Git repo and edited in the workdir, or
+ # committed locally on the branch without being in upstream master.
+ #
+ # The simple and naive test is to simply check for the current year,
+ # but updating the year even without an edit is against project policy
+ # (and it would fail every file on January 1st).
+ #
+ # A rather more interesting, and correct, check would be to not test
+ # only locally committed files but inspect all files wrt the year of
+ # their last commit. Removing the `git rev-list origin/master..HEAD`
+ # condition below will enfore copyright year checks against the year
+ # the file was last committed (and thus edited to some degree).
+ my $commityear = undef;
+ @copyright = sort {$$b{year} cmp $$a{year}} @copyright;
+
+ if(`git status -s -- $file` =~ /^ [MARCU]/) {
+ $commityear = (localtime(time))[5] + 1900;
+ }
+ elsif (`git rev-list --count origin/master..HEAD -- $file` !~ /^0/) {
+ my $grl = `git rev-list --max-count=1 --timestamp HEAD -- $file`;
+ $commityear = (localtime((split(/ /, $grl))[0]))[5] + 1900;
+ }
+
+ if(defined($commityear) && scalar(@copyright) &&
+ $copyright[0]{year} != $commityear) {
+ checkwarn("COPYRIGHTYEAR", $copyright[0]{line}, $copyright[0]{col},
+ $file, $copyright[0]{code},
+ "Copyright year out of date, should be $commityear, " .
+ "is $copyright[0]{year}", 1);
+ }
+ }
+
if($incomment) {
checkwarn("OPENCOMMENT", 1, 0, $file, "", "Missing closing comment", 1);
}
diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c
index 6fbf3b1d27..08e9042a6f 100644
--- a/libs/libcurl/src/conncache.c
+++ b/libs/libcurl/src/conncache.c
@@ -175,7 +175,7 @@ static void hashkey(struct connectdata *conn, char *buf,
DEBUGASSERT(len > 32);
/* put the number first so that the hostname gets cut off if too long */
- snprintf(buf, len, "%ld%s", conn->port, hostname);
+ msnprintf(buf, len, "%ld%s", conn->port, hostname);
}
void Curl_conncache_unlock(struct connectdata *conn)
diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c
index 41f2202681..ec3cd3a795 100644
--- a/libs/libcurl/src/connect.c
+++ b/libs/libcurl/src/connect.c
@@ -522,7 +522,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
err = 0;
}
#endif
-#ifdef __minix
+#if defined(EBADIOCTL) && defined(__minix)
/* Minix 3.1.x doesn't support getsockopt on UDP sockets */
if(EBADIOCTL == err) {
SET_SOCKERRNO(0);
@@ -655,7 +655,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
case AF_UNIX:
su = (struct sockaddr_un*)sa;
- snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+ msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
*port = 0;
return TRUE;
#endif
@@ -1314,7 +1314,7 @@ int Curl_closesocket(struct connectdata *conn,
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
else {
int rc;
- Curl_multi_closed(conn, sock);
+ Curl_multi_closed(conn->data, sock);
Curl_set_in_callback(conn->data, true);
rc = conn->fclosesocket(conn->closesocket_client, sock);
Curl_set_in_callback(conn->data, false);
@@ -1324,7 +1324,7 @@ int Curl_closesocket(struct connectdata *conn,
if(conn)
/* tell the multi-socket code about this */
- Curl_multi_closed(conn, sock);
+ Curl_multi_closed(conn->data, sock);
sclose(sock);
diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c
index 5b7ab66337..3dc85ee5ca 100644
--- a/libs/libcurl/src/cookie.c
+++ b/libs/libcurl/src/cookie.c
@@ -675,7 +675,10 @@ Curl_cookie_add(struct Curl_easy *data,
/* overflow, used max value */
co->expires = CURL_OFF_T_MAX;
else if(!offt) {
- if(CURL_OFF_T_MAX - now < co->expires)
+ if(!co->expires)
+ /* already expired */
+ co->expires = 1;
+ else if(CURL_OFF_T_MAX - now < co->expires)
/* would overflow */
co->expires = CURL_OFF_T_MAX;
else
@@ -1456,22 +1459,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
unsigned int j;
struct Cookie **array;
- if((NULL == c) || (0 == c->numcookies))
- /* If there are no known cookies, we don't write or even create any
- destination file */
- return 0;
-
/* at first, remove expired cookies */
remove_expired(c);
- /* make sure we still have cookies after expiration */
- if(0 == c->numcookies)
- return 0;
-
- array = malloc(sizeof(struct Cookie *) * c->numcookies);
- if(!array)
- return 1;
-
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
@@ -1480,7 +1470,6 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
else {
out = fopen(dumphere, FOPEN_WRITETEXT);
if(!out) {
- free(array);
return 1; /* failure */
}
}
@@ -1490,32 +1479,40 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
- j = 0;
- for(i = 0; i < COOKIE_HASH_SIZE; i++) {
- for(co = c->cookies[i]; co; co = co->next) {
- if(!co->domain)
- continue;
- array[j++] = co;
- }
- }
-
- qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
-
- for(i = 0; i < j; i++) {
- format_ptr = get_netscape_format(array[i]);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- free(array);
+ if(c->numcookies) {
+ array = malloc(sizeof(struct Cookie *) * c->numcookies);
+ if(!array) {
if(!use_stdout)
fclose(out);
return 1;
}
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
- }
- free(array);
+ j = 0;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(co = c->cookies[i]; co; co = co->next) {
+ if(!co->domain)
+ continue;
+ array[j++] = co;
+ }
+ }
+ qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+
+ for(i = 0; i < j; i++) {
+ format_ptr = get_netscape_format(array[i]);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ free(array);
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ }
+
+ free(array);
+ }
if(!use_stdout)
fclose(out);
diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in
index 477d61eb4a..781006f20f 100644
--- a/libs/libcurl/src/curl_config.h.in
+++ b/libs/libcurl/src/curl_config.h.in
@@ -175,9 +175,6 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
-/* Define to 1 if you have the `ENGINE_cleanup' function. */
-#undef HAVE_ENGINE_CLEANUP
-
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
@@ -928,9 +925,6 @@
/* Define to enable c-ares support */
#undef USE_ARES
-/* if axTLS is enabled */
-#undef USE_AXTLS
-
/* if CyaSSL/WolfSSL is enabled */
#undef USE_CYASSL
diff --git a/libs/libcurl/src/curl_gssapi.c b/libs/libcurl/src/curl_gssapi.c
index f007986c0d..d854ab0c7f 100644
--- a/libs/libcurl/src/curl_gssapi.c
+++ b/libs/libcurl/src/curl_gssapi.c
@@ -97,9 +97,9 @@ static size_t display_gss_error(OM_uint32 status, int type,
&msg_ctx,
&status_string);
if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
- len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
- "%.*s. ", (int)status_string.length,
- (char *)status_string.value);
+ len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
+ "%.*s. ", (int)status_string.length,
+ (char *)status_string.value);
}
gss_release_buffer(&min_stat, &status_string);
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
diff --git a/libs/libcurl/src/curl_multibyte.c b/libs/libcurl/src/curl_multibyte.c
index e78bb5002e..e48334faff 100644
--- a/libs/libcurl/src/curl_multibyte.c
+++ b/libs/libcurl/src/curl_multibyte.c
@@ -64,13 +64,13 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
char *str_utf8 = NULL;
if(str_w) {
- int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
- 0, NULL, NULL);
- if(str_utf8_len > 0) {
- str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+ int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
+ NULL, 0, NULL, NULL);
+ if(bytes > 0) {
+ str_utf8 = malloc(bytes);
if(str_utf8) {
- if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
- NULL, FALSE) == 0) {
+ if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
+ NULL, NULL) == 0) {
free(str_utf8);
return NULL;
}
diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c
index 922e85a926..9eb6c43c8c 100644
--- a/libs/libcurl/src/curl_ntlm_core.c
+++ b/libs/libcurl/src/curl_ntlm_core.c
@@ -54,23 +54,13 @@
#ifdef USE_OPENSSL
-# ifdef USE_OPENSSL
-# include <openssl/des.h>
-# ifndef OPENSSL_NO_MD4
-# include <openssl/md4.h>
-# endif
-# include <openssl/md5.h>
-# include <openssl/ssl.h>
-# include <openssl/rand.h>
-# else
-# include <des.h>
-# ifndef OPENSSL_NO_MD4
-# include <md4.h>
-# endif
-# include <md5.h>
-# include <ssl.h>
-# include <rand.h>
+# include <openssl/des.h>
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
# endif
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
# define DES_key_schedule des_key_schedule
# define DES_cblock des_cblock
@@ -753,12 +743,12 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
return CURLE_OUT_OF_MEMORY;
/* Create the BLOB structure */
- snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
- "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
- "%c%c%c%c", /* Reserved = 0 */
- NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
- NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
- 0, 0, 0, 0);
+ msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+ "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
+ "%c%c%c%c", /* Reserved = 0 */
+ NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
+ NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
+ 0, 0, 0, 0);
Curl_write64_le(tw, ptr + 24);
memcpy(ptr + 32, challenge_client, 8);
diff --git a/libs/libcurl/src/curl_printf.h b/libs/libcurl/src/curl_printf.h
index 49857cdb0d..0d37b8e572 100644
--- a/libs/libcurl/src/curl_printf.h
+++ b/libs/libcurl/src/curl_printf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
# undef printf
# undef fprintf
-# undef snprintf
+# undef msnprintf
# undef vprintf
# undef vfprintf
# undef vsnprintf
@@ -39,18 +39,10 @@
# undef vaprintf
# define printf curl_mprintf
# define fprintf curl_mfprintf
-# define snprintf curl_msnprintf
+# define msnprintf curl_msnprintf
# define vprintf curl_mvprintf
# define vfprintf curl_mvfprintf
-# define vsnprintf curl_mvsnprintf
+# define mvsnprintf curl_mvsnprintf
# define aprintf curl_maprintf
# define vaprintf curl_mvaprintf
-
-/* We define away the sprintf functions unconditonally since we don't want
- internal code to be using them, intentionally or by mistake!*/
-# undef sprintf
-# undef vsprintf
-# define sprintf sprintf_was_used
-# define vsprintf vsprintf_was_used
-
#endif /* HEADER_CURL_PRINTF_H */
diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h
index b84501556f..f83e1ea4f7 100644
--- a/libs/libcurl/src/curl_setup.h
+++ b/libs/libcurl/src/curl_setup.h
@@ -646,7 +646,7 @@ int netware_init(void);
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
- defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
+ defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
#define USE_SSL /* SSL support has been enabled */
diff --git a/libs/libcurl/src/curlx.h b/libs/libcurl/src/curlx.h
index 4c77d4f2e8..3e9b516f82 100644
--- a/libs/libcurl/src/curlx.h
+++ b/libs/libcurl/src/curlx.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -81,22 +81,21 @@
# undef printf
# undef fprintf
# undef sprintf
-# undef snprintf
+# undef msnprintf
# undef vprintf
# undef vfprintf
# undef vsprintf
-# undef vsnprintf
+# undef mvsnprintf
# undef aprintf
# undef vaprintf
# define printf curlx_mprintf
# define fprintf curlx_mfprintf
# define sprintf curlx_msprintf
-# define snprintf curlx_msnprintf
+# define msnprintf curlx_msnprintf
# define vprintf curlx_mvprintf
# define vfprintf curlx_mvfprintf
-# define vsprintf curlx_mvsprintf
-# define vsnprintf curlx_mvsnprintf
+# define mvsnprintf curlx_mvsnprintf
# define aprintf curlx_maprintf
# define vaprintf curlx_mvaprintf
#endif /* ENABLE_CURLX_PRINTF */
diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c
index ef6013db9d..1e76c96f91 100644
--- a/libs/libcurl/src/doh.c
+++ b/libs/libcurl/src/doh.c
@@ -26,13 +26,13 @@
#include "curl_addrinfo.h"
#include "doh.h"
-#ifdef USE_NGHTTP2
#include "sendf.h"
#include "multiif.h"
#include "url.h"
#include "share.h"
#include "curl_base64.h"
#include "connect.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -143,8 +143,8 @@ doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
/* suspiciously much for us */
return 0;
- mem->memory = realloc(mem->memory, mem->size + realsize);
- if(mem->memory == NULL)
+ mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
+ if(!mem->memory)
/* out of memory! */
return 0;
@@ -234,7 +234,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
}
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+#ifdef USE_NGHTTP2
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#endif
#ifndef CURLDEBUG
/* enforce HTTPS if not debug */
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
@@ -524,7 +526,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
if(dohlen < 12)
return DOH_TOO_SMALL_BUFFER; /* too small */
- if(doh[0] || doh[1])
+ if(!doh || doh[0] || doh[1])
return DOH_DNS_BAD_ID; /* bad ID */
rcode = doh[3] & 0x0f;
if(rcode)
@@ -660,13 +662,13 @@ static void showdoh(struct Curl_easy *data,
char buffer[128];
char *ptr;
size_t len;
- snprintf(buffer, 128, "DOH AAAA: ");
+ msnprintf(buffer, 128, "DOH AAAA: ");
ptr = &buffer[10];
len = 118;
for(j = 0; j < 16; j += 2) {
size_t l;
- snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
- d->addr[i].ip.v6[j + 1]);
+ msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+ d->addr[i].ip.v6[j + 1]);
l = strlen(ptr);
len -= l;
ptr += l;
@@ -853,7 +855,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
&de);
free(data->req.doh.probe[1].serverdoh.memory);
if(rc2) {
- infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+ infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
type2name(data->req.doh.probe[1].dnstype),
data->req.doh.host);
}
@@ -893,28 +895,3 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
return CURLE_OK;
}
-
-#else /* !USE_NGHTTP2 */
-/*
- */
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
-{
- (void)conn;
- (void)hostname;
- (void)port;
- (void)waitp;
- return NULL;
-}
-
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
- struct Curl_dns_entry **dnsp)
-{
- (void)conn;
- (void)dnsp;
- return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* USE_NGHTTP2 */
diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c
index 4de4e6522f..e592d7a71e 100644
--- a/libs/libcurl/src/easy.c
+++ b/libs/libcurl/src/easy.c
@@ -664,12 +664,12 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
while(!done && !mcode) {
int still_running = 0;
- int rc;
+ bool gotsocket = FALSE;
- mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
+ mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket);
if(!mcode) {
- if(!rc) {
+ if(!gotsocket) {
long sleep_ms;
/* If it returns without any filedescriptor instantly, we need to
@@ -688,6 +688,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
/* only read 'still_running' if curl_multi_perform() return OK */
if(!mcode && !still_running) {
+ int rc;
CURLMsg *msg = curl_multi_info_read(multi, &rc);
if(msg) {
result = msg->data.result;
@@ -966,7 +967,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
}
/* Clone the resolver handle, if present, for the new handle */
- if(Curl_resolver_duphandle(&outcurl->state.resolver,
+ if(Curl_resolver_duphandle(outcurl,
+ &outcurl->state.resolver,
data->state.resolver))
goto fail;
diff --git a/libs/libcurl/src/escape.c b/libs/libcurl/src/escape.c
index afd3899f9f..7121db31c2 100644
--- a/libs/libcurl/src/escape.c
+++ b/libs/libcurl/src/escape.c
@@ -122,7 +122,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
return NULL;
}
- snprintf(&ns[strindex], 4, "%%%02X", in);
+ msnprintf(&ns[strindex], 4, "%%%02X", in);
strindex += 3;
}
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c
index 722b55e9d2..8bba3b9165 100644
--- a/libs/libcurl/src/file.c
+++ b/libs/libcurl/src/file.c
@@ -417,8 +417,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
struct tm buffer;
const struct tm *tm = &buffer;
char header[80];
- snprintf(header, sizeof(header),
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+ msnprintf(header, sizeof(header),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+ expected_size);
result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
@@ -434,16 +435,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
return result;
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
- snprintf(header, sizeof(header),
- "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
- Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
- tm->tm_mday,
- Curl_month[tm->tm_mon],
- tm->tm_year + 1900,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec,
- data->set.opt_no_body ? "": "\r\n");
+ msnprintf(header, sizeof(header),
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ data->set.opt_no_body ? "": "\r\n");
result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index 793d991ccb..581df09d77 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -1272,7 +1272,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
source++;
}
*dest = 0;
- snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+ msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
if(result) {
@@ -2061,9 +2061,9 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
char timebuf[24];
time_t secs = time(NULL);
- snprintf(timebuf, sizeof(timebuf),
- "%04d%02d%02d %02d:%02d:%02d GMT",
- year, month, day, hour, minute, second);
+ msnprintf(timebuf, sizeof(timebuf),
+ "%04d%02d%02d %02d:%02d:%02d GMT",
+ year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
data->info.filetime = curl_getdate(timebuf, &secs);
}
@@ -2086,15 +2086,15 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
return result;
/* format: "Tue, 15 Nov 1994 12:45:26" */
- snprintf(headerbuf, sizeof(headerbuf),
- "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
- Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
- tm->tm_mday,
- Curl_month[tm->tm_mon],
- tm->tm_year + 1900,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec);
+ msnprintf(headerbuf, sizeof(headerbuf),
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
if(result)
return result;
@@ -2276,8 +2276,8 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(-1 != filesize) {
char clbuf[128];
- snprintf(clbuf, sizeof(clbuf),
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+ msnprintf(clbuf, sizeof(clbuf),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
if(result)
return result;
diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c
index 249fe09c84..1b1de5c3cd 100644
--- a/libs/libcurl/src/ftplistparser.c
+++ b/libs/libcurl/src/ftplistparser.c
@@ -405,7 +405,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->state.UNIX.main = PL_UNIX_FILETYPE;
/* start FSM again not considering size of directory */
finfo->b_used = 0;
- i--;
+ continue;
}
break;
case PL_UNIX_TOTALSIZE_READING:
diff --git a/libs/libcurl/src/hostcheck.c b/libs/libcurl/src/hostcheck.c
index c9d8112d86..6fcd0a9011 100644
--- a/libs/libcurl/src/hostcheck.c
+++ b/libs/libcurl/src/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,6 @@
#include "curl_setup.h"
#if defined(USE_OPENSSL) \
- || defined(USE_AXTLS) \
|| defined(USE_GSKIT) \
|| defined(USE_SCHANNEL)
/* these backends use functions from this file */
@@ -150,4 +149,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
return res;
}
-#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
+#endif /* OPENSSL, GSKIT or schannel+wince */
diff --git a/libs/libcurl/src/hostip4.c b/libs/libcurl/src/hostip4.c
index 9d6f115ae6..e6ba710d83 100644
--- a/libs/libcurl/src/hostip4.c
+++ b/libs/libcurl/src/hostip4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -145,7 +145,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
if(port) {
- snprintf(sbuf, sizeof(sbuf), "%d", port);
+ msnprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr = sbuf;
}
diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c
index 3bf47b467d..e06d0343a5 100644
--- a/libs/libcurl/src/hostip6.c
+++ b/libs/libcurl/src/hostip6.c
@@ -178,7 +178,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
#endif
if(port) {
- snprintf(sbuf, sizeof(sbuf), "%d", port);
+ msnprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr = sbuf;
}
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c
index 46ac15a6e2..345100f6c8 100644
--- a/libs/libcurl/src/http.c
+++ b/libs/libcurl/src/http.c
@@ -526,6 +526,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
+ if(data->state.authhost.picked == CURLAUTH_NTLM &&
+ conn->httpversion > 11) {
+ infof(data, "Forcing HTTP/1.1 for NTLM");
+ connclose(conn, "Force HTTP/1.1 connection");
+ conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ }
}
if(conn->bits.proxy_user_passwd &&
((data->req.httpcode == 407) ||
@@ -610,7 +616,6 @@ output_auth_headers(struct connectdata *conn,
result = Curl_output_negotiate(conn, proxy);
if(result)
return result;
- authstatus->done = TRUE;
negdata->state = GSS_AUTHSENT;
}
else
@@ -697,7 +702,7 @@ output_auth_headers(struct connectdata *conn,
*
* @param conn all information about the current connection
* @param request pointer to the request keyword
- * @param path pointer to the requested path
+ * @param path pointer to the requested path; should include query part
* @param proxytunnel boolean if this is the request setting up a "proxy
* tunnel"
*
@@ -1479,14 +1484,14 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
strcpy(tcp_version, "TCP4");
}
- snprintf(proxy_header,
- sizeof(proxy_header),
- "PROXY %s %s %s %li %li\r\n",
- tcp_version,
- conn->data->info.conn_local_ip,
- conn->data->info.conn_primary_ip,
- conn->data->info.conn_local_port,
- conn->data->info.conn_primary_port);
+ msnprintf(proxy_header,
+ sizeof(proxy_header),
+ "PROXY %s %s %s %li %li\r\n",
+ tcp_version,
+ conn->data->info.conn_local_ip,
+ conn->data->info.conn_primary_ip,
+ conn->data->info.conn_local_port,
+ conn->data->info.conn_primary_port);
req_buffer = Curl_add_buffer_init();
if(!req_buffer)
@@ -1850,16 +1855,16 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
*/
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
- snprintf(datestr, sizeof(datestr),
- "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
- condp,
- Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
- tm->tm_mday,
- Curl_month[tm->tm_mon],
- tm->tm_year + 1900,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec);
+ msnprintf(datestr, sizeof(datestr),
+ "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ condp,
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
@@ -1995,9 +2000,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, request, path, FALSE);
- if(result)
- return result;
+ {
+ char *pq = NULL;
+ if(query && *query) {
+ pq = aprintf("%s?%s", path, query);
+ if(!pq)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
+ free(pq);
+ if(result)
+ return result;
+ }
if((data->state.authhost.multipass || data->state.authproxy.multipass) &&
(httpreq != HTTPREQ_GET) &&
@@ -2293,8 +2307,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
*p++ = '/';
}
- snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
- data->set.prefer_ascii ? 'a' : 'i');
+ msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+ data->set.prefer_ascii ? 'a' : 'i');
}
}
if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
@@ -3652,13 +3666,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
switch(k->httpcode) {
- case 204:
- /* (quote from RFC2616, section 10.2.5): The server has
- * fulfilled the request but does not need to return an
- * entity-body ... The 204 response MUST NOT include a
- * message-body, and thus is always terminated by the first
- * empty line after the header fields. */
- /* FALLTHROUGH */
case 304:
/* (quote from RFC2616, section 10.3.5): The 304 response
* MUST NOT contain a message-body, and thus is always
@@ -3666,6 +3673,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* fields. */
if(data->set.timecondition)
data->info.timecond = TRUE;
+ /* FALLTHROUGH */
+ case 204:
+ /* (quote from RFC2616, section 10.2.5): The server has
+ * fulfilled the request but does not need to return an
+ * entity-body ... The 204 response MUST NOT include a
+ * message-body, and thus is always terminated by the first
+ * empty line after the header fields. */
k->size = 0;
k->maxdownload = 0;
k->ignorecl = TRUE; /* ignore Content-Length headers */
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
index 0c5f6db0b4..a61d8c2403 100644
--- a/libs/libcurl/src/http2.c
+++ b/libs/libcurl/src/http2.c
@@ -350,7 +350,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
int Curl_http2_ver(char *p, size_t len)
{
nghttp2_info *h2 = nghttp2_version(0);
- return snprintf(p, len, " nghttp2/%s", h2->version_str);
+ return msnprintf(p, len, " nghttp2/%s", h2->version_str);
}
/* HTTP/2 error code to name based on the Error Code Registry.
@@ -2367,6 +2367,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
Curl_http2_remove_child(data->set.stream_depends_on, data);
}
+/* Only call this function for a transfer that already got a HTTP/2
+ CURLE_HTTP2_STREAM error! */
+bool Curl_h2_http_1_1_error(struct connectdata *conn)
+{
+ struct http_conn *httpc = &conn->proto.httpc;
+ return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
+}
+
#else /* !USE_NGHTTP2 */
/* Satisfy external references even if http2 is not compiled in. */
diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h
index 4492ec2113..67db3dffb0 100644
--- a/libs/libcurl/src/http2.h
+++ b/libs/libcurl/src/http2.h
@@ -59,6 +59,9 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
void Curl_http2_remove_child(struct Curl_easy *parent,
struct Curl_easy *child);
void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
+
+/* 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
@@ -74,6 +77,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
+#define Curl_h2_http_1_1_error(x) 0
#endif
#endif /* HEADER_CURL_HTTP2_H */
diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c
index ddcd65b3b9..444265d11f 100644
--- a/libs/libcurl/src/http_negotiate.c
+++ b/libs/libcurl/src/http_negotiate.c
@@ -49,6 +49,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
/* Point to the correct struct with this */
struct negotiatedata *neg_ctx;
+ struct auth *authp;
if(proxy) {
userp = conn->http_proxy.user;
@@ -57,6 +58,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
host = conn->http_proxy.host.name;
neg_ctx = &data->state.proxyneg;
+ authp = &conn->data->state.authproxy;
}
else {
userp = conn->user;
@@ -65,6 +67,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
data->set.str[STRING_SERVICE_NAME] : "HTTP";
host = conn->host.name;
neg_ctx = &data->state.negotiate;
+ authp = &conn->data->state.authhost;
}
/* Not set means empty */
@@ -95,6 +98,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
if(result)
Curl_auth_spnego_cleanup(neg_ctx);
+ else
+ /* If the status is different than 0 and we encountered no errors
+ it means we have to continue. 0 is the OK value for both GSSAPI
+ (GSS_S_COMPLETE) and SSPI (SEC_E_OK) */
+ authp->done = !neg_ctx->status;
return result;
}
diff --git a/libs/libcurl/src/if2ip.c b/libs/libcurl/src/if2ip.c
index ce38ea117b..566061a564 100644
--- a/libs/libcurl/src/if2ip.c
+++ b/libs/libcurl/src/if2ip.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -169,7 +169,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
}
#endif
if(scopeid)
- snprintf(scope, sizeof(scope), "%%%u", scopeid);
+ msnprintf(scope, sizeof(scope), "%%%u", scopeid);
}
else
#endif
@@ -177,7 +177,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
&((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
res = IF2IP_FOUND;
ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
- snprintf(buf, buf_size, "%s%s", ip, scope);
+ msnprintf(buf, buf_size, "%s%s", ip, scope);
break;
}
}
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c
index 3ef89097f9..a8320e3f18 100644
--- a/libs/libcurl/src/imap.c
+++ b/libs/libcurl/src/imap.c
@@ -1749,8 +1749,8 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
imapc->cmdid = (imapc->cmdid + 1) % 1000;
/* Calculate the tag based on the connection ID and command ID */
- snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+ msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+ 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
/* Prefix the format with the tag */
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
diff --git a/libs/libcurl/src/inet_ntop.c b/libs/libcurl/src/inet_ntop.c
index ac5d2d4d6f..855981c666 100644
--- a/libs/libcurl/src/inet_ntop.c
+++ b/libs/libcurl/src/inet_ntop.c
@@ -55,11 +55,11 @@ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
DEBUGASSERT(size >= 16);
tmp[0] = '\0';
- (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
- ((int)((unsigned char)src[0])) & 0xff,
- ((int)((unsigned char)src[1])) & 0xff,
- ((int)((unsigned char)src[2])) & 0xff,
- ((int)((unsigned char)src[3])) & 0xff);
+ (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+ ((int)((unsigned char)src[0])) & 0xff,
+ ((int)((unsigned char)src[1])) & 0xff,
+ ((int)((unsigned char)src[2])) & 0xff,
+ ((int)((unsigned char)src[3])) & 0xff);
len = strlen(tmp);
if(len == 0 || len >= size) {
@@ -148,7 +148,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
tp += strlen(tp);
break;
}
- tp += snprintf(tp, 5, "%lx", words[i]);
+ tp += msnprintf(tp, 5, "%lx", words[i]);
}
/* Was it a trailing run of 0x00's?
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c
index ceaa71d089..a149f8cbc3 100644
--- a/libs/libcurl/src/ldap.c
+++ b/libs/libcurl/src/ldap.c
@@ -839,6 +839,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *path;
+ char *query;
char *p;
char *q;
size_t i;
@@ -846,7 +847,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
if(!conn->data ||
!conn->data->state.up.path ||
conn->data->state.up.path[0] != '/' ||
- !strcasecompare("LDAP", conn->data->state.up.scheme))
+ !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -858,11 +859,14 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
if(!path)
return LDAP_NO_MEMORY;
- /* Parse the DN (Distinguished Name) */
- q = strchr(p, '?');
- if(q)
- *q++ = '\0';
+ /* Duplicate the query */
+ q = query = strdup(conn->data->state.up.query);
+ if(!query) {
+ free(path);
+ return LDAP_NO_MEMORY;
+ }
+ /* Parse the DN (Distinguished Name) */
if(*p) {
char *dn = p;
char *unescaped;
@@ -1039,6 +1043,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
quit:
free(path);
+ free(query);
return rc;
}
diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist
index 54d0480bec..ca8d642076 100644
--- a/libs/libcurl/src/libcurl.plist
+++ b/libs/libcurl/src/libcurl.plist
@@ -15,7 +15,7 @@
<string>se.haxx.curl.libcurl</string>
<key>CFBundleVersion</key>
- <string>7.62.0</string>
+ <string>7.63.0</string>
<key>CFBundleName</key>
<string>libcurl</string>
@@ -27,9 +27,9 @@
<string>????</string>
<key>CFBundleShortVersionString</key>
- <string>libcurl 7.62.0</string>
+ <string>libcurl 7.63.0</string>
<key>CFBundleGetInfoString</key>
- <string>libcurl.plist 7.62.0</string>
+ <string>libcurl.plist 7.63.0</string>
</dict>
</plist>
diff --git a/libs/libcurl/src/libcurl.rc b/libs/libcurl/src/libcurl.rc
index 3316fba191..4839d0a651 100644
--- a/libs/libcurl/src/libcurl.rc
+++ b/libs/libcurl/src/libcurl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,22 +22,22 @@
#include <winver.h>
#include "../include/curl/curlver.h"
-LANGUAGE 0x09,0x01
+LANGUAGE 0, 0
#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
VS_VERSION_INFO VERSIONINFO
FILEVERSION RC_VERSION
PRODUCTVERSION RC_VERSION
- FILEFLAGSMASK 0x3fL
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#if defined(DEBUGBUILD) || defined(_DEBUG)
- FILEFLAGS 1
+ FILEFLAGS VS_FF_DEBUG
#else
- FILEFLAGS 0
+ FILEFLAGS 0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
- FILESUBTYPE 0x0L
+ FILESUBTYPE 0L
BEGIN
BLOCK "StringFileInfo"
diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c
index d350602163..4691904be4 100644
--- a/libs/libcurl/src/md4.c
+++ b/libs/libcurl/src/md4.c
@@ -1,4 +1,5 @@
/*
+ * !checksrc! disable COPYRIGHT
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD4 Message-Digest Algorithm (RFC 1320).
*
diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c
index 45f45bbd9e..a17a58fa61 100644
--- a/libs/libcurl/src/md5.c
+++ b/libs/libcurl/src/md5.c
@@ -163,13 +163,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
CryptReleaseContext(ctx->hCryptProv, 0);
}
-#elif defined(USE_AXTLS)
-#include <axTLS/config.h>
-#include <axTLS/os_int.h>
-#include <axTLS/crypto.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
#else
/* When no other crypto library is available we use this code segment */
/*
diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c
index 2b81c26a6f..05590a8f83 100644
--- a/libs/libcurl/src/memdebug.c
+++ b/libs/libcurl/src/memdebug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -504,7 +504,7 @@ void curl_memlog(const char *format, ...)
return;
va_start(ap, format);
- nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+ nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
va_end(ap);
if(nchars > LOGLINE_BUFSIZE - 1)
diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c
index d2d91d7438..e190936782 100644
--- a/libs/libcurl/src/mprintf.c
+++ b/libs/libcurl/src/mprintf.c
@@ -835,7 +835,7 @@ static int dprintf_formatf(
while(width-- > 0)
OUTCHAR(' ');
- while((len-- > 0) && *str)
+ for(; len && *str; len--)
OUTCHAR(*str++);
if(p->flags&FLAGS_LEFT)
while(width-- > 0)
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index 0db2a97308..56b3faf2fa 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -46,6 +46,7 @@
#include "vtls/vtls.h"
#include "connect.h"
#include "http_proxy.h"
+#include "http2.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -634,13 +635,13 @@ static CURLcode multi_done(struct connectdata **connp,
else {
char buffer[256];
/* create string before returning the connection */
- snprintf(buffer, sizeof(buffer),
- "Connection #%ld to host %s left intact",
- conn->connection_id,
- conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
- conn->bits.httpproxy ? conn->http_proxy.host.dispname :
- conn->bits.conn_to_host ? conn->conn_to_host.dispname :
- conn->host.dispname);
+ msnprintf(buffer, sizeof(buffer),
+ "Connection #%ld to host %s left intact",
+ conn->connection_id,
+ conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+ conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+ conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+ conn->host.dispname);
/* the connection is no longer in use by this transfer */
if(Curl_conncache_return_conn(conn)) {
@@ -985,11 +986,12 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
#define NUM_POLLS_ON_STACK 10
-CURLMcode curl_multi_wait(struct Curl_multi *multi,
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
- int *ret)
+ int *ret,
+ bool *gotsocket) /* if any socket was checked */
{
struct Curl_easy *data;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
@@ -1003,6 +1005,9 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
int retcode = 0;
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
+ if(gotsocket)
+ *gotsocket = FALSE;
+
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1135,9 +1140,21 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
free(ufds);
if(ret)
*ret = retcode;
+ if(gotsocket && (extra_fds || curlfds))
+ /* if any socket was checked */
+ *gotsocket = TRUE;
+
return CURLM_OK;
}
+CURLMcode curl_multi_wait(struct Curl_multi *multi,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret)
+{
+ 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
@@ -1337,8 +1354,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLMcode rc;
CURLcode result = CURLE_OK;
struct SingleRequest *k;
- time_t timeout_ms;
- time_t recv_timeout_ms;
+ timediff_t timeout_ms;
+ timediff_t recv_timeout_ms;
timediff_t send_timeout_ms;
int control;
@@ -1939,6 +1956,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
done = TRUE;
}
}
+ else if((CURLE_HTTP2_STREAM == result) &&
+ Curl_h2_http_1_1_error(data->easy_conn)) {
+ CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
+
+ infof(data, "Forcing HTTP/1.1 for NTLM");
+ data->set.httpversion = CURL_HTTP_VERSION_1_1;
+
+ if(!ret)
+ retry = (newurl)?TRUE:FALSE;
+ else
+ result = ret;
+
+ if(retry) {
+ /* if we are to retry, set the result to OK and consider the
+ request as done */
+ result = CURLE_OK;
+ done = TRUE;
+ }
+ }
if(result) {
/*
@@ -2466,11 +2502,11 @@ void Curl_updatesocket(struct Curl_easy *data)
* socket again and it gets the same file descriptor number.
*/
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
{
- if(conn->data) {
+ if(data) {
/* if there's still an easy handle associated with this connection */
- struct Curl_multi *multi = conn->data->multi;
+ struct Curl_multi *multi = data->multi;
if(multi) {
/* this is set if this connection is part of a handle that is added to
a multi handle, and only then this is necessary */
@@ -2478,7 +2514,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
if(entry) {
if(multi->socket_cb)
- multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+ multi->socket_cb(data, s, CURL_POLL_REMOVE,
multi->socket_userp,
entry->socketp);
diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h
index c8fb5ca0d1..e44646bf9d 100644
--- a/libs/libcurl/src/multiif.h
+++ b/libs/libcurl/src/multiif.h
@@ -89,7 +89,7 @@ void Curl_multi_connchanged(struct Curl_multi *multi);
* socket again and it gets the same file descriptor number.
*/
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s);
/*
* Add a handle and move it into PERFORM state at once. For pushed streams.
@@ -97,4 +97,12 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
struct Curl_easy *data,
struct connectdata *conn);
+
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret,
+ bool *gotsocket); /* if any socket was checked */
+
#endif /* HEADER_CURL_MULTIIF_H */
diff --git a/libs/libcurl/src/netrc.c b/libs/libcurl/src/netrc.c
index 1724b35b0b..aba355b760 100644
--- a/libs/libcurl/src/netrc.c
+++ b/libs/libcurl/src/netrc.c
@@ -53,6 +53,8 @@ enum host_lookup_state {
int Curl_parsenetrc(const char *host,
char **loginp,
char **passwordp,
+ bool *login_changed,
+ bool *password_changed,
char *netrcfile)
{
FILE *file;
@@ -164,7 +166,7 @@ int Curl_parsenetrc(const char *host,
if(specific_login) {
state_our_login = strcasecompare(login, tok);
}
- else {
+ else if(!login || strcmp(login, tok)) {
if(login_alloc) {
free(login);
login_alloc = FALSE;
@@ -179,7 +181,8 @@ int Curl_parsenetrc(const char *host,
state_login = 0;
}
else if(state_password) {
- if(state_our_login || !specific_login) {
+ if((state_our_login || !specific_login)
+ && (!password || strcmp(password, tok))) {
if(password_alloc) {
free(password);
password_alloc = FALSE;
@@ -211,15 +214,19 @@ int Curl_parsenetrc(const char *host,
out:
if(!retcode) {
+ *login_changed = FALSE;
+ *password_changed = FALSE;
if(login_alloc) {
if(*loginp)
free(*loginp);
*loginp = login;
+ *login_changed = TRUE;
}
if(password_alloc) {
if(*passwordp)
free(*passwordp);
*passwordp = password;
+ *password_changed = TRUE;
}
}
else {
diff --git a/libs/libcurl/src/netrc.h b/libs/libcurl/src/netrc.h
index d980166e6b..fe3dc357ec 100644
--- a/libs/libcurl/src/netrc.h
+++ b/libs/libcurl/src/netrc.h
@@ -26,6 +26,8 @@
int Curl_parsenetrc(const char *host,
char **loginp,
char **passwordp,
+ bool *login_changed,
+ bool *password_changed,
char *filename);
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine
diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c
index c6cb794343..bc007883e3 100644
--- a/libs/libcurl/src/openldap.c
+++ b/libs/libcurl/src/openldap.c
@@ -220,8 +220,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
ptr = hosturl + 4;
if(conn->handler->flags & PROTOPT_SSL)
*ptr++ = 's';
- snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
- conn->host.name, conn->remote_port);
+ msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+ conn->host.name, conn->remote_port);
#ifdef CURL_OPENLDAP_DEBUG
static int do_trace = 0;
diff --git a/libs/libcurl/src/openssl.c b/libs/libcurl/src/openssl.c
deleted file mode 100644
index 7e1b681b2b..0000000000
--- a/libs/libcurl/src/openssl.c
+++ /dev/null
@@ -1,3661 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/*
- * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- */
-
-/*
- * The original SSLeay-using code for curl was written by Linas Vepstas and
- * Sampo Kellomaki 1998.
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_OPENSSL
-
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#include "urldata.h"
-#include "sendf.h"
-#include "formdata.h" /* for the boundary function */
-#include "url.h" /* for the ssl config check function */
-#include "inet_pton.h"
-#include "openssl.h"
-#include "connect.h"
-#include "slist.h"
-#include "select.h"
-#include "vtls/vtls.h"
-#include "strcase.h"
-#include "hostcheck.h"
-#include "curl_printf.h"
-#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-#include <openssl/rand.h>
-#include <openssl/x509v3.h>
-#ifndef OPENSSL_NO_DSA
-#include <openssl/dsa.h>
-#endif
-#include <openssl/dh.h>
-#include <openssl/err.h>
-#include <openssl/md5.h>
-#include <openssl/conf.h>
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-#include <openssl/bio.h>
-#include <openssl/buffer.h>
-
-#ifndef OPENSSL_IS_BORINGSSL
-/* BoringSSL does not support PKCS12 */
-#define HAVE_PKCS12_SUPPORT 1
-#include <openssl/pkcs12.h>
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
-#include <openssl/ocsp.h>
-#endif
-
-#include "warnless.h"
-#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
-
-/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
-
-#ifndef OPENSSL_VERSION_NUMBER
-#error "OPENSSL_VERSION_NUMBER not defined"
-#endif
-
-#if defined(HAVE_OPENSSL_ENGINE_H)
-#include <openssl/ui.h>
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
-#define SSL_METHOD_QUAL const
-#else
-#define SSL_METHOD_QUAL
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
-#define HAVE_ERR_REMOVE_THREAD_STATE 1
-#endif
-
-#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \
- OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */
-#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */
-#define OPENSSL_NO_SSL2
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
- !defined(LIBRESSL_VERSION_NUMBER)
-#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
-#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
-#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
-#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */
-#define CONST_EXTS const
-#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
-#else
-/* For OpenSSL before 1.1.0 */
-#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
-#define X509_get0_notBefore(x) X509_get_notBefore(x)
-#define X509_get0_notAfter(x) X509_get_notAfter(x)
-#define CONST_EXTS /* nope */
-#ifdef LIBRESSL_VERSION_NUMBER
-static unsigned long OpenSSL_version_num(void)
-{
- return LIBRESSL_VERSION_NUMBER;
-}
-#else
-#define OpenSSL_version_num() SSLeay()
-#endif
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
- !defined(LIBRESSL_VERSION_NUMBER)
-#define HAVE_X509_GET0_SIGNATURE 1
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \
- OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \
- !defined(OPENSSL_NO_COMP)
-#define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1
-#endif
-
-#if (OPENSSL_VERSION_NUMBER < 0x0090808fL)
-/* not present in older OpenSSL */
-#define OPENSSL_load_builtin_modules(x)
-#endif
-
-/*
- * Whether SSL_CTX_set_keylog_callback is available.
- * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
- * BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
- * lies and pretends to be OpenSSL 2.0.0).
- */
-#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
- !defined(LIBRESSL_VERSION_NUMBER)) || \
- defined(OPENSSL_IS_BORINGSSL)
-#define HAVE_KEYLOG_CALLBACK
-#endif
-
-#if defined(LIBRESSL_VERSION_NUMBER)
-#define OSSL_PACKAGE "LibreSSL"
-#elif defined(OPENSSL_IS_BORINGSSL)
-#define OSSL_PACKAGE "BoringSSL"
-#else
-#define OSSL_PACKAGE "OpenSSL"
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-/* up2date versions of OpenSSL maintain the default reasonably secure without
- * breaking compatibility, so it is better not to override the default by curl
- */
-#define DEFAULT_CIPHER_SELECTION NULL
-#else
-/* ... but it is not the case with old versions of OpenSSL */
-#define DEFAULT_CIPHER_SELECTION \
- "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
-#endif
-
-#ifdef ENABLE_SSLKEYLOGFILE
-typedef struct ssl_tap_state {
- int master_key_length;
- unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
- unsigned char client_random[SSL3_RANDOM_SIZE];
-} ssl_tap_state_t;
-#endif /* ENABLE_SSLKEYLOGFILE */
-
-struct ssl_backend_data {
- /* these ones requires specific SSL-types */
- SSL_CTX* ctx;
- SSL* handle;
- X509* server_cert;
-#ifdef ENABLE_SSLKEYLOGFILE
- /* tap_state holds the last seen master key if we're logging them */
- ssl_tap_state_t tap_state;
-#endif
-};
-
-#define BACKEND connssl->backend
-
-/*
- * Number of bytes to read from the random number seed file. This must be
- * a finite value (because some entropy "files" like /dev/urandom have
- * an infinite length), but must be large enough to provide enough
- * entropy to properly seed OpenSSL's PRNG.
- */
-#define RAND_LOAD_LENGTH 1024
-
-#ifdef ENABLE_SSLKEYLOGFILE
-/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
-static FILE *keylog_file_fp;
-
-#ifdef HAVE_KEYLOG_CALLBACK
-static void ossl_keylog_callback(const SSL *ssl, const char *line)
-{
- (void)ssl;
-
- /* Using fputs here instead of fprintf since libcurl's fprintf replacement
- may not be thread-safe. */
- if(keylog_file_fp && line && *line) {
- char stackbuf[256];
- char *buf;
- size_t linelen = strlen(line);
-
- if(linelen <= sizeof(stackbuf) - 2)
- buf = stackbuf;
- else {
- buf = malloc(linelen + 2);
- if(!buf)
- return;
- }
- strncpy(buf, line, linelen);
- buf[linelen] = '\n';
- buf[linelen + 1] = '\0';
-
- fputs(buf, keylog_file_fp);
- if(buf != stackbuf)
- free(buf);
- }
-}
-#else
-#define KEYLOG_PREFIX "CLIENT_RANDOM "
-#define KEYLOG_PREFIX_LEN (sizeof(KEYLOG_PREFIX) - 1)
-/*
- * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL
- * being used doesn't have native support for doing that.
- */
-static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
-{
- const char *hex = "0123456789ABCDEF";
- int pos, i;
- char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 +
- 2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1];
- const SSL_SESSION *session = SSL_get_session(ssl);
- unsigned char client_random[SSL3_RANDOM_SIZE];
- unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
- int master_key_length = 0;
-
- if(!session || !keylog_file_fp)
- return;
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
- * we have a valid SSL context if we have a non-NULL session. */
- SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
- master_key_length =
- SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
-#else
- if(ssl->s3 && session->master_key_length > 0) {
- master_key_length = session->master_key_length;
- memcpy(master_key, session->master_key, session->master_key_length);
- memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE);
- }
-#endif
-
- if(master_key_length <= 0)
- return;
-
- /* Skip writing keys if there is no key or it did not change. */
- if(state->master_key_length == master_key_length &&
- !memcmp(state->master_key, master_key, master_key_length) &&
- !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) {
- return;
- }
-
- state->master_key_length = master_key_length;
- memcpy(state->master_key, master_key, master_key_length);
- memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE);
-
- memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN);
- pos = KEYLOG_PREFIX_LEN;
-
- /* Client Random for SSLv3/TLS */
- for(i = 0; i < SSL3_RANDOM_SIZE; i++) {
- line[pos++] = hex[client_random[i] >> 4];
- line[pos++] = hex[client_random[i] & 0xF];
- }
- line[pos++] = ' ';
-
- /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */
- for(i = 0; i < master_key_length; i++) {
- line[pos++] = hex[master_key[i] >> 4];
- line[pos++] = hex[master_key[i] & 0xF];
- }
- line[pos++] = '\n';
- line[pos] = '\0';
-
- /* Using fputs here instead of fprintf since libcurl's fprintf replacement
- may not be thread-safe. */
- fputs(line, keylog_file_fp);
-}
-#endif /* !HAVE_KEYLOG_CALLBACK */
-#endif /* ENABLE_SSLKEYLOGFILE */
-
-static const char *SSL_ERROR_to_str(int err)
-{
- switch(err) {
- case SSL_ERROR_NONE:
- return "SSL_ERROR_NONE";
- case SSL_ERROR_SSL:
- return "SSL_ERROR_SSL";
- case SSL_ERROR_WANT_READ:
- return "SSL_ERROR_WANT_READ";
- case SSL_ERROR_WANT_WRITE:
- return "SSL_ERROR_WANT_WRITE";
- case SSL_ERROR_WANT_X509_LOOKUP:
- return "SSL_ERROR_WANT_X509_LOOKUP";
- case SSL_ERROR_SYSCALL:
- return "SSL_ERROR_SYSCALL";
- case SSL_ERROR_ZERO_RETURN:
- return "SSL_ERROR_ZERO_RETURN";
- case SSL_ERROR_WANT_CONNECT:
- return "SSL_ERROR_WANT_CONNECT";
- case SSL_ERROR_WANT_ACCEPT:
- return "SSL_ERROR_WANT_ACCEPT";
-#if defined(SSL_ERROR_WANT_ASYNC)
- case SSL_ERROR_WANT_ASYNC:
- return "SSL_ERROR_WANT_ASYNC";
-#endif
-#if defined(SSL_ERROR_WANT_ASYNC_JOB)
- case SSL_ERROR_WANT_ASYNC_JOB:
- return "SSL_ERROR_WANT_ASYNC_JOB";
-#endif
-#if defined(SSL_ERROR_WANT_EARLY)
- case SSL_ERROR_WANT_EARLY:
- return "SSL_ERROR_WANT_EARLY";
-#endif
- default:
- return "SSL_ERROR unknown";
- }
-}
-
-/* Return error string for last OpenSSL error
- */
-static char *ossl_strerror(unsigned long error, char *buf, size_t size)
-{
- ERR_error_string_n(error, buf, size);
- return buf;
-}
-
-static int passwd_callback(char *buf, int num, int encrypting,
- void *global_passwd)
-{
- DEBUGASSERT(0 == encrypting);
-
- if(!encrypting) {
- int klen = curlx_uztosi(strlen((char *)global_passwd));
- if(num > klen) {
- memcpy(buf, global_passwd, klen + 1);
- return klen;
- }
- }
- return 0;
-}
-
-/*
- * rand_enough() returns TRUE if we have seeded the random engine properly.
- */
-static bool rand_enough(void)
-{
- return (0 != RAND_status()) ? TRUE : FALSE;
-}
-
-static CURLcode Curl_ossl_seed(struct Curl_easy *data)
-{
- /* we have the "SSL is seeded" boolean static to prevent multiple
- time-consuming seedings in vain */
- static bool ssl_seeded = FALSE;
- char fname[256];
-
- if(ssl_seeded)
- return CURLE_OK;
-
- if(rand_enough()) {
- /* OpenSSL 1.1.0+ will return here */
- ssl_seeded = TRUE;
- return CURLE_OK;
- }
-
-#ifndef RANDOM_FILE
- /* if RANDOM_FILE isn't defined, we only perform this if an option tells
- us to! */
- if(data->set.str[STRING_SSL_RANDOM_FILE])
-#define RANDOM_FILE "" /* doesn't matter won't be used */
-#endif
- {
- /* let the option override the define */
- RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
- data->set.str[STRING_SSL_RANDOM_FILE]:
- RANDOM_FILE),
- RAND_LOAD_LENGTH);
- if(rand_enough())
- return CURLE_OK;
- }
-
-#if defined(HAVE_RAND_EGD)
- /* only available in OpenSSL 0.9.5 and later */
- /* EGD_SOCKET is set at configure time or not at all */
-#ifndef EGD_SOCKET
- /* If we don't have the define set, we only do this if the egd-option
- is set */
- if(data->set.str[STRING_SSL_EGDSOCKET])
-#define EGD_SOCKET "" /* doesn't matter won't be used */
-#endif
- {
- /* If there's an option and a define, the option overrides the
- define */
- int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
- data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
- if(-1 != ret) {
- if(rand_enough())
- return CURLE_OK;
- }
- }
-#endif
-
- /* fallback to a custom seeding of the PRNG using a hash based on a current
- time */
- do {
- unsigned char randb[64];
- size_t len = sizeof(randb);
- size_t i, i_max;
- for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) {
- struct curltime tv = Curl_now();
- Curl_wait_ms(1);
- tv.tv_sec *= i + 1;
- tv.tv_usec *= (unsigned int)i + 2;
- tv.tv_sec ^= ((Curl_now().tv_sec + Curl_now().tv_usec) *
- (i + 3)) << 8;
- tv.tv_usec ^= (unsigned int) ((Curl_now().tv_sec +
- Curl_now().tv_usec) *
- (i + 4)) << 16;
- memcpy(&randb[i * sizeof(struct curltime)], &tv,
- sizeof(struct curltime));
- }
- RAND_add(randb, (int)len, (double)len/2);
- } while(!rand_enough());
-
- /* generates a default path for the random seed file */
- fname[0] = 0; /* blank it first */
- RAND_file_name(fname, sizeof(fname));
- if(fname[0]) {
- /* we got a file name to try */
- RAND_load_file(fname, RAND_LOAD_LENGTH);
- if(rand_enough())
- return CURLE_OK;
- }
-
- infof(data, "libcurl is now using a weak random seed!\n");
- return (rand_enough() ? CURLE_OK :
- CURLE_SSL_CONNECT_ERROR /* confusing error code */);
-}
-
-#ifndef SSL_FILETYPE_ENGINE
-#define SSL_FILETYPE_ENGINE 42
-#endif
-#ifndef SSL_FILETYPE_PKCS12
-#define SSL_FILETYPE_PKCS12 43
-#endif
-static int do_file_type(const char *type)
-{
- if(!type || !type[0])
- return SSL_FILETYPE_PEM;
- if(strcasecompare(type, "PEM"))
- return SSL_FILETYPE_PEM;
- if(strcasecompare(type, "DER"))
- return SSL_FILETYPE_ASN1;
- if(strcasecompare(type, "ENG"))
- return SSL_FILETYPE_ENGINE;
- if(strcasecompare(type, "P12"))
- return SSL_FILETYPE_PKCS12;
- return -1;
-}
-
-#if defined(HAVE_OPENSSL_ENGINE_H)
-/*
- * Supply default password to the engine user interface conversation.
- * The password is passed by OpenSSL engine from ENGINE_load_private_key()
- * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
- */
-static int ssl_ui_reader(UI *ui, UI_STRING *uis)
-{
- const char *password;
- switch(UI_get_string_type(uis)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- password = (const char *)UI_get0_user_data(ui);
- if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
- UI_set_result(ui, uis, password);
- return 1;
- }
- default:
- break;
- }
- return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
-}
-
-/*
- * Suppress interactive request for a default password if available.
- */
-static int ssl_ui_writer(UI *ui, UI_STRING *uis)
-{
- switch(UI_get_string_type(uis)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- if(UI_get0_user_data(ui) &&
- (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
- return 1;
- }
- default:
- break;
- }
- return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
-}
-#endif
-
-static
-int cert_stuff(struct connectdata *conn,
- SSL_CTX* ctx,
- char *cert_file,
- const char *cert_type,
- char *key_file,
- const char *key_type,
- char *key_passwd)
-{
- struct Curl_easy *data = conn->data;
- char error_buffer[256];
- bool check_privkey = TRUE;
-
- int file_type = do_file_type(cert_type);
-
- if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) {
- SSL *ssl;
- X509 *x509;
- int cert_done = 0;
-
- if(key_passwd) {
- /* set the password in the callback userdata */
- SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
- /* Set passwd callback: */
- SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
- }
-
-
- switch(file_type) {
- case SSL_FILETYPE_PEM:
- /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
- if(SSL_CTX_use_certificate_chain_file(ctx,
- cert_file) != 1) {
- failf(data,
- "could not load PEM client certificate, " OSSL_PACKAGE
- " error %s, "
- "(no key found, wrong pass phrase, or wrong file format?)",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- return 0;
- }
- break;
-
- case SSL_FILETYPE_ASN1:
- /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
- we use the case above for PEM so this can only be performed with
- ASN1 files. */
- if(SSL_CTX_use_certificate_file(ctx,
- cert_file,
- file_type) != 1) {
- failf(data,
- "could not load ASN1 client certificate, " OSSL_PACKAGE
- " error %s, "
- "(no key found, wrong pass phrase, or wrong file format?)",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- return 0;
- }
- break;
- case SSL_FILETYPE_ENGINE:
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
- {
- if(data->state.engine) {
- const char *cmd_name = "LOAD_CERT_CTRL";
- struct {
- const char *cert_id;
- X509 *cert;
- } params;
-
- params.cert_id = cert_file;
- params.cert = NULL;
-
- /* Does the engine supports LOAD_CERT_CTRL ? */
- if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
- 0, (void *)cmd_name, NULL)) {
- failf(data, "ssl engine does not support loading certificates");
- return 0;
- }
-
- /* Load the certificate from the engine */
- if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name,
- 0, &params, NULL, 1)) {
- failf(data, "ssl engine cannot load client cert with id"
- " '%s' [%s]", cert_file,
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return 0;
- }
-
- if(!params.cert) {
- failf(data, "ssl engine didn't initialized the certificate "
- "properly.");
- return 0;
- }
-
- if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
- failf(data, "unable to set client certificate");
- X509_free(params.cert);
- return 0;
- }
- X509_free(params.cert); /* we don't need the handle any more... */
- }
- else {
- failf(data, "crypto engine not set, can't load certificate");
- return 0;
- }
- }
- break;
-#else
- failf(data, "file type ENG for certificate not implemented");
- return 0;
-#endif
-
- case SSL_FILETYPE_PKCS12:
- {
-#ifdef HAVE_PKCS12_SUPPORT
- FILE *f;
- PKCS12 *p12;
- EVP_PKEY *pri;
- STACK_OF(X509) *ca = NULL;
-
- f = fopen(cert_file, "rb");
- if(!f) {
- failf(data, "could not open PKCS12 file '%s'", cert_file);
- return 0;
- }
- p12 = d2i_PKCS12_fp(f, NULL);
- fclose(f);
-
- if(!p12) {
- failf(data, "error reading PKCS12 file '%s'", cert_file);
- return 0;
- }
-
- PKCS12_PBE_add();
-
- if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
- &ca)) {
- failf(data,
- "could not parse PKCS12 file, check password, " OSSL_PACKAGE
- " error %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- PKCS12_free(p12);
- return 0;
- }
-
- PKCS12_free(p12);
-
- if(SSL_CTX_use_certificate(ctx, x509) != 1) {
- failf(data,
- "could not load PKCS12 client certificate, " OSSL_PACKAGE
- " error %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- goto fail;
- }
-
- if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
- failf(data, "unable to use private key from PKCS12 file '%s'",
- cert_file);
- goto fail;
- }
-
- if(!SSL_CTX_check_private_key (ctx)) {
- failf(data, "private key from PKCS12 file '%s' "
- "does not match certificate in same file", cert_file);
- goto fail;
- }
- /* Set Certificate Verification chain */
- if(ca) {
- while(sk_X509_num(ca)) {
- /*
- * Note that sk_X509_pop() is used below to make sure the cert is
- * removed from the stack properly before getting passed to
- * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously
- * we used sk_X509_value() instead, but then we'd clean it in the
- * subsequent sk_X509_pop_free() call.
- */
- X509 *x = sk_X509_pop(ca);
- if(!SSL_CTX_add_client_CA(ctx, x)) {
- X509_free(x);
- failf(data, "cannot add certificate to client CA list");
- goto fail;
- }
- if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
- X509_free(x);
- failf(data, "cannot add certificate to certificate chain");
- goto fail;
- }
- }
- }
-
- cert_done = 1;
- fail:
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
-
- if(!cert_done)
- return 0; /* failure! */
- break;
-#else
- failf(data, "file type P12 for certificate not supported");
- return 0;
-#endif
- }
- default:
- failf(data, "not supported file type '%s' for certificate", cert_type);
- return 0;
- }
-
- 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) {
- failf(data, "unable to set private key file: '%s' type %s",
- key_file, key_type?key_type:"PEM");
- return 0;
- }
- break;
- case SSL_FILETYPE_ENGINE:
-#ifdef HAVE_OPENSSL_ENGINE_H
- { /* XXXX still needs some work */
- EVP_PKEY *priv_key = NULL;
- if(data->state.engine) {
- UI_METHOD *ui_method =
- UI_create_method((char *)"curl user interface");
- if(!ui_method) {
- failf(data, "unable do create " OSSL_PACKAGE
- " user-interface method");
- return 0;
- }
- UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
- UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
- UI_method_set_reader(ui_method, ssl_ui_reader);
- UI_method_set_writer(ui_method, ssl_ui_writer);
- /* the typecast below was added to please mingw32 */
- priv_key = (EVP_PKEY *)
- ENGINE_load_private_key(data->state.engine, key_file,
- ui_method,
- key_passwd);
- UI_destroy_method(ui_method);
- if(!priv_key) {
- failf(data, "failed to load private key from crypto engine");
- return 0;
- }
- if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
- failf(data, "unable to set private key");
- EVP_PKEY_free(priv_key);
- return 0;
- }
- EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
- }
- else {
- failf(data, "crypto engine not set, can't load private key");
- return 0;
- }
- }
- break;
-#else
- failf(data, "file type ENG for private key not supported");
- return 0;
-#endif
- case SSL_FILETYPE_PKCS12:
- if(!cert_done) {
- failf(data, "file type P12 for private key not supported");
- return 0;
- }
- break;
- default:
- failf(data, "not supported file type for private key");
- return 0;
- }
-
- ssl = SSL_new(ctx);
- if(!ssl) {
- failf(data, "unable to create an SSL structure");
- return 0;
- }
-
- x509 = SSL_get_certificate(ssl);
-
- /* This version was provided by Evan Jordan and is supposed to not
- leak memory as the previous version: */
- if(x509) {
- EVP_PKEY *pktmp = X509_get_pubkey(x509);
- EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl));
- EVP_PKEY_free(pktmp);
- }
-
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL)
- {
- /* If RSA is used, don't check the private key if its flags indicate
- * it doesn't support it. */
- EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
- int pktype;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- pktype = EVP_PKEY_id(priv_key);
-#else
- pktype = priv_key->type;
-#endif
- if(pktype == EVP_PKEY_RSA) {
- RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
- if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
- check_privkey = FALSE;
- RSA_free(rsa); /* Decrement reference count */
- }
- }
-#endif
-
- SSL_free(ssl);
-
- /* If we are using DSA, we can copy the parameters from
- * the private key */
-
- if(check_privkey == TRUE) {
- /* Now we know that a key and cert have been set against
- * the SSL context */
- if(!SSL_CTX_check_private_key(ctx)) {
- failf(data, "Private key does not match the certificate public key");
- return 0;
- }
- }
- }
- return 1;
-}
-
-/* returns non-zero on failure */
-static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
-{
-#if 0
- return X509_NAME_oneline(a, buf, size);
-#else
- BIO *bio_out = BIO_new(BIO_s_mem());
- BUF_MEM *biomem;
- int rc;
-
- if(!bio_out)
- return 1; /* alloc failed! */
-
- rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
- BIO_get_mem_ptr(bio_out, &biomem);
-
- if((size_t)biomem->length < size)
- size = biomem->length;
- else
- size--; /* don't overwrite the buffer end */
-
- memcpy(buf, biomem->data, size);
- buf[size] = 0;
-
- BIO_free(bio_out);
-
- return !rc;
-#endif
-}
-
-/**
- * Global SSL init
- *
- * @retval 0 error initializing SSL
- * @retval 1 SSL initialized successfully
- */
-static int Curl_ossl_init(void)
-{
-#ifdef ENABLE_SSLKEYLOGFILE
- const char *keylog_file_name;
-#endif
-
- OPENSSL_load_builtin_modules();
-
-#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
- ENGINE_load_builtin_engines();
-#endif
-
- /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately
- that function makes an exit() call on wrongly formatted config files
- which makes it hard to use in some situations. OPENSSL_config() itself
- calls CONF_modules_load_file() and we use that instead and we ignore
- its return code! */
-
- /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and
- 0.9.8e */
-#ifndef CONF_MFLAGS_DEFAULT_SECTION
-#define CONF_MFLAGS_DEFAULT_SECTION 0x0
-#endif
-
- CONF_modules_load_file(NULL, NULL,
- CONF_MFLAGS_DEFAULT_SECTION|
- CONF_MFLAGS_IGNORE_MISSING_FILE);
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
- /* OpenSSL 1.1.0+ takes care of initialization itself */
-#else
- /* Lets get nice error messages */
- SSL_load_error_strings();
-
- /* Init the global ciphers and digests */
- if(!SSLeay_add_ssl_algorithms())
- return 0;
-
- OpenSSL_add_all_algorithms();
-#endif
-
-#ifdef ENABLE_SSLKEYLOGFILE
- keylog_file_name = curl_getenv("SSLKEYLOGFILE");
- if(keylog_file_name && !keylog_file_fp) {
- keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
- if(keylog_file_fp) {
- if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) {
- fclose(keylog_file_fp);
- keylog_file_fp = NULL;
- }
- }
- }
-#endif
-
- return 1;
-}
-
-/* Global cleanup */
-static void Curl_ossl_cleanup(void)
-{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
- /* OpenSSL 1.1 deprecates all these cleanup functions and
- turns them into no-ops in OpenSSL 1.0 compatibility mode */
-#else
- /* Free ciphers and digests lists */
- EVP_cleanup();
-
-#ifdef HAVE_ENGINE_CLEANUP
- /* Free engine list */
- ENGINE_cleanup();
-#endif
-
- /* Free OpenSSL error strings */
- ERR_free_strings();
-
- /* Free thread local error state, destroying hash upon zero refcount */
-#ifdef HAVE_ERR_REMOVE_THREAD_STATE
- ERR_remove_thread_state(NULL);
-#else
- ERR_remove_state(0);
-#endif
-
- /* Free all memory allocated by all configuration modules */
- CONF_modules_free();
-
-#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS
- SSL_COMP_free_compression_methods();
-#endif
-#endif
-
-#ifdef ENABLE_SSLKEYLOGFILE
- if(keylog_file_fp) {
- fclose(keylog_file_fp);
- keylog_file_fp = NULL;
- }
-#endif
-}
-
-/*
- * This function is used 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_ossl_check_cxn(struct connectdata *conn)
-{
- /* SSL_peek takes data out of the raw recv buffer without peeking so we use
- recv MSG_PEEK instead. Bug #795 */
-#ifdef MSG_PEEK
- char buf;
- ssize_t nread;
- nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
- (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK);
- if(nread == 0)
- return 0; /* connection has been closed */
- if(nread == 1)
- return 1; /* connection still in place */
- else if(nread == -1) {
- int err = SOCKERRNO;
- if(err == EINPROGRESS ||
-#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK)
- err == EAGAIN ||
-#endif
- err == EWOULDBLOCK)
- return 1; /* connection still in place */
- if(err == ECONNRESET ||
-#ifdef ECONNABORTED
- err == ECONNABORTED ||
-#endif
-#ifdef ENETDOWN
- err == ENETDOWN ||
-#endif
-#ifdef ENETRESET
- err == ENETRESET ||
-#endif
-#ifdef ESHUTDOWN
- err == ESHUTDOWN ||
-#endif
-#ifdef ETIMEDOUT
- err == ETIMEDOUT ||
-#endif
- err == ENOTCONN)
- return 0; /* connection has been closed */
- }
-#endif
- return -1; /* connection status unknown */
-}
-
-/* Selects an OpenSSL crypto engine
- */
-static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
- const char *engine)
-{
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
- ENGINE *e;
-
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
- e = ENGINE_by_id(engine);
-#else
- /* avoid memory leak */
- for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
- const char *e_id = ENGINE_get_id(e);
- if(!strcmp(engine, e_id))
- break;
- }
-#endif
-
- if(!e) {
- failf(data, "SSL Engine '%s' not found", engine);
- return CURLE_SSL_ENGINE_NOTFOUND;
- }
-
- if(data->state.engine) {
- ENGINE_finish(data->state.engine);
- ENGINE_free(data->state.engine);
- data->state.engine = NULL;
- }
- if(!ENGINE_init(e)) {
- char buf[256];
-
- ENGINE_free(e);
- failf(data, "Failed to initialise SSL Engine '%s':\n%s",
- engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
- return CURLE_SSL_ENGINE_INITFAILED;
- }
- data->state.engine = e;
- return CURLE_OK;
-#else
- (void)engine;
- failf(data, "SSL Engine not supported");
- return CURLE_SSL_ENGINE_NOTFOUND;
-#endif
-}
-
-/* Sets engine as default for all SSL operations
- */
-static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
-{
-#ifdef HAVE_OPENSSL_ENGINE_H
- if(data->state.engine) {
- if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
- infof(data, "set default crypto engine '%s'\n",
- ENGINE_get_id(data->state.engine));
- }
- else {
- failf(data, "set default crypto engine '%s' failed",
- ENGINE_get_id(data->state.engine));
- return CURLE_SSL_ENGINE_SETFAILED;
- }
- }
-#else
- (void) data;
-#endif
- return CURLE_OK;
-}
-
-/* Return list of OpenSSL crypto engine names.
- */
-static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
-{
- struct curl_slist *list = NULL;
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
- struct curl_slist *beg;
- ENGINE *e;
-
- for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
- beg = curl_slist_append(list, ENGINE_get_id(e));
- if(!beg) {
- curl_slist_free_all(list);
- return NULL;
- }
- list = beg;
- }
-#endif
- (void) data;
- return list;
-}
-
-
-static void ossl_close(struct ssl_connect_data *connssl)
-{
- if(BACKEND->handle) {
- (void)SSL_shutdown(BACKEND->handle);
- SSL_set_connect_state(BACKEND->handle);
-
- SSL_free(BACKEND->handle);
- BACKEND->handle = NULL;
- }
- if(BACKEND->ctx) {
- SSL_CTX_free(BACKEND->ctx);
- BACKEND->ctx = NULL;
- }
-}
-
-/*
- * This function is called when an SSL connection is closed.
- */
-static void Curl_ossl_close(struct connectdata *conn, int sockindex)
-{
- ossl_close(&conn->ssl[sockindex]);
- ossl_close(&conn->proxy_ssl[sockindex]);
-}
-
-/*
- * This function is called to shut down the SSL layer but keep the
- * socket open (CCC - Clear Command Channel)
- */
-static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
-{
- int retval = 0;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
- char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
- to be at least 256 bytes long. */
- unsigned long sslerror;
- ssize_t nread;
- int buffsize;
- int err;
- int done = 0;
-
- /* This has only been tested on the proftpd server, and the mod_tls code
- sends a close notify alert without waiting for a close notify alert in
- response. Thus we wait for a close notify alert from the server, but
- we do not send one. Let's hope other servers do the same... */
-
- if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- (void)SSL_shutdown(BACKEND->handle);
-
- if(BACKEND->handle) {
- buffsize = (int)sizeof(buf);
- while(!done) {
- int what = SOCKET_READABLE(conn->sock[sockindex],
- SSL_SHUTDOWN_TIMEOUT);
- if(what > 0) {
- ERR_clear_error();
-
- /* Something to read, let's do it and hope that it is the close
- notify alert from the server */
- nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
- err = SSL_get_error(BACKEND->handle, (int)nread);
-
- switch(err) {
- case SSL_ERROR_NONE: /* this is not an error */
- case SSL_ERROR_ZERO_RETURN: /* no more data */
- /* This is the expected response. There was no data but only
- the close notify alert */
- done = 1;
- break;
- case SSL_ERROR_WANT_READ:
- /* there's data pending, re-invoke SSL_read() */
- infof(data, "SSL_ERROR_WANT_READ\n");
- break;
- case SSL_ERROR_WANT_WRITE:
- /* SSL wants a write. Really odd. Let's bail out. */
- infof(data, "SSL_ERROR_WANT_WRITE\n");
- done = 1;
- break;
- default:
- /* openssl/ssl.h says "look at error stack/return value/errno" */
- sslerror = ERR_get_error();
- failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
- (sslerror ?
- ossl_strerror(sslerror, buf, sizeof(buf)) :
- SSL_ERROR_to_str(err)),
- SOCKERRNO);
- done = 1;
- break;
- }
- }
- else if(0 == what) {
- /* timeout */
- failf(data, "SSL shutdown timeout");
- done = 1;
- }
- else {
- /* anything that gets here is fatally bad */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- retval = -1;
- done = 1;
- }
- } /* while()-loop for the select() */
-
- if(data->set.verbose) {
-#ifdef HAVE_SSL_GET_SHUTDOWN
- switch(SSL_get_shutdown(BACKEND->handle)) {
- case SSL_SENT_SHUTDOWN:
- infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
- break;
- case SSL_RECEIVED_SHUTDOWN:
- infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
- break;
- case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
- infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
- "SSL_RECEIVED__SHUTDOWN\n");
- break;
- }
-#endif
- }
-
- SSL_free(BACKEND->handle);
- BACKEND->handle = NULL;
- }
- return retval;
-}
-
-static void Curl_ossl_session_free(void *ptr)
-{
- /* free the ID */
- SSL_SESSION_free(ptr);
-}
-
-/*
- * This function is called when the 'data' struct is going away. Close
- * down everything and free all resources!
- */
-static void Curl_ossl_close_all(struct Curl_easy *data)
-{
-#ifdef HAVE_OPENSSL_ENGINE_H
- if(data->state.engine) {
- ENGINE_finish(data->state.engine);
- ENGINE_free(data->state.engine);
- data->state.engine = NULL;
- }
-#else
- (void)data;
-#endif
-#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \
- defined(HAVE_ERR_REMOVE_THREAD_STATE)
- /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread
- so we need to clean it here in case the thread will be killed. All OpenSSL
- code should extract the error in association with the error so clearing
- this queue here should be harmless at worst. */
- ERR_remove_thread_state(NULL);
-#endif
-}
-
-/* ====================================================== */
-
-
-/* Quote from RFC2818 section 3.1 "Server Identity"
-
- If a subjectAltName extension of type dNSName is present, that MUST
- be used as the identity. Otherwise, the (most specific) Common Name
- field in the Subject field of the certificate MUST be used. Although
- the use of the Common Name is existing practice, it is deprecated and
- Certification Authorities are encouraged to use the dNSName instead.
-
- Matching is performed using the matching rules specified by
- [RFC2459]. If more than one identity of a given type is present in
- the certificate (e.g., more than one dNSName name, a match in any one
- of the set is considered acceptable.) Names may contain the wildcard
- character * which is considered to match any single domain name
- component or component fragment. E.g., *.a.com matches foo.a.com but
- not bar.foo.a.com. f*.com matches foo.com but not bar.com.
-
- In some cases, the URI is specified as an IP address rather than a
- hostname. In this case, the iPAddress subjectAltName must be present
- in the certificate and must exactly match the IP in the URI.
-
-*/
-static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
-{
- bool matched = FALSE;
- int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
- size_t addrlen = 0;
- struct Curl_easy *data = conn->data;
- STACK_OF(GENERAL_NAME) *altnames;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
- CURLcode result = CURLE_OK;
- bool dNSName = FALSE; /* if a dNSName field exists in the cert */
- bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
-
-#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, hostname, &addr)) {
- target = GEN_IPADD;
- addrlen = sizeof(struct in6_addr);
- }
- else
-#endif
- if(Curl_inet_pton(AF_INET, hostname, &addr)) {
- target = GEN_IPADD;
- addrlen = sizeof(struct in_addr);
- }
-
- /* get a "list" of alternative names */
- altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
-
- if(altnames) {
- int numalts;
- int i;
- bool dnsmatched = FALSE;
- bool ipmatched = FALSE;
-
- /* get amount of alternatives, RFC2459 claims there MUST be at least
- one, but we don't depend on it... */
- numalts = sk_GENERAL_NAME_num(altnames);
-
- /* loop through all alternatives - until a dnsmatch */
- for(i = 0; (i < numalts) && !dnsmatched; i++) {
- /* get a handle to alternative name number i */
- const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
-
- if(check->type == GEN_DNS)
- dNSName = TRUE;
- else if(check->type == GEN_IPADD)
- iPAddress = TRUE;
-
- /* only check alternatives of the same type the target is */
- if(check->type == target) {
- /* get data and length */
- const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5);
- size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
-
- switch(target) {
- case GEN_DNS: /* name/pattern comparison */
- /* The OpenSSL man page explicitly says: "In general it cannot be
- assumed that the data returned by ASN1_STRING_data() is null
- terminated or does not contain embedded nulls." But also that
- "The actual format of the data will depend on the actual string
- type itself: for example for and IA5String the data will be ASCII"
-
- Gisle researched the OpenSSL sources:
- "I checked the 0.9.6 and 0.9.8 sources before my patch and
- it always 0-terminates an IA5String."
- */
- if((altlen == strlen(altptr)) &&
- /* if this isn't true, there was an embedded zero in the name
- string and we cannot match it. */
- Curl_cert_hostcheck(altptr, hostname)) {
- dnsmatched = TRUE;
- infof(data,
- " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
- dispname, altptr);
- }
- break;
-
- case GEN_IPADD: /* IP address comparison */
- /* compare alternative IP address if the data chunk is the same size
- our server IP address is */
- if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
- ipmatched = TRUE;
- infof(data,
- " subjectAltName: host \"%s\" matched cert's IP address!\n",
- dispname);
- }
- break;
- }
- }
- }
- GENERAL_NAMES_free(altnames);
-
- if(dnsmatched || ipmatched)
- matched = TRUE;
- }
-
- if(matched)
- /* an alternative name matched */
- ;
- else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s\n", dispname);
- failf(data, "SSL: no alternative certificate subject name matches "
- "target host name '%s'", dispname);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else {
- /* we have to look to the last occurrence of a commonName in the
- distinguished one to get the most significant one. */
- int j, i = -1;
-
- /* The following is done because of a bug in 0.9.6b */
-
- unsigned char *nulstr = (unsigned char *)"";
- unsigned char *peer_CN = nulstr;
-
- X509_NAME *name = X509_get_subject_name(server_cert);
- if(name)
- while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
- i = j;
-
- /* we have the name entry and we will now convert this to a string
- that we can use for comparison. Doing this we support BMPstring,
- UTF8 etc. */
-
- if(i >= 0) {
- ASN1_STRING *tmp =
- X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
-
- /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
- is already UTF-8 encoded. We check for this case and copy the raw
- string manually to avoid the problem. This code can be made
- conditional in the future when OpenSSL has been fixed. Work-around
- brought by Alexis S. L. Carvalho. */
- if(tmp) {
- if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if(j >= 0) {
- peer_CN = OPENSSL_malloc(j + 1);
- if(peer_CN) {
- memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j);
- peer_CN[j] = '\0';
- }
- }
- }
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
-
- if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) {
- /* there was a terminating zero before the end of string, this
- cannot match and we return failure! */
- failf(data, "SSL: illegal cert name field");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- }
- }
-
- if(peer_CN == nulstr)
- peer_CN = NULL;
- else {
- /* convert peer_CN from UTF8 */
- CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN,
- strlen((char *)peer_CN));
- /* Curl_convert_from_utf8 calls failf if unsuccessful */
- if(rc) {
- OPENSSL_free(peer_CN);
- return rc;
- }
- }
-
- if(result)
- /* error already detected, pass through */
- ;
- else if(!peer_CN) {
- failf(data,
- "SSL: unable to obtain common name from peer certificate");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
- failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, dispname);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else {
- infof(data, " common name: %s (matched)\n", peer_CN);
- }
- if(peer_CN)
- OPENSSL_free(peer_CN);
- }
-
- return result;
-}
-
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
-static CURLcode verifystatus(struct connectdata *conn,
- struct ssl_connect_data *connssl)
-{
- int i, ocsp_status;
- const unsigned char *p;
- CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
- OCSP_RESPONSE *rsp = NULL;
- OCSP_BASICRESP *br = NULL;
- X509_STORE *st = NULL;
- STACK_OF(X509) *ch = NULL;
-
- long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p);
-
- if(!p) {
- failf(data, "No OCSP response received");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
- if(!rsp) {
- failf(data, "Invalid OCSP response");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- ocsp_status = OCSP_response_status(rsp);
- if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
- failf(data, "Invalid OCSP response status: %s (%d)",
- OCSP_response_status_str(ocsp_status), ocsp_status);
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- br = OCSP_response_get1_basic(rsp);
- if(!br) {
- failf(data, "Invalid OCSP response");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- ch = SSL_get_peer_cert_chain(BACKEND->handle);
- st = SSL_CTX_get_cert_store(BACKEND->ctx);
-
-#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
- (defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
- /* The authorized responder cert in the OCSP response MUST be signed by the
- peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
- no problem, but if it's an intermediate cert OpenSSL has a bug where it
- expects this issuer to be present in the chain embedded in the OCSP
- response. So we add it if necessary. */
-
- /* First make sure the peer cert chain includes both a peer and an issuer,
- and the OCSP response contains a responder cert. */
- if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) {
- X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1);
-
- /* Find issuer of responder cert and add it to the OCSP response chain */
- for(i = 0; i < sk_X509_num(ch); i++) {
- X509 *issuer = sk_X509_value(ch, i);
- if(X509_check_issued(issuer, responder) == X509_V_OK) {
- if(!OCSP_basic_add1_cert(br, issuer)) {
- failf(data, "Could not add issuer cert to OCSP response");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
- }
- }
- }
-#endif
-
- if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
- failf(data, "OCSP response verification failed");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- for(i = 0; i < OCSP_resp_count(br); i++) {
- int cert_status, crl_reason;
- OCSP_SINGLERESP *single = NULL;
-
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
-
- single = OCSP_resp_get0(br, i);
- if(!single)
- continue;
-
- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
- &thisupd, &nextupd);
-
- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
- failf(data, "OCSP response has expired");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
-
- infof(data, "SSL certificate status: %s (%d)\n",
- OCSP_cert_status_str(cert_status), cert_status);
-
- switch(cert_status) {
- case V_OCSP_CERTSTATUS_GOOD:
- break;
-
- case V_OCSP_CERTSTATUS_REVOKED:
- result = CURLE_SSL_INVALIDCERTSTATUS;
-
- failf(data, "SSL certificate revocation reason: %s (%d)",
- OCSP_crl_reason_str(crl_reason), crl_reason);
- goto end;
-
- case V_OCSP_CERTSTATUS_UNKNOWN:
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
- }
-
-end:
- if(br) OCSP_BASICRESP_free(br);
- OCSP_RESPONSE_free(rsp);
-
- return result;
-}
-#endif
-
-#endif /* USE_OPENSSL */
-
-/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions
- and thus this cannot be done there. */
-#ifdef SSL_CTRL_SET_MSG_CALLBACK
-
-static const char *ssl_msg_type(int ssl_ver, int msg)
-{
-#ifdef SSL2_VERSION_MAJOR
- if(ssl_ver == SSL2_VERSION_MAJOR) {
- switch(msg) {
- case SSL2_MT_ERROR:
- return "Error";
- case SSL2_MT_CLIENT_HELLO:
- return "Client hello";
- case SSL2_MT_CLIENT_MASTER_KEY:
- return "Client key";
- case SSL2_MT_CLIENT_FINISHED:
- return "Client finished";
- case SSL2_MT_SERVER_HELLO:
- return "Server hello";
- case SSL2_MT_SERVER_VERIFY:
- return "Server verify";
- case SSL2_MT_SERVER_FINISHED:
- return "Server finished";
- case SSL2_MT_REQUEST_CERTIFICATE:
- return "Request CERT";
- case SSL2_MT_CLIENT_CERTIFICATE:
- return "Client CERT";
- }
- }
- else
-#endif
- if(ssl_ver == SSL3_VERSION_MAJOR) {
- switch(msg) {
- case SSL3_MT_HELLO_REQUEST:
- return "Hello request";
- case SSL3_MT_CLIENT_HELLO:
- return "Client hello";
- case SSL3_MT_SERVER_HELLO:
- return "Server hello";
-#ifdef SSL3_MT_NEWSESSION_TICKET
- case SSL3_MT_NEWSESSION_TICKET:
- return "Newsession Ticket";
-#endif
- case SSL3_MT_CERTIFICATE:
- return "Certificate";
- case SSL3_MT_SERVER_KEY_EXCHANGE:
- return "Server key exchange";
- case SSL3_MT_CLIENT_KEY_EXCHANGE:
- return "Client key exchange";
- case SSL3_MT_CERTIFICATE_REQUEST:
- return "Request CERT";
- case SSL3_MT_SERVER_DONE:
- return "Server finished";
- case SSL3_MT_CERTIFICATE_VERIFY:
- return "CERT verify";
- case SSL3_MT_FINISHED:
- return "Finished";
-#ifdef SSL3_MT_CERTIFICATE_STATUS
- case SSL3_MT_CERTIFICATE_STATUS:
- return "Certificate Status";
-#endif
- }
- }
- return "Unknown";
-}
-
-static const char *tls_rt_type(int type)
-{
- switch(type) {
-#ifdef SSL3_RT_HEADER
- case SSL3_RT_HEADER:
- return "TLS header";
-#endif
- case SSL3_RT_CHANGE_CIPHER_SPEC:
- return "TLS change cipher";
- case SSL3_RT_ALERT:
- return "TLS alert";
- case SSL3_RT_HANDSHAKE:
- return "TLS handshake";
- case SSL3_RT_APPLICATION_DATA:
- return "TLS app data";
- default:
- return "TLS Unknown";
- }
-}
-
-
-/*
- * Our callback from the SSL/TLS layers.
- */
-static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
- const void *buf, size_t len, SSL *ssl,
- void *userp)
-{
- struct Curl_easy *data;
- const char *msg_name, *tls_rt_name;
- char ssl_buf[1024];
- char unknown[32];
- int msg_type, txt_len;
- const char *verstr = NULL;
- struct connectdata *conn = userp;
-
- if(!conn || !conn->data || !conn->data->set.fdebug ||
- (direction != 0 && direction != 1))
- return;
-
- data = conn->data;
-
- switch(ssl_ver) {
-#ifdef SSL2_VERSION /* removed in recent versions */
- case SSL2_VERSION:
- verstr = "SSLv2";
- break;
-#endif
-#ifdef SSL3_VERSION
- case SSL3_VERSION:
- verstr = "SSLv3";
- break;
-#endif
- case TLS1_VERSION:
- verstr = "TLSv1.0";
- break;
-#ifdef TLS1_1_VERSION
- case TLS1_1_VERSION:
- verstr = "TLSv1.1";
- break;
-#endif
-#ifdef TLS1_2_VERSION
- case TLS1_2_VERSION:
- verstr = "TLSv1.2";
- break;
-#endif
-#ifdef TLS1_3_VERSION
- case TLS1_3_VERSION:
- verstr = "TLSv1.3";
- break;
-#endif
- case 0:
- break;
- default:
- snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
- verstr = unknown;
- break;
- }
-
- if(ssl_ver) {
- /* the info given when the version is zero is not that useful for us */
-
- ssl_ver >>= 8; /* check the upper 8 bits only below */
-
- /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL
- * always pass-up content-type as 0. But the interesting message-type
- * is at 'buf[0]'.
- */
- if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
- tls_rt_name = tls_rt_type(content_type);
- else
- tls_rt_name = "";
-
- msg_type = *(char *)buf;
- msg_name = ssl_msg_type(ssl_ver, msg_type);
-
- txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
- verstr, direction?"OUT":"IN",
- tls_rt_name, msg_name, msg_type);
- Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
- }
-
- Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
- CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
- (void) ssl;
-}
-#endif
-
-#ifdef USE_OPENSSL
-/* ====================================================== */
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-# define use_sni(x) sni = (x)
-#else
-# define use_sni(x) Curl_nop_stmt
-#endif
-
-/* Check for OpenSSL 1.0.2 which has ALPN support. */
-#undef HAS_ALPN
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
- && !defined(OPENSSL_NO_TLSEXT)
-# define HAS_ALPN 1
-#endif
-
-/* Check for OpenSSL 1.0.1 which has NPN support. */
-#undef HAS_NPN
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L \
- && !defined(OPENSSL_NO_TLSEXT) \
- && !defined(OPENSSL_NO_NEXTPROTONEG)
-# define HAS_NPN 1
-#endif
-
-#ifdef HAS_NPN
-
-/*
- * in is a list of length prefixed strings. this function has to select
- * the protocol we want to use from the list and write its string into out.
- */
-
-static int
-select_next_protocol(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const char *key, unsigned int keylen)
-{
- unsigned int i;
- for(i = 0; i + keylen <= inlen; i += in[i] + 1) {
- if(memcmp(&in[i + 1], key, keylen) == 0) {
- *out = (unsigned char *) &in[i + 1];
- *outlen = in[i];
- return 0;
- }
- }
- return -1;
-}
-
-static int
-select_next_proto_cb(SSL *ssl,
- unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- void *arg)
-{
- struct connectdata *conn = (struct connectdata*) arg;
-
- (void)ssl;
-
-#ifdef USE_NGHTTP2
- if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
- infof(conn->data, "NPN, negotiated HTTP2 (%s)\n",
- NGHTTP2_PROTO_VERSION_ID);
- conn->negnpn = CURL_HTTP_VERSION_2;
- return SSL_TLSEXT_ERR_OK;
- }
-#endif
-
- if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
- ALPN_HTTP_1_1_LENGTH)) {
- infof(conn->data, "NPN, negotiated HTTP1.1\n");
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- return SSL_TLSEXT_ERR_OK;
- }
-
- infof(conn->data, "NPN, no overlap, use HTTP1.1\n");
- *out = (unsigned char *)ALPN_HTTP_1_1;
- *outlen = ALPN_HTTP_1_1_LENGTH;
- conn->negnpn = CURL_HTTP_VERSION_1_1;
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif /* HAS_NPN */
-
-static const char *
-get_ssl_version_txt(SSL *ssl)
-{
- if(!ssl)
- return "";
-
- switch(SSL_version(ssl)) {
-#ifdef TLS1_3_VERSION
- case TLS1_3_VERSION:
- return "TLSv1.3";
-#endif
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- case TLS1_2_VERSION:
- return "TLSv1.2";
- case TLS1_1_VERSION:
- return "TLSv1.1";
-#endif
- case TLS1_VERSION:
- return "TLSv1.0";
- case SSL3_VERSION:
- return "SSLv3";
- case SSL2_VERSION:
- return "SSLv2";
- }
- return "unknown";
-}
-
-static CURLcode
-set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
- int sockindex)
-{
-#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
- /* convoluted #if condition just to avoid compiler warnings on unused
- variable */
- struct Curl_easy *data = conn->data;
-#endif
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
-
- if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
- ssl_version_max = ssl_version << 16;
- }
-
- switch(ssl_version) {
- case CURL_SSLVERSION_TLSv1_3:
-#ifdef TLS1_3_VERSION
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION);
- *ctx_options |= SSL_OP_NO_TLSv1_2;
- }
-#else
- (void)sockindex;
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
-#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_TLSv1_2:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_1;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_TLSv1_1:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
- return CURLE_NOT_BUILT_IN;
-#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_TLSv1_0:
- *ctx_options |= SSL_OP_NO_SSLv2;
- *ctx_options |= SSL_OP_NO_SSLv3;
- break;
- }
-
- switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_TLSv1_0:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_1;
-#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_MAX_TLSv1_1:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_2;
-#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_MAX_TLSv1_2:
- case CURL_SSLVERSION_MAX_DEFAULT:
-#ifdef TLS1_3_VERSION
- *ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
- break;
- case CURL_SSLVERSION_MAX_TLSv1_3:
-#ifdef TLS1_3_VERSION
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
-#endif
- }
- return CURLE_OK;
-}
-
-static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
-{
- CURLcode result = CURLE_OK;
- char *ciphers;
- struct Curl_easy *data = conn->data;
- SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
- X509_LOOKUP *lookup = NULL;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long ctx_options = 0;
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- bool sni;
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
-#endif
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
- const long int ssl_version = SSL_CONN_CONFIG(version);
-#ifdef USE_TLS_SRP
- const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
-#endif
- char * const ssl_cert = SSL_SET_OPTION(cert);
- const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
- const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
- char error_buffer[256];
-
- DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
-
- /* Make funny stuff to get random input */
- result = Curl_ossl_seed(data);
- if(result)
- return result;
-
- *certverifyresult = !X509_V_OK;
-
- /* check to see if we've been told to use an explicit SSL/TLS version */
-
- switch(ssl_version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- /* it will be handled later with the context options */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
- req_method = TLS_client_method();
-#else
- req_method = SSLv23_client_method();
-#endif
- use_sni(TRUE);
- break;
- case CURL_SSLVERSION_SSLv2:
-#ifdef OPENSSL_NO_SSL2
- failf(data, OSSL_PACKAGE " was built without SSLv2 support");
- return CURLE_NOT_BUILT_IN;
-#else
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP)
- return CURLE_SSL_CONNECT_ERROR;
-#endif
- req_method = SSLv2_client_method();
- use_sni(FALSE);
- break;
-#endif
- case CURL_SSLVERSION_SSLv3:
-#ifdef OPENSSL_NO_SSL3_METHOD
- failf(data, OSSL_PACKAGE " was built without SSLv3 support");
- return CURLE_NOT_BUILT_IN;
-#else
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP)
- return CURLE_SSL_CONNECT_ERROR;
-#endif
- req_method = SSLv3_client_method();
- use_sni(FALSE);
- break;
-#endif
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- if(BACKEND->ctx)
- SSL_CTX_free(BACKEND->ctx);
- BACKEND->ctx = SSL_CTX_new(req_method);
-
- if(!BACKEND->ctx) {
- failf(data, "SSL: couldn't create a context: %s",
- ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
- return CURLE_OUT_OF_MEMORY;
- }
-
-#ifdef SSL_MODE_RELEASE_BUFFERS
- SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
-
-#ifdef SSL_CTRL_SET_MSG_CALLBACK
- if(data->set.fdebug && data->set.verbose) {
- /* the SSL trace callback is only used for verbose logging */
- SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace);
- SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn);
- }
-#endif
-
- /* OpenSSL contains code to work-around lots of bugs and flaws in various
- SSL-implementations. SSL_CTX_set_options() is used to enabled those
- work-arounds. The man page for this option states that SSL_OP_ALL enables
- all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
- enable the bug workaround options if compatibility with somewhat broken
- implementations is desired."
-
- The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
- disable "rfc4507bis session ticket support". rfc4507bis was later turned
- into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077
-
- The enabled extension concerns the session management. I wonder how often
- libcurl stops a connection and then resumes a TLS session. also, sending
- the session data is some overhead. .I suggest that you just use your
- proposed patch (which explicitly disables TICKET).
-
- If someone writes an application with libcurl and openssl who wants to
- enable the feature, one can do this in the SSL callback.
-
- SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
- interoperability with web server Netscape Enterprise Server 2.0.1 which
- was released back in 1996.
-
- Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has
- become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate
- CVE-2010-4180 when using previous OpenSSL versions we no longer enable
- this option regardless of OpenSSL version and SSL_OP_ALL definition.
-
- OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability
- (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to
- SSL_OP_ALL that _disables_ that work-around despite the fact that
- SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to
- keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit
- must not be set.
- */
-
- ctx_options = SSL_OP_ALL;
-
-#ifdef SSL_OP_NO_TICKET
- ctx_options |= SSL_OP_NO_TICKET;
-#endif
-
-#ifdef SSL_OP_NO_COMPRESSION
- ctx_options |= SSL_OP_NO_COMPRESSION;
-#endif
-
-#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
- /* mitigate CVE-2010-4180 */
- ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
-#endif
-
-#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
- /* unless the user explicitly ask to allow the protocol vulnerability we
- use the work-around */
- if(!SSL_SET_OPTION(enable_beast))
- ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
-#endif
-
- switch(ssl_version) {
- case CURL_SSLVERSION_SSLv3:
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP) {
- infof(data, "Set version TLSv1.x for SRP authorisation\n");
- }
-#endif
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_TLSv1;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
-#endif
- break;
-
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- break;
-
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
- if(result != CURLE_OK)
- return result;
- break;
-
- case CURL_SSLVERSION_SSLv2:
-#ifndef OPENSSL_NO_SSL2
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
-#endif
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without SSLv2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
-
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- SSL_CTX_set_options(BACKEND->ctx, ctx_options);
-
-#ifdef HAS_NPN
- if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn);
-#endif
-
-#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- int cur = 0;
- unsigned char protocols[128];
-
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
- protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
-
- memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN);
- cur += NGHTTP2_PROTO_VERSION_ID_LEN;
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
- }
-#endif
-
- protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
-
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
- SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur);
- }
-#endif
-
- if(ssl_cert || ssl_cert_type) {
- if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type,
- SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
- SSL_SET_OPTION(key_passwd))) {
- /* failf() is already done in cert_stuff() */
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- ciphers = SSL_CONN_CONFIG(cipher_list);
- if(!ciphers)
- ciphers = (char *)DEFAULT_CIPHER_SELECTION;
- if(ciphers) {
- if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
- failf(data, "failed setting cipher list: %s", ciphers);
- return CURLE_SSL_CIPHER;
- }
- infof(data, "Cipher selection: %s\n", ciphers);
- }
-
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP) {
- char * const ssl_username = SSL_SET_OPTION(username);
-
- infof(data, "Using TLS-SRP username: %s\n", ssl_username);
-
- if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) {
- failf(data, "Unable to set SRP user name");
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
- if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) {
- failf(data, "failed setting SRP password");
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
- if(!SSL_CONN_CONFIG(cipher_list)) {
- infof(data, "Setting cipher list SRP\n");
-
- if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) {
- failf(data, "failed setting SRP cipher list");
- return CURLE_SSL_CIPHER;
- }
- }
- }
-#endif
-
- if(ssl_cafile || ssl_capath) {
- /* tell SSL where to find CA certificates that are used to verify
- the servers certificate. */
- if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
- if(verifypeer) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return CURLE_SSL_CACERT_BADFILE;
- }
- /* Just continue with a warning if no strict certificate verification
- is required. */
- infof(data, "error setting certificate verify locations,"
- " continuing anyway:\n");
- }
- else {
- /* Everything is fine. */
- infof(data, "successfully set certificate verify locations:\n");
- }
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else if(verifypeer) {
- /* verfying the peer without any CA certificates won't
- work so use openssl's built in default as fallback */
- SSL_CTX_set_default_verify_paths(BACKEND->ctx);
- }
-#endif
-
- if(ssl_crlfile) {
- /* tell SSL where to find CRL file that is used to check certificate
- * revocation */
- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx),
- X509_LOOKUP_file());
- if(!lookup ||
- (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
- failf(data, "error loading CRL file: %s", ssl_crlfile);
- return CURLE_SSL_CRL_BADFILE;
- }
- /* Everything is fine. */
- infof(data, "successfully load CRL file:\n");
- X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
- X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-
- infof(data, " CRLfile: %s\n", ssl_crlfile);
- }
-
- /* Try building a chain using issuers in the trusted store first to avoid
- problems with server-sent legacy intermediates.
- Newer versions of OpenSSL do alternate chain checking by default which
- gives us the same fix without as much of a performance hit (slight), so we
- prefer that if available.
- https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
- */
-#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
- if(verifypeer) {
- X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
- X509_V_FLAG_TRUSTED_FIRST);
- }
-#endif
-
- /* 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. */
- SSL_CTX_set_verify(BACKEND->ctx,
- verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
-
- /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
-#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK)
- if(keylog_file) {
- SSL_CTX_set_keylog_callback(connssl->ctx, ossl_keylog_callback);
- }
-#endif
-
- /* give application a chance to interfere with SSL set up. */
- if(data->set.ssl.fsslctx) {
- result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
- data->set.ssl.fsslctxp);
- if(result) {
- failf(data, "error signaled by ssl ctx callback");
- return result;
- }
- }
-
- /* Lets make an SSL structure */
- if(BACKEND->handle)
- SSL_free(BACKEND->handle);
- BACKEND->handle = SSL_new(BACKEND->ctx);
- if(!BACKEND->handle) {
- failf(data, "SSL: couldn't create a context (handle)!");
- return CURLE_OUT_OF_MEMORY;
- }
-
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- if(SSL_CONN_CONFIG(verifystatus))
- SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp);
-#endif
-
- SSL_set_connect_state(BACKEND->handle);
-
- BACKEND->server_cert = 0x0;
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni &&
- !SSL_set_tlsext_host_name(BACKEND->handle, hostname))
- infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
-#endif
-
- /* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
- void *ssl_sessionid = NULL;
-
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
- /* we got a session id, use it! */
- if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
- Curl_ssl_sessionid_unlock(conn);
- failf(data, "SSL: SSL_set_session failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* Informational message */
- infof(data, "SSL re-using session ID\n");
- }
- Curl_ssl_sessionid_unlock(conn);
- }
-
- if(conn->proxy_ssl[sockindex].use) {
- BIO *const bio = BIO_new(BIO_f_ssl());
- SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
- DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(handle != NULL);
- DEBUGASSERT(bio != NULL);
- BIO_set_ssl(bio, handle, FALSE);
- SSL_set_bio(BACKEND->handle, bio, bio);
- }
- else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
- /* pass the raw socket into the SSL layers */
- failf(data, "SSL: SSL_set_fd failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- connssl->connecting_state = ssl_connect_2;
-
- return CURLE_OK;
-}
-
-static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
-{
- struct Curl_easy *data = conn->data;
- int err;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
- DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
- || ssl_connect_2_reading == connssl->connecting_state
- || ssl_connect_2_writing == connssl->connecting_state);
-
- ERR_clear_error();
-
- err = SSL_connect(BACKEND->handle);
- /* If keylogging is enabled but the keylog callback is not supported then log
- secrets here, immediately after SSL_connect by using tap_ssl_key. */
-#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK)
- tap_ssl_key(BACKEND->handle, &BACKEND->tap_state);
-#endif
-
- /* 1 is fine
- 0 is "not successful but was shut down controlled"
- <0 is "handshake was not successful, because a fatal error occurred" */
- if(1 != err) {
- int detail = SSL_get_error(BACKEND->handle, err);
-
- if(SSL_ERROR_WANT_READ == detail) {
- connssl->connecting_state = ssl_connect_2_reading;
- return CURLE_OK;
- }
- if(SSL_ERROR_WANT_WRITE == detail) {
- connssl->connecting_state = ssl_connect_2_writing;
- return CURLE_OK;
- }
- else {
- /* untreated error */
- unsigned long errdetail;
- char error_buffer[256]="";
- CURLcode result;
- long lerr;
- int lib;
- int reason;
-
- /* the connection failed, we're not waiting for anything else. */
- connssl->connecting_state = ssl_connect_2;
-
- /* Get the earliest error code from the thread's error queue and removes
- the entry. */
- errdetail = ERR_get_error();
-
- /* Extract which lib and reason */
- lib = ERR_GET_LIB(errdetail);
- reason = ERR_GET_REASON(errdetail);
-
- if((lib == ERR_LIB_SSL) &&
- (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
- result = CURLE_SSL_CACERT;
-
- lerr = SSL_get_verify_result(BACKEND->handle);
- if(lerr != X509_V_OK) {
- *certverifyresult = lerr;
- snprintf(error_buffer, sizeof(error_buffer),
- "SSL certificate problem: %s",
- X509_verify_cert_error_string(lerr));
- }
- else
- /* strcpy() is fine here as long as the string fits within
- error_buffer */
- strcpy(error_buffer, "SSL certificate verification failed");
- }
- else {
- result = CURLE_SSL_CONNECT_ERROR;
- ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
- }
-
- /* detail is already set to the SSL error above */
-
- /* If we e.g. use SSLv2 request-method and the server doesn't like us
- * (RST connection etc.), OpenSSL gives no explanation whatsoever and
- * the SO_ERROR is also lost.
- */
- if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
- 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;
- failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ",
- SSL_ERROR_to_str(detail), hostname, port);
- return result;
- }
-
- /* Could be a CERT problem */
- failf(data, "%s", error_buffer);
-
- return result;
- }
- }
- else {
- /* we have been connected fine, we're not waiting for anything else. */
- connssl->connecting_state = ssl_connect_3;
-
- /* Informational message */
- infof(data, "SSL connection using %s / %s\n",
- get_ssl_version_txt(BACKEND->handle),
- SSL_get_cipher(BACKEND->handle));
-
-#ifdef HAS_ALPN
- /* Sets data and len to negotiated protocol, len is 0 if no protocol was
- * negotiated
- */
- if(conn->bits.tls_enable_alpn) {
- const unsigned char *neg_protocol;
- unsigned int len;
- SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len);
- if(len != 0) {
- infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
-
-#ifdef USE_NGHTTP2
- if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(len == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else
- infof(data, "ALPN, server did not agree to a protocol\n");
- }
-#endif
-
- return CURLE_OK;
- }
-}
-
-static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
-{
- int i, ilen;
-
- ilen = (int)len;
- if(ilen < 0)
- return 1; /* buffer too big */
-
- i = i2t_ASN1_OBJECT(buf, ilen, a);
-
- if(i >= ilen)
- return 1; /* buffer too small */
-
- return 0;
-}
-
-#define push_certinfo(_label, _num) \
-do { \
- long info_len = BIO_get_mem_data(mem, &ptr); \
- Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
- if(1 != BIO_reset(mem)) \
- break; \
-} WHILE_FALSE
-
-static void pubkey_show(struct Curl_easy *data,
- BIO *mem,
- int num,
- const char *type,
- const char *name,
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- const
-#endif
- BIGNUM *bn)
-{
- char *ptr;
- char namebuf[32];
-
- snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
-
- if(bn)
- BN_print(mem, bn);
- push_certinfo(namebuf, num);
-}
-
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
-#define print_pubkey_BN(_type, _name, _num) \
- pubkey_show(data, mem, _num, #_type, #_name, _name)
-
-#else
-#define print_pubkey_BN(_type, _name, _num) \
-do { \
- if(_type->_name) { \
- pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
- } \
-} WHILE_FALSE
-#endif
-
-static int X509V3_ext(struct Curl_easy *data,
- int certnum,
- CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
-{
- int i;
- size_t j;
-
- if((int)sk_X509_EXTENSION_num(exts) <= 0)
- /* no extensions, bail out */
- return 1;
-
- for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
- BUF_MEM *biomem;
- char buf[512];
- char *ptr = buf;
- char namebuf[128];
- BIO *bio_out = BIO_new(BIO_s_mem());
-
- if(!bio_out)
- return 1;
-
- obj = X509_EXTENSION_get_object(ext);
-
- asn1_object_dump(obj, namebuf, sizeof(namebuf));
-
- if(!X509V3_EXT_print(bio_out, ext, 0, 0))
- ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
-
- BIO_get_mem_ptr(bio_out, &biomem);
-
- for(j = 0; j < (size_t)biomem->length; j++) {
- const char *sep = "";
- if(biomem->data[j] == '\n') {
- sep = ", ";
- j++; /* skip the newline */
- };
- while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
- j++;
- if(j<(size_t)biomem->length)
- ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
- biomem->data[j]);
- }
-
- Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
-
- BIO_free(bio_out);
-
- }
- return 0; /* all is fine */
-}
-
-static CURLcode get_cert_chain(struct connectdata *conn,
- struct ssl_connect_data *connssl)
-
-{
- CURLcode result;
- STACK_OF(X509) *sk;
- int i;
- struct Curl_easy *data = conn->data;
- int numcerts;
- BIO *mem;
-
- sk = SSL_get_peer_cert_chain(BACKEND->handle);
- if(!sk) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- numcerts = sk_X509_num(sk);
-
- result = Curl_ssl_init_certinfo(data, numcerts);
- if(result) {
- return result;
- }
-
- mem = BIO_new(BIO_s_mem());
-
- for(i = 0; i < numcerts; i++) {
- ASN1_INTEGER *num;
- X509 *x = sk_X509_value(sk, i);
- EVP_PKEY *pubkey = NULL;
- int j;
- char *ptr;
- const ASN1_BIT_STRING *psig = NULL;
-
- X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Subject", i);
-
- X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Issuer", i);
-
- BIO_printf(mem, "%lx", X509_get_version(x));
- push_certinfo("Version", i);
-
- num = X509_get_serialNumber(x);
- if(num->type == V_ASN1_NEG_INTEGER)
- BIO_puts(mem, "-");
- for(j = 0; j < num->length; j++)
- BIO_printf(mem, "%02x", num->data[j]);
- push_certinfo("Serial Number", i);
-
-#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
- {
- const X509_ALGOR *palg = NULL;
- ASN1_STRING *a = ASN1_STRING_new();
- if(a) {
- X509_get0_signature(&psig, &palg, x);
- X509_signature_print(mem, palg, a);
- ASN1_STRING_free(a);
-
- if(palg) {
- i2a_ASN1_OBJECT(mem, palg->algorithm);
- push_certinfo("Public Key Algorithm", i);
- }
- }
- X509V3_ext(data, i, X509_get0_extensions(x));
- }
-#else
- {
- /* before OpenSSL 1.0.2 */
- X509_CINF *cinf = x->cert_info;
-
- i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
- push_certinfo("Signature Algorithm", i);
-
- i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
- push_certinfo("Public Key Algorithm", i);
-
- X509V3_ext(data, i, cinf->extensions);
-
- psig = x->signature;
- }
-#endif
-
- ASN1_TIME_print(mem, X509_get0_notBefore(x));
- push_certinfo("Start date", i);
-
- ASN1_TIME_print(mem, X509_get0_notAfter(x));
- push_certinfo("Expire date", i);
-
- pubkey = X509_get_pubkey(x);
- if(!pubkey)
- infof(data, " Unable to load public key\n");
- else {
- int pktype;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- pktype = EVP_PKEY_id(pubkey);
-#else
- pktype = pubkey->type;
-#endif
- switch(pktype) {
- case EVP_PKEY_RSA:
- {
- RSA *rsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- rsa = EVP_PKEY_get0_RSA(pubkey);
-#else
- rsa = pubkey->pkey.rsa;
-#endif
-
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- {
- const BIGNUM *n;
- const BIGNUM *e;
-
- RSA_get0_key(rsa, &n, &e, NULL);
- BN_print(mem, n);
- push_certinfo("RSA Public Key", i);
- print_pubkey_BN(rsa, n, i);
- print_pubkey_BN(rsa, e, i);
- }
-#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
- push_certinfo("RSA Public Key", i);
- print_pubkey_BN(rsa, n, i);
- print_pubkey_BN(rsa, e, i);
-#endif
-
- break;
- }
- case EVP_PKEY_DSA:
- {
-#ifndef OPENSSL_NO_DSA
- DSA *dsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dsa = EVP_PKEY_get0_DSA(pubkey);
-#else
- dsa = pubkey->pkey.dsa;
-#endif
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- {
- const BIGNUM *p;
- const BIGNUM *q;
- const BIGNUM *g;
- const BIGNUM *pub_key;
-
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, NULL);
-
- print_pubkey_BN(dsa, p, i);
- print_pubkey_BN(dsa, q, i);
- print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, pub_key, i);
- }
-#else
- print_pubkey_BN(dsa, p, i);
- print_pubkey_BN(dsa, q, i);
- print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, pub_key, i);
-#endif
-#endif /* !OPENSSL_NO_DSA */
- break;
- }
- case EVP_PKEY_DH:
- {
- DH *dh;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dh = EVP_PKEY_get0_DH(pubkey);
-#else
- dh = pubkey->pkey.dh;
-#endif
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- {
- const BIGNUM *p;
- const BIGNUM *q;
- const BIGNUM *g;
- const BIGNUM *pub_key;
- DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, NULL);
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, q, i);
- print_pubkey_BN(dh, g, i);
- print_pubkey_BN(dh, pub_key, i);
- }
-#else
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, g, i);
- print_pubkey_BN(dh, pub_key, i);
-#endif
- break;
- }
-#if 0
- case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */
- /* left TODO */
- break;
-#endif
- }
- EVP_PKEY_free(pubkey);
- }
-
- if(psig) {
- for(j = 0; j < psig->length; j++)
- BIO_printf(mem, "%02x:", psig->data[j]);
- push_certinfo("Signature", i);
- }
-
- PEM_write_bio_X509(mem, x);
- push_certinfo("Cert", i);
- }
-
- BIO_free(mem);
-
- return CURLE_OK;
-}
-
-/*
- * Heavily modified from:
- * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
- */
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
- const char *pinnedpubkey)
-{
- /* Scratch */
- int len1 = 0, len2 = 0;
- unsigned char *buff1 = NULL, *temp = 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(!cert)
- return result;
-
- do {
- /* Begin Gyrations to get the subjectPublicKeyInfo */
- /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */
-
- /* https://groups.google.com/group/mailing.openssl.users/browse_thread
- /thread/d61858dae102c6c7 */
- len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
- if(len1 < 1)
- break; /* failed */
-
- /* https://www.openssl.org/docs/crypto/buffer.html */
- buff1 = temp = malloc(len1);
- if(!buff1)
- break; /* failed */
-
- /* https://www.openssl.org/docs/crypto/d2i_X509.html */
- len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp);
-
- /*
- * These checks are verifying we got back the same values as when we
- * sized the buffer. It's pretty weak since they should always be the
- * same. But it gives us something to test.
- */
- if((len1 != len2) || !temp || ((temp - buff1) != len1))
- break; /* failed */
-
- /* End Gyrations */
-
- /* The one good exit point */
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
- } while(0);
-
- /* https://www.openssl.org/docs/crypto/buffer.html */
- if(buff1)
- free(buff1);
-
- return result;
-}
-
-/*
- * Get the server cert, verify it and show it etc, only call failf() if the
- * 'strict' argument is TRUE as otherwise all this is for informational
- * purposes only!
- *
- * We check certificates to authenticate the server; otherwise we risk
- * man-in-the-middle attack.
- */
-static CURLcode servercert(struct connectdata *conn,
- struct ssl_connect_data *connssl,
- bool strict)
-{
- CURLcode result = CURLE_OK;
- int rc;
- long lerr, len;
- struct Curl_easy *data = conn->data;
- X509 *issuer;
- FILE *fp;
- char buffer[2048];
- const char *ptr;
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
- BIO *mem = BIO_new(BIO_s_mem());
-
- if(data->set.ssl.certinfo)
- /* we've been asked to gather certificate info! */
- (void)get_cert_chain(conn, connssl);
-
- BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
- if(!BACKEND->server_cert) {
- BIO_free(mem);
- if(!strict)
- return CURLE_OK;
-
- failf(data, "SSL: couldn't get peer certificate!");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
-
- infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
-
- rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert),
- buffer, sizeof(buffer));
- infof(data, " subject: %s\n", rc?"[NONE]":buffer);
-
- ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " start date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
-
- ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " expire date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
-
- BIO_free(mem);
-
- if(SSL_CONN_CONFIG(verifyhost)) {
- result = verifyhost(conn, BACKEND->server_cert);
- if(result) {
- X509_free(BACKEND->server_cert);
- BACKEND->server_cert = NULL;
- return result;
- }
- }
-
- rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert),
- buffer, sizeof(buffer));
- if(rc) {
- if(strict)
- failf(data, "SSL: couldn't get X509-issuer name!");
- result = CURLE_SSL_CONNECT_ERROR;
- }
- else {
- infof(data, " issuer: %s\n", buffer);
-
- /* We could do all sorts of certificate verification stuff here before
- deallocating the certificate. */
-
- /* e.g. match issuer name with provided issuer certificate */
- if(SSL_SET_OPTION(issuercert)) {
- fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
- if(!fp) {
- if(strict)
- failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
- BACKEND->server_cert = NULL;
- return CURLE_SSL_ISSUER_ERROR;
- }
-
- issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL);
- if(!issuer) {
- if(strict)
- failf(data, "SSL: Unable to read issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
- X509_free(issuer);
- fclose(fp);
- return CURLE_SSL_ISSUER_ERROR;
- }
-
- fclose(fp);
-
- if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
- if(strict)
- failf(data, "SSL: Certificate issuer check failed (%s)",
- SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
- X509_free(issuer);
- BACKEND->server_cert = NULL;
- return CURLE_SSL_ISSUER_ERROR;
- }
-
- infof(data, " SSL certificate issuer check ok (%s)\n",
- SSL_SET_OPTION(issuercert));
- X509_free(issuer);
- }
-
- lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle);
-
- if(*certverifyresult != X509_V_OK) {
- if(SSL_CONN_CONFIG(verifypeer)) {
- /* We probably never reach this, because SSL_connect() will fail
- and we return earlier if verifypeer is set? */
- if(strict)
- failf(data, "SSL certificate verify result: %s (%ld)",
- X509_verify_cert_error_string(lerr), lerr);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- infof(data, " SSL certificate verify result: %s (%ld),"
- " continuing anyway.\n",
- X509_verify_cert_error_string(lerr), lerr);
- }
- else
- infof(data, " SSL certificate verify ok.\n");
- }
-
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- if(SSL_CONN_CONFIG(verifystatus)) {
- result = verifystatus(conn, connssl);
- if(result) {
- X509_free(BACKEND->server_cert);
- BACKEND->server_cert = NULL;
- return result;
- }
- }
-#endif
-
- if(!strict)
- /* when not strict, we don't bother about the verify cert problems */
- result = CURLE_OK;
-
- ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
- if(!result && ptr) {
- result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr);
- if(result)
- failf(data, "SSL: public key does not match pinned public key!");
- }
-
- X509_free(BACKEND->server_cert);
- BACKEND->server_cert = NULL;
- connssl->connecting_state = ssl_connect_done;
-
- return result;
-}
-
-static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
-{
- CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
- DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
-
- if(SSL_SET_OPTION(primary.sessionid)) {
- bool incache;
- SSL_SESSION *our_ssl_sessionid;
- void *old_ssl_sessionid = NULL;
-
- our_ssl_sessionid = SSL_get1_session(BACKEND->handle);
-
- /* SSL_get1_session() will increment the reference count and the session
- will stay in memory until explicitly freed with SSL_SESSION_free(3),
- regardless of its state. */
-
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
- sockindex));
- if(incache) {
- if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- incache = FALSE;
- }
- }
-
- if(!incache) {
- result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */, sockindex);
- if(result) {
- Curl_ssl_sessionid_unlock(conn);
- failf(data, "failed to store ssl session");
- return result;
- }
- }
- else {
- /* Session was incache, so refcount already incremented earlier.
- * Avoid further increments with each SSL_get1_session() call.
- * This does not free the session as refcount remains > 0
- */
- SSL_SESSION_free(our_ssl_sessionid);
- }
- Curl_ssl_sessionid_unlock(conn);
- }
-
- /*
- * We check certificates to authenticate the server; otherwise we risk
- * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
- * verify the peer ignore faults and failures from the server cert
- * operations.
- */
-
- result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
- SSL_CONN_CONFIG(verifyhost)));
-
- if(!result)
- connssl->connecting_state = ssl_connect_done;
-
- return result;
-}
-
-static Curl_recv ossl_recv;
-static Curl_send ossl_send;
-
-static CURLcode ossl_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];
- time_t 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 = ossl_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;
- }
- if(0 == what) {
- if(nonblocking) {
- *done = FALSE;
- return CURLE_OK;
- }
- /* 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 = ossl_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 = ossl_connect_step3(conn, sockindex);
- if(result)
- return result;
- }
-
- if(ssl_connect_done == connssl->connecting_state) {
- connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = ossl_recv;
- conn->send[sockindex] = ossl_send;
- *done = TRUE;
- }
- else
- *done = FALSE;
-
- /* Reset our connect state machine */
- connssl->connecting_state = ssl_connect_1;
-
- return CURLE_OK;
-}
-
-static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
-{
- return ossl_connect_common(conn, sockindex, TRUE, done);
-}
-
-static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
-{
- CURLcode result;
- bool done = FALSE;
-
- result = ossl_connect_common(conn, sockindex, FALSE, &done);
- if(result)
- return result;
-
- DEBUGASSERT(done);
-
- return CURLE_OK;
-}
-
-static bool Curl_ossl_data_pending(const struct connectdata *conn,
- int connindex)
-{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
- if(BACKEND->handle)
- /* SSL is in use */
- return (0 != SSL_pending(BACKEND->handle) ||
- (proxyssl->backend->handle &&
- 0 != SSL_pending(proxyssl->backend->handle))) ?
- TRUE : FALSE;
- return FALSE;
-}
-
-static size_t Curl_ossl_version(char *buffer, size_t size);
-
-static ssize_t ossl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- /* SSL_write() is said to return 'int' while write() and send() returns
- 'size_t' */
- int err;
- char error_buffer[256];
- unsigned long sslerror;
- int memlen;
- int rc;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
- ERR_clear_error();
-
- memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- rc = SSL_write(BACKEND->handle, mem, memlen);
-
- if(rc <= 0) {
- err = SSL_get_error(BACKEND->handle, rc);
-
- switch(err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- /* The operation did not complete; the same TLS/SSL I/O function
- should be called again later. This is basically an EWOULDBLOCK
- equivalent. */
- *curlcode = CURLE_AGAIN;
- return -1;
- case SSL_ERROR_SYSCALL:
- failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
- SOCKERRNO);
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- case SSL_ERROR_SSL:
- /* A failure in the SSL library occurred, usually a protocol error.
- The OpenSSL error queue contains more information on the error. */
- sslerror = ERR_get_error();
- if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
- ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- conn->ssl[sockindex].state == ssl_connection_complete &&
- conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
- char ver[120];
- Curl_ossl_version(ver, 120);
- failf(conn->data, "Error: %s does not support double SSL tunneling.",
- ver);
- }
- else
- failf(conn->data, "SSL_write() error: %s",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- /* a true error */
- failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
- SSL_ERROR_to_str(err), SOCKERRNO);
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- *curlcode = CURLE_OK;
- return (ssize_t)rc; /* number of bytes */
-}
-
-static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
- int num, /* socketindex */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
- CURLcode *curlcode)
-{
- char error_buffer[256];
- unsigned long sslerror;
- ssize_t nread;
- int buffsize;
- struct ssl_connect_data *connssl = &conn->ssl[num];
-
- ERR_clear_error();
-
- buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
- if(nread <= 0) {
- /* failed SSL_read */
- int err = SSL_get_error(BACKEND->handle, (int)nread);
-
- switch(err) {
- case SSL_ERROR_NONE: /* this is not an error */
- case SSL_ERROR_ZERO_RETURN: /* no more data */
- break;
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- /* there's data pending, re-invoke SSL_read() */
- *curlcode = CURLE_AGAIN;
- return -1;
- default:
- /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
- value/errno" */
- /* https://www.openssl.org/docs/crypto/ERR_get_error.html */
- sslerror = ERR_get_error();
- if((nread < 0) || sslerror) {
- /* If the return code was negative or there actually is an error in the
- queue */
- failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
- (sslerror ?
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) :
- SSL_ERROR_to_str(err)),
- SOCKERRNO);
- *curlcode = CURLE_RECV_ERROR;
- return -1;
- }
- }
- }
- return nread;
-}
-
-static size_t Curl_ossl_version(char *buffer, size_t size)
-{
-#ifdef OPENSSL_IS_BORINGSSL
- return snprintf(buffer, size, OSSL_PACKAGE);
-#else /* OPENSSL_IS_BORINGSSL */
- char sub[3];
- unsigned long ssleay_value;
- sub[2]='\0';
- sub[1]='\0';
- ssleay_value = OpenSSL_version_num();
- if(ssleay_value < 0x906000) {
- ssleay_value = SSLEAY_VERSION_NUMBER;
- sub[0]='\0';
- }
- else {
- if(ssleay_value&0xff0) {
- int minor_ver = (ssleay_value >> 4) & 0xff;
- if(minor_ver > 26) {
- /* handle extended version introduced for 0.9.8za */
- sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1);
- sub[0] = 'z';
- }
- else {
- sub[0] = (char) (minor_ver + 'a' - 1);
- }
- }
- else
- sub[0]='\0';
- }
-
- return snprintf(buffer, size, "%s/%lx.%lx.%lx%s",
- OSSL_PACKAGE,
- (ssleay_value>>28)&0xf,
- (ssleay_value>>20)&0xff,
- (ssleay_value>>12)&0xff,
- sub);
-#endif /* OPENSSL_IS_BORINGSSL */
-}
-
-/* can be called with data == NULL */
-static CURLcode Curl_ossl_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
-{
- int rc;
- if(data) {
- if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
- return CURLE_FAILED_INIT; /* couldn't seed for some reason */
- }
- else {
- if(!rand_enough())
- return CURLE_FAILED_INIT;
- }
- /* RAND_bytes() returns 1 on success, 0 otherwise. */
- rc = RAND_bytes(entropy, curlx_uztosi(length));
- return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
-}
-
-static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum /* output */,
- size_t unused)
-{
- MD5_CTX MD5pw;
- (void)unused;
- MD5_Init(&MD5pw);
- MD5_Update(&MD5pw, tmp, tmplen);
- MD5_Final(md5sum, &MD5pw);
- return CURLE_OK;
-}
-
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
-{
- SHA256_CTX SHA256pw;
- (void)unused;
- SHA256_Init(&SHA256pw);
- SHA256_Update(&SHA256pw, tmp, tmplen);
- SHA256_Final(sha256sum, &SHA256pw);
-}
-#endif
-
-static bool Curl_ossl_cert_status_request(void)
-{
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info)
-{
- /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
- return info == CURLINFO_TLS_SESSION ?
- (void *)BACKEND->ctx : (void *)BACKEND->handle;
-}
-
-const struct Curl_ssl Curl_ssl_openssl = {
- { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
-
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 1, /* support_https_proxy */
-
- sizeof(struct ssl_backend_data),
-
- Curl_ossl_init, /* init */
- Curl_ossl_cleanup, /* cleanup */
- Curl_ossl_version, /* version */
- Curl_ossl_check_cxn, /* check_cxn */
- Curl_ossl_shutdown, /* shutdown */
- Curl_ossl_data_pending, /* data_pending */
- Curl_ossl_random, /* random */
- Curl_ossl_cert_status_request, /* cert_status_request */
- Curl_ossl_connect, /* connect */
- Curl_ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ossl_get_internals, /* get_internals */
- Curl_ossl_close, /* close_one */
- Curl_ossl_close_all, /* close_all */
- Curl_ossl_session_free, /* session_free */
- Curl_ossl_set_engine, /* set_engine */
- Curl_ossl_set_engine_default, /* set_engine_default */
- Curl_ossl_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- Curl_ossl_md5sum, /* md5sum */
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
- Curl_ossl_sha256sum /* sha256sum */
-#else
- NULL /* sha256sum */
-#endif
-};
-
-#endif /* USE_OPENSSL */
diff --git a/libs/libcurl/src/openssl.h b/libs/libcurl/src/openssl.h
deleted file mode 100644
index 114dc4baeb..0000000000
--- a/libs/libcurl/src/openssl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef HEADER_CURL_SSLUSE_H
-#define HEADER_CURL_SSLUSE_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#ifdef USE_OPENSSL
-/*
- * This header should only be needed to get included by vtls.c and openssl.c
- */
-
-#include "urldata.h"
-
-extern const struct Curl_ssl Curl_ssl_openssl;
-
-#endif /* USE_OPENSSL */
-#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c
index 5e0fd2299b..05853f001d 100644
--- a/libs/libcurl/src/pop3.c
+++ b/libs/libcurl/src/pop3.c
@@ -443,7 +443,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
/* Convert the calculated 16 octet digest into a 32 byte hex string */
for(i = 0; i < MD5_DIGEST_LEN; i++)
- snprintf(&secret[2 * i], 3, "%02x", digest[i]);
+ msnprintf(&secret[2 * i], 3, "%02x", digest[i]);
result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
@@ -629,6 +629,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
if(line[i] == '<') {
/* Calculate the length of the timestamp */
size_t timestamplen = len - 1 - i;
+ char *at;
if(!timestamplen)
break;
@@ -642,8 +643,15 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
memcpy(pop3c->apoptimestamp, line + i, timestamplen);
pop3c->apoptimestamp[timestamplen] = '\0';
- /* Store the APOP capability */
- pop3c->authtypes |= POP3_TYPE_APOP;
+ /* If the timestamp does not contain '@' it is not (as required by
+ RFC-1939) conformant to the RFC-822 message id syntax, and we
+ therefore do not use APOP authentication. */
+ at = strchr(pop3c->apoptimestamp, '@');
+ if(!at)
+ Curl_safefree(pop3c->apoptimestamp);
+ else
+ /* Store the APOP capability */
+ pop3c->authtypes |= POP3_TYPE_APOP;
break;
}
}
diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c
index a94668dc2a..d37e1d5a63 100644
--- a/libs/libcurl/src/progress.c
+++ b/libs/libcurl/src/progress.c
@@ -44,8 +44,8 @@ static void time2str(char *r, curl_off_t seconds)
if(h <= CURL_OFF_T_C(99)) {
curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
- snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
- ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
+ msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
+ ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
}
else {
/* this equals to more than 99 hours, switch to a more suitable output
@@ -53,10 +53,10 @@ static void time2str(char *r, curl_off_t seconds)
curl_off_t d = seconds / CURL_OFF_T_C(86400);
h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
if(d <= CURL_OFF_T_C(999))
- snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
- "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
+ msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
+ "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
else
- snprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
+ msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
}
}
@@ -72,40 +72,40 @@ static char *max5data(curl_off_t bytes, char *max5)
#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
if(bytes < CURL_OFF_T_C(100000))
- snprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
+ msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
/* 'XX.XM' is good as long as we're less than 100 megs */
- snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
- CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
- (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
+ msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
+ (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
#if (CURL_SIZEOF_CURL_OFF_T > 4)
else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
/* 'XXXXM' is good until we're at 10000MB or above */
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
/* 10000 MB - 100 GB, we show it as XX.XG */
- snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
- CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
- (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
+ msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
+ (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
/* up to 10000GB, display without decimal: XXXXG */
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
/* up to 10000TB, display without decimal: XXXXT */
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
else
/* up to 10000PB, display without decimal: XXXXP */
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
/* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
can hold, but our data type is signed so 8192PB will be the maximum. */
@@ -113,7 +113,7 @@ static char *max5data(curl_off_t bytes, char *max5)
#else
else
- snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
#endif
diff --git a/libs/libcurl/src/security.c b/libs/libcurl/src/security.c
index 6165d0af01..7f13071f6f 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 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2001 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* All rights reserved.
*
@@ -120,7 +120,7 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...)
char print_buffer[50];
va_start(args, message);
- vsnprintf(print_buffer, sizeof(print_buffer), message, args);
+ mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
va_end(args);
if(Curl_ftpsend(conn, print_buffer)) {
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c
index d3c10b3690..e8598e6173 100644
--- a/libs/libcurl/src/sendf.c
+++ b/libs/libcurl/src/sendf.c
@@ -237,7 +237,18 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
size_t len;
char print_buffer[2048 + 1];
va_start(ap, fmt);
- vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+ len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+ /*
+ * Indicate truncation of the input by replacing the last 3 characters
+ * with "...", and transfer the newline over in case the format had one.
+ */
+ if(len >= sizeof(print_buffer)) {
+ len = strlen(fmt);
+ if(fmt[--len] == '\n')
+ msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n");
+ else
+ msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "...");
+ }
va_end(ap);
len = strlen(print_buffer);
Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
@@ -255,7 +266,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
size_t len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+ mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
len = strlen(error);
if(data->set.errorbuffer && !data->state.errorbuf) {
diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c
index 22956a20fb..1627aba6df 100644
--- a/libs/libcurl/src/setopt.c
+++ b/libs/libcurl/src/setopt.c
@@ -1204,6 +1204,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.low_speed_time = arg;
break;
+ case CURLOPT_CURLU:
+ /*
+ * pass CURLU to set URL
+ */
+ data->set.uh = va_arg(param, CURLU *);
+ break;
case CURLOPT_URL:
/*
* The URL to fetch.
diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c
index 96948ac4ba..65294bbebd 100644
--- a/libs/libcurl/src/socks_gssapi.c
+++ b/libs/libcurl/src/socks_gssapi.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -151,8 +151,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
service.length = serviceptr_length +
strlen(conn->socks_proxy.host.name) + 1;
- snprintf(service.value, service.length + 1, "%s@%s",
- serviceptr, conn->socks_proxy.host.name);
+ msnprintf(service.value, service.length + 1, "%s@%s",
+ serviceptr, conn->socks_proxy.host.name);
gss_major_status = gss_import_name(&gss_minor_status, &service,
GSS_C_NT_HOSTBASED_SERVICE, &server);
diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c
index 34699d3742..bedb01ebbc 100644
--- a/libs/libcurl/src/socks_sspi.c
+++ b/libs/libcurl/src/socks_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
@@ -107,9 +107,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
strlen(conn->socks_proxy.host.name) + 2);
if(!service_name)
return CURLE_OUT_OF_MEMORY;
- snprintf(service_name, service_length +
- strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
- service, conn->socks_proxy.host.name);
+ msnprintf(service_name, service_length +
+ strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
+ service, conn->socks_proxy.host.name);
}
input_desc.cBuffers = 1;
diff --git a/libs/libcurl/src/ssh-libssh.c b/libs/libcurl/src/ssh-libssh.c
index 7d590891ca..e38c01ac74 100644
--- a/libs/libcurl/src/ssh-libssh.c
+++ b/libs/libcurl/src/ssh-libssh.c
@@ -1342,8 +1342,8 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
- sshc->readdir_filename);
+ msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
+ sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_LINK);
break;
@@ -1406,12 +1406,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
sshc->readdir_line = new_readdir_line;
- sshc->readdir_currLen += snprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen,
- " -> %s",
- sshc->readdir_filename);
+ sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen,
+ " -> %s",
+ sshc->readdir_filename);
sftp_attributes_free(sshc->readdir_link_attrs);
sshc->readdir_link_attrs = NULL;
@@ -1421,10 +1421,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_READDIR_BOTTOM);
/* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
- sshc->readdir_currLen += snprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen, "\n");
+ sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen, "\n");
result = Curl_client_write(conn, CLIENTWRITE_BODY,
sshc->readdir_line,
sshc->readdir_currLen);
diff --git a/libs/libcurl/src/ssh.c b/libs/libcurl/src/ssh.c
index da896196f3..f3b0a58be6 100644
--- a/libs/libcurl/src/ssh.c
+++ b/libs/libcurl/src/ssh.c
@@ -599,7 +599,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
if(fingerprint) {
/* The fingerprint points to static storage (!), don't free() it. */
for(i = 0; i < 16; i++)
- snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
+ msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
}
@@ -1999,8 +1999,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
- sshc->readdir_filename);
+ msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
+ sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_LINK);
break;
}
@@ -2055,21 +2055,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
sshc->readdir_line = new_readdir_line;
- sshc->readdir_currLen += snprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen,
- " -> %s",
- sshc->readdir_filename);
+ sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen,
+ " -> %s",
+ sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_BOTTOM);
break;
case SSH_SFTP_READDIR_BOTTOM:
- sshc->readdir_currLen += snprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen, "\n");
+ sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen, "\n");
result = Curl_client_write(conn, CLIENTWRITE_BODY,
sshc->readdir_line,
sshc->readdir_currLen);
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c
index 47ef44a66d..bf30c89077 100644
--- a/libs/libcurl/src/strerror.c
+++ b/libs/libcurl/src/strerror.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2004 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2004 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -681,7 +681,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
if(!get_winsock_error(err, buf, max) &&
!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
LANG_NEUTRAL, buf, (DWORD)max, NULL))
- snprintf(buf, max, "Unknown error %d (%#x)", err, err);
+ msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
}
#endif
@@ -695,7 +695,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
*/
if(0 != strerror_r(err, buf, max)) {
if('\0' == buf[0])
- snprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, max, "Unknown error %d", err);
}
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
/*
@@ -709,7 +709,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
if(msg)
strncpy(buf, msg, max);
else
- snprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, max, "Unknown error %d", err);
}
#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
/*
@@ -721,7 +721,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
if(OK == strerror_r(err, buffer))
strncpy(buf, buffer, max);
else
- snprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, max, "Unknown error %d", err);
}
#else
{
@@ -729,7 +729,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
if(msg)
strncpy(buf, msg, max);
else
- snprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, max, "Unknown error %d", err);
}
#endif
@@ -1032,14 +1032,14 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
if(err == SEC_E_OK)
strncpy(outbuf, txt, outmax);
else if(err == SEC_E_ILLEGAL_MESSAGE)
- snprintf(outbuf, outmax,
- "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
- "when a fatal SSL/TLS alert is received (e.g. handshake failed). "
- "More detail may be available in the Windows System event log.",
- err);
+ msnprintf(outbuf, outmax,
+ "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
+ "when a fatal SSL/TLS alert is received (e.g. handshake failed)."
+ " More detail may be available in the Windows System event log.",
+ err);
else {
str = txtbuf;
- snprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
+ msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
txtbuf[sizeof(txtbuf)-1] = '\0';
#ifdef _WIN32_WCE
@@ -1075,7 +1075,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
msg = msgbuf;
}
if(msg)
- snprintf(outbuf, outmax, "%s - %s", str, msg);
+ msnprintf(outbuf, outmax, "%s - %s", str, msg);
else
strncpy(outbuf, str, outmax);
}
diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c
index 05fe744dbd..e4c0bac3dc 100644
--- a/libs/libcurl/src/telnet.c
+++ b/libs/libcurl/src/telnet.c
@@ -829,7 +829,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
/* Add the user name as an environment variable if it
was given on the command line */
if(conn->bits.user_passwd) {
- snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
+ msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) {
curl_slist_free_all(tn->telnet_vars);
@@ -935,9 +935,9 @@ static void suboption(struct connectdata *conn)
switch(CURL_SB_GET(tn)) {
case CURL_TELOPT_TTYPE:
len = strlen(tn->subopt_ttype) + 4 + 2;
- snprintf((char *)temp, sizeof(temp),
- "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
- CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
+ msnprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
+ CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
if(bytes_written < 0) {
err = SOCKERRNO;
@@ -947,9 +947,9 @@ static void suboption(struct connectdata *conn)
break;
case CURL_TELOPT_XDISPLOC:
len = strlen(tn->subopt_xdisploc) + 4 + 2;
- snprintf((char *)temp, sizeof(temp),
- "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
- CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
+ msnprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
+ CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
if(bytes_written < 0) {
err = SOCKERRNO;
@@ -958,9 +958,9 @@ static void suboption(struct connectdata *conn)
printsub(data, '>', &temp[2], len-2);
break;
case CURL_TELOPT_NEW_ENVIRON:
- snprintf((char *)temp, sizeof(temp),
- "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
- CURL_TELQUAL_IS);
+ msnprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
+ CURL_TELQUAL_IS);
len = 4;
for(v = tn->telnet_vars; v; v = v->next) {
@@ -968,15 +968,15 @@ static void suboption(struct connectdata *conn)
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
- snprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
- CURL_NEW_ENV_VALUE, varval);
+ msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
len += tmplen;
}
}
}
- snprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%c", CURL_IAC, CURL_SE);
+ msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%c", CURL_IAC, CURL_SE);
len += 2;
bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
if(bytes_written < 0) {
diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c
index 5b74e8e08c..269b3cde4b 100644
--- a/libs/libcurl/src/tftp.c
+++ b/libs/libcurl/src/tftp.c
@@ -496,9 +496,9 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
return CURLE_TFTP_ILLEGAL; /* too long file name field */
}
- snprintf((char *)state->spacket.data + 2,
- state->blksize,
- "%s%c%s%c", filename, '\0', mode, '\0');
+ msnprintf((char *)state->spacket.data + 2,
+ state->blksize,
+ "%s%c%s%c", filename, '\0', mode, '\0');
sbytes = 4 + strlen(filename) + strlen(mode);
/* optional addition of TFTP options */
@@ -506,8 +506,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
char buf[64];
/* add tsize option */
if(data->set.upload && (data->state.infilesize != -1))
- snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
- data->state.infilesize);
+ msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
+ data->state.infilesize);
else
strcpy(buf, "0"); /* the destination is large enough */
@@ -517,7 +517,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
sbytes += tftp_option_add(state, sbytes,
(char *)state->spacket.data + sbytes, buf);
/* add blksize option */
- snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
+ msnprintf(buf, sizeof(buf), "%d", state->requested_blksize);
sbytes += tftp_option_add(state, sbytes,
(char *)state->spacket.data + sbytes,
TFTP_OPTION_BLKSIZE);
@@ -525,7 +525,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
(char *)state->spacket.data + sbytes, buf);
/* add timeout option */
- snprintf(buf, sizeof(buf), "%d", state->retry_time);
+ msnprintf(buf, sizeof(buf), "%d", state->retry_time);
sbytes += tftp_option_add(state, sbytes,
(char *)state->spacket.data + sbytes,
TFTP_OPTION_INTERVAL);
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c
index b73f94d9e7..6390821bba 100644
--- a/libs/libcurl/src/transfer.c
+++ b/libs/libcurl/src/transfer.c
@@ -218,8 +218,8 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
endofline_native = "\r\n";
endofline_network = "\x0d\x0a";
}
- hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
- "%x%s", nread, endofline_native);
+ hexlen = msnprintf(hexbuffer, sizeof(hexbuffer),
+ "%x%s", nread, endofline_native);
/* move buffer pointer */
data->req.upload_fromhere -= hexlen;
@@ -844,6 +844,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
k->keepon &= ~KEEP_RECV;
}
+ if(k->keepon & KEEP_RECV_PAUSE) {
+ /* this is a paused transfer */
+ break;
+ }
+
} while(data_pending(conn) && maxloops--);
if(maxloops <= 0) {
@@ -1348,17 +1353,30 @@ void Curl_init_CONNECT(struct Curl_easy *data)
CURLcode Curl_pretransfer(struct Curl_easy *data)
{
CURLcode result;
- if(!data->change.url) {
+
+ if(!data->change.url && !data->set.uh) {
/* we can't do anything without URL */
failf(data, "No URL set!");
return CURLE_URL_MALFORMAT;
}
+
/* since the URL may have been redirected in a previous use of this handle */
if(data->change.url_alloc) {
/* the already set URL is allocated, free it first! */
Curl_safefree(data->change.url);
data->change.url_alloc = FALSE;
}
+
+ if(!data->change.url && data->set.uh) {
+ CURLUcode uc;
+ uc = curl_url_get(data->set.uh,
+ CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
+ if(uc) {
+ failf(data, "No URL set!");
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+
data->change.url = data->set.str[STRING_SET_URL];
/* Init the SSL session ID cache here. We do it here since we want to do it
@@ -1514,13 +1532,24 @@ CURLcode Curl_follow(struct Curl_easy *data,
disallowport = TRUE;
DEBUGASSERT(data->state.uh);
- uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, 0);
- if(uc)
- return Curl_uc_to_curlcode(uc);
+ uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
+ (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0);
+ if(uc) {
+ if(type != FOLLOW_FAKE)
+ return Curl_uc_to_curlcode(uc);
+
+ /* the URL could not be parsed for some reason, but since this is FAKE
+ mode, just duplicate the field as-is */
+ newurl = strdup(newurl);
+ if(!newurl)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
- uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
- if(uc)
- return Curl_uc_to_curlcode(uc);
+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ }
if(type == FOLLOW_FAKE) {
/* we're only figuring out the new url if we would've followed locations
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index 0d5a13f996..7839dfa7ce 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -127,7 +127,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "memdebug.h"
static void conn_free(struct connectdata *conn);
-static void free_fixed_hostname(struct hostname *host);
+static void free_idnconverted_hostname(struct hostname *host);
static unsigned int get_protocol_family(unsigned int protocol);
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
@@ -570,7 +570,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->magic = CURLEASY_MAGIC_NUMBER;
- result = Curl_resolver_init(&data->state.resolver);
+ result = Curl_resolver_init(data, &data->state.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
free(data);
@@ -708,6 +708,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
+ Curl_safefree(conn->hostname_resolve);
Curl_safefree(conn->secondaryhostname);
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
@@ -788,10 +789,10 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
infof(data, "Closing connection %ld\n", conn->connection_id);
Curl_conncache_remove_conn(conn, TRUE);
- free_fixed_hostname(&conn->host);
- free_fixed_hostname(&conn->conn_to_host);
- free_fixed_hostname(&conn->http_proxy.host);
- free_fixed_hostname(&conn->socks_proxy.host);
+ 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);
DEBUGASSERT(conn->data == data);
/* this assumes that the pointer is still there after the connection was
@@ -1679,11 +1680,23 @@ static bool is_ASCII_name(const char *hostname)
}
/*
- * Perform any necessary IDN conversion of hostname
+ * Strip single trailing dot in the hostname,
+ * primarily for SNI and http host header.
*/
-static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
+static void strip_trailing_dot(struct hostname *host)
{
size_t len;
+ len = strlen(host->name);
+ if(len && (host->name[len-1] == '.'))
+ host->name[len-1] = 0;
+}
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+static CURLcode idnconvert_hostname(struct connectdata *conn,
+ struct hostname *host)
+{
struct Curl_easy *data = conn->data;
#ifndef USE_LIBIDN2
@@ -1696,12 +1709,6 @@ static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
/* set the name we use to display the host name */
host->dispname = host->name;
- len = strlen(host->name);
- if(len && (host->name[len-1] == '.'))
- /* strip off a single trailing dot if present, primarily for SNI but
- there's no use for it */
- host->name[len-1] = 0;
-
/* Check name for non-ASCII and convert hostname to ACE form if we can */
if(!is_ASCII_name(host->name)) {
#ifdef USE_LIBIDN2
@@ -1756,9 +1763,9 @@ static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
}
/*
- * Frees data allocated by fix_hostname()
+ * Frees data allocated by idnconvert_hostname()
*/
-static void free_fixed_hostname(struct hostname *host)
+static void free_idnconverted_hostname(struct hostname *host)
{
#if defined(USE_LIBIDN2)
if(host->encalloc) {
@@ -2026,7 +2033,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
Curl_up_free(data); /* cleanup previous leftovers first */
/* parse the URL */
- uh = data->state.uh = curl_url();
+ if(data->set.uh) {
+ uh = data->set.uh;
+ }
+ else {
+ uh = data->state.uh = curl_url();
+ }
+
if(!uh)
return CURLE_OUT_OF_MEMORY;
@@ -2043,14 +2056,18 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
data->change.url_alloc = TRUE;
}
- uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+ if(!data->set.uh) {
+ uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
CURLU_GUESS_SCHEME |
CURLU_NON_SUPPORT_SCHEME |
(data->set.disallow_username_in_url ?
CURLU_DISALLOW_USER : 0) |
(data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
- if(uc)
- return Curl_uc_to_curlcode(uc);
+ if(uc) {
+ DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
+ return Curl_uc_to_curlcode(uc);
+ }
+ }
uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
if(uc)
@@ -2191,6 +2208,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OK;
}
+
/*
* If we're doing a resumed transfer, we need to setup our stuff
* properly.
@@ -2979,7 +2997,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
char portbuf[16];
CURLUcode uc;
conn->remote_port = (unsigned short)data->set.use_port;
- snprintf(portbuf, sizeof(portbuf), "%u", conn->remote_port);
+ msnprintf(portbuf, sizeof(portbuf), "%u", conn->remote_port);
uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
if(uc)
return CURLE_OUT_OF_MEMORY;
@@ -2999,6 +3017,20 @@ static CURLcode override_login(struct Curl_easy *data,
bool user_changed = FALSE;
bool passwd_changed = FALSE;
CURLUcode uc;
+
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
+ /* ignore user+password in the URL */
+ if(*userp) {
+ Curl_safefree(*userp);
+ user_changed = TRUE;
+ }
+ if(*passwdp) {
+ Curl_safefree(*passwdp);
+ passwd_changed = TRUE;
+ }
+ conn->bits.user_passwd = FALSE; /* disable user+password */
+ }
+
if(data->set.str[STRING_USERNAME]) {
free(*userp);
*userp = strdup(data->set.str[STRING_USERNAME]);
@@ -3025,16 +3057,15 @@ static CURLcode override_login(struct Curl_easy *data,
}
conn->bits.netrc = FALSE;
- if(data->set.use_netrc != CURL_NETRC_IGNORED) {
- char *nuser = NULL;
- char *npasswd = NULL;
+ if(data->set.use_netrc != CURL_NETRC_IGNORED &&
+ (!*userp || !**userp || !*passwdp || !**passwdp)) {
+ bool netrc_user_changed = FALSE;
+ bool netrc_passwd_changed = FALSE;
int ret;
- if(data->set.use_netrc == CURL_NETRC_OPTIONAL)
- nuser = *userp; /* to separate otherwise identical machines */
-
ret = Curl_parsenetrc(conn->host.name,
- &nuser, &npasswd,
+ userp, passwdp,
+ &netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the "
@@ -3051,31 +3082,11 @@ static CURLcode override_login(struct Curl_easy *data,
conn->bits.netrc = TRUE;
conn->bits.user_passwd = TRUE; /* enable user+password */
- if(data->set.use_netrc == CURL_NETRC_OPTIONAL) {
- /* prefer credentials outside netrc */
- if(nuser && !*userp) {
- free(*userp);
- *userp = nuser;
- user_changed = TRUE;
- }
- if(npasswd && !*passwdp) {
- free(*passwdp);
- *passwdp = npasswd;
- passwd_changed = TRUE;
- }
+ if(netrc_user_changed) {
+ user_changed = TRUE;
}
- else {
- /* prefer netrc credentials */
- if(nuser) {
- free(*userp);
- *userp = nuser;
- user_changed = TRUE;
- }
- if(npasswd) {
- free(*passwdp);
- *passwdp = npasswd;
- passwd_changed = TRUE;
- }
+ if(netrc_passwd_changed) {
+ passwd_changed = TRUE;
}
}
}
@@ -3369,7 +3380,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
*************************************************************/
if(conn->bits.reuse)
/* We're reusing the connection - no need to resolve anything, and
- fix_hostname() was called already in create_conn() for the re-use
+ idnconvert_hostname() was called already in create_conn() for the re-use
case. */
*async = FALSE;
@@ -3424,7 +3435,10 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->port = conn->remote_port;
/* Resolve target host right on */
- rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
+ conn->hostname_resolve = strdup(connhost->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
+ rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
@@ -3445,7 +3459,10 @@ static CURLcode resolve_server(struct Curl_easy *data,
&conn->socks_proxy.host : &conn->http_proxy.host;
/* resolve proxy */
- rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
+ conn->hostname_resolve = strdup(host->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
+ rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
@@ -3475,8 +3492,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
static void reuse_conn(struct connectdata *old_conn,
struct connectdata *conn)
{
- free_fixed_hostname(&old_conn->http_proxy.host);
- free_fixed_hostname(&old_conn->socks_proxy.host);
+ free_idnconverted_hostname(&old_conn->http_proxy.host);
+ free_idnconverted_hostname(&old_conn->socks_proxy.host);
free(old_conn->http_proxy.host.rawalloc);
free(old_conn->socks_proxy.host.rawalloc);
@@ -3520,14 +3537,18 @@ static void reuse_conn(struct connectdata *old_conn,
/* host can change, when doing keepalive with a proxy or if the case is
different this time etc */
- free_fixed_hostname(&conn->host);
- free_fixed_hostname(&conn->conn_to_host);
+ free_idnconverted_hostname(&conn->host);
+ free_idnconverted_hostname(&conn->conn_to_host);
Curl_safefree(conn->host.rawalloc);
Curl_safefree(conn->conn_to_host.rawalloc);
conn->host = old_conn->host;
conn->conn_to_host = old_conn->conn_to_host;
conn->conn_to_port = old_conn->conn_to_port;
conn->remote_port = old_conn->remote_port;
+ Curl_safefree(conn->hostname_resolve);
+
+ conn->hostname_resolve = old_conn->hostname_resolve;
+ old_conn->hostname_resolve = NULL;
/* persist connection info in session handle */
Curl_persistconninfo(conn);
@@ -3677,30 +3698,30 @@ static CURLcode create_conn(struct Curl_easy *data,
goto out;
/*************************************************************
- * IDN-fix the hostnames
+ * IDN-convert the hostnames
*************************************************************/
- result = fix_hostname(conn, &conn->host);
+ result = idnconvert_hostname(conn, &conn->host);
if(result)
goto out;
if(conn->bits.conn_to_host) {
- result = fix_hostname(conn, &conn->conn_to_host);
+ result = idnconvert_hostname(conn, &conn->conn_to_host);
if(result)
goto out;
}
if(conn->bits.httpproxy) {
- result = fix_hostname(conn, &conn->http_proxy.host);
+ result = idnconvert_hostname(conn, &conn->http_proxy.host);
if(result)
goto out;
}
if(conn->bits.socksproxy) {
- result = fix_hostname(conn, &conn->socks_proxy.host);
+ result = idnconvert_hostname(conn, &conn->socks_proxy.host);
if(result)
goto out;
}
/*************************************************************
* Check whether the host and the "connect to host" are equal.
- * Do this after the hostnames have been IDN-fixed.
+ * Do this after the hostnames have been IDN-converted.
*************************************************************/
if(conn->bits.conn_to_host &&
strcasecompare(conn->conn_to_host.name, conn->host.name)) {
@@ -4028,6 +4049,15 @@ static CURLcode create_conn(struct Curl_easy *data,
*************************************************************/
result = resolve_server(data, conn, async);
+ /* Strip trailing dots. resolve_server copied the name. */
+ strip_trailing_dot(&conn->host);
+ if(conn->bits.httpproxy)
+ strip_trailing_dot(&conn->http_proxy.host);
+ if(conn->bits.socksproxy)
+ strip_trailing_dot(&conn->socks_proxy.host);
+ if(conn->bits.conn_to_host)
+ strip_trailing_dot(&conn->conn_to_host);
+
out:
return result;
}
diff --git a/libs/libcurl/src/urlapi-int.h b/libs/libcurl/src/urlapi-int.h
index a57d2e22bd..75a3605423 100644
--- a/libs/libcurl/src/urlapi-int.h
+++ b/libs/libcurl/src/urlapi-int.h
@@ -30,4 +30,9 @@ bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
char *Curl_concat_url(const char *base, const char *relurl);
size_t Curl_strlen_url(const char *url, bool relative);
void Curl_strcpy_url(char *output, const char *url, bool relative);
+
+#ifdef DEBUGBUILD
+CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname);
+#endif
+
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index c53e523434..5cbda6a98c 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -67,6 +67,12 @@ 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);
@@ -203,7 +209,7 @@ void Curl_strcpy_url(char *output, const char *url, bool relative)
/* FALLTHROUGH */
default:
if(urlchar_needs_escaping(*iptr)) {
- snprintf(optr, 4, "%%%02x", *iptr);
+ msnprintf(optr, 4, "%%%02x", *iptr);
optr += 3;
}
else
@@ -238,7 +244,7 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
#endif
for(i = 0; i < buflen && url[i]; ++i) {
char s = url[i];
- if(s == ':') {
+ if((s == ':') && (url[i + 1] == '/')) {
if(buf)
buf[i] = 0;
return TRUE;
@@ -488,19 +494,37 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
return result;
}
-static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
{
- char *portptr;
+ char *portptr = NULL;
char endbracket;
int len;
- if((1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.%%]%c%n",
- &endbracket, &len)) &&
- (']' == endbracket)) {
- /* this is a RFC2732-style specified IP-address */
- portptr = &hostname[len];
- if (*portptr != ':')
+ /*
+ * Find the end of an IPv6 address, either on the ']' ending bracket or
+ * a percent-encoded zone index.
+ */
+ if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n",
+ &endbracket, &len)) {
+ if(']' == endbracket)
+ portptr = &hostname[len];
+ else if('%' == endbracket) {
+ int zonelen = len;
+ if(1 == sscanf(hostname + zonelen, "25%*[^]]]%c%n", &endbracket, &len))
+ portptr = &hostname[--zonelen + len];
+ else
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else
return CURLUE_MALFORMED_INPUT;
+
+ /* this is a RFC2732-style specified IP-address */
+ if(portptr && *portptr) {
+ if(*portptr != ':')
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else
+ portptr = NULL;
}
else
portptr = strchr(hostname, ':');
@@ -527,7 +551,7 @@ static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
*portptr++ = '\0'; /* cut off the name there */
*rest = 0;
/* generate a new to get rid of leading zeroes etc */
- snprintf(portbuf, sizeof(portbuf), "%ld", port);
+ msnprintf(portbuf, sizeof(portbuf), "%ld", port);
u->portnum = port;
u->port = strdup(portbuf);
if(!u->port)
@@ -827,7 +851,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
if(result)
return result;
- result = parse_port(u, hostname);
+ result = Curl_parse_port(u, hostname);
if(result)
return result;
@@ -960,7 +984,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
const struct Curl_handler *h =
Curl_builtin_scheme(u->scheme);
if(h) {
- snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
ptr = portbuf;
}
}
@@ -1019,7 +1043,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there's no stored port number, but asked to deliver
a default one for the scheme */
if(h) {
- snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
port = portbuf;
}
}
@@ -1099,6 +1123,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
bool plusencode = FALSE;
bool urlskipslash = FALSE;
bool appendquery = FALSE;
+ bool equalsencode = FALSE;
if(!u)
return CURLUE_BAD_HANDLE;
@@ -1179,6 +1204,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
case CURLUPART_QUERY:
plusencode = urlencode;
appendquery = (flags & CURLU_APPENDQUERY)?1:0;
+ equalsencode = appendquery;
storep = &u->query;
break;
case CURLUPART_FRAGMENT:
@@ -1272,13 +1298,16 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
for(i = part, o = enc; *i; i++) {
if(Curl_isunreserved(*i) ||
((*i == '/') && urlskipslash) ||
- ((*i == '=') && appendquery) ||
+ ((*i == '=') && equalsencode) ||
((*i == '+') && plusencode)) {
+ if((*i == '=') && equalsencode)
+ /* only skip the first equals sign */
+ equalsencode = FALSE;
*o = *i;
o++;
}
else {
- snprintf(o, 4, "%%%02x", *i);
+ msnprintf(o, 4, "%%%02x", *i);
o += 3;
}
}
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h
index 11a6a22c61..448437d2ad 100644
--- a/libs/libcurl/src/urldata.h
+++ b/libs/libcurl/src/urldata.h
@@ -828,6 +828,7 @@ struct connectdata {
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
struct hostname host;
+ char *hostname_resolve; /* host name to resolve to address, allocated */
char *secondaryhostname; /* secondary socket host name (ftp) */
struct hostname conn_to_host; /* the host to connect to. valid only if
bits.conn_to_host is set */
@@ -1728,6 +1729,7 @@ struct UserDefined {
bool doh_get; /* use GET for DoH requests, instead of POST */
multidone_func fmultidone;
struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
+ CURLU *uh; /* URL handle for the current parsed URL */
};
struct Names {
diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c
index ab5156eb75..0f2e6509ef 100644
--- a/libs/libcurl/src/vauth/digest.c
+++ b/libs/libcurl/src/vauth/digest.c
@@ -143,7 +143,7 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
{
int i;
for(i = 0; i < 16; i++)
- snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+ msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
}
/* Convert sha256 chunk to RFC7616 -suitable ascii string*/
@@ -152,7 +152,7 @@ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
{
int i;
for(i = 0; i < 32; i++)
- snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+ msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
}
/* Perform quoted-string escaping as described in RFC2616 and its errata */
@@ -432,7 +432,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
/* Convert calculated 16 octet hex into 32 bytes string */
for(i = 0; i < MD5_DIGEST_LEN; i++)
- snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
+ msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
/* Generate our SPN */
spn = Curl_auth_build_spn(service, realm, NULL);
@@ -455,7 +455,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
Curl_MD5_final(ctxt, digest);
for(i = 0; i < MD5_DIGEST_LEN; i++)
- snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
+ msnprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
/* Now calculate the response hash */
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
@@ -485,7 +485,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
Curl_MD5_final(ctxt, digest);
for(i = 0; i < MD5_DIGEST_LEN; i++)
- snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
+ msnprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
/* Generate the response */
response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
diff --git a/libs/libcurl/src/vauth/ntlm.c b/libs/libcurl/src/vauth/ntlm.c
index 11f42f5042..458b272539 100644
--- a/libs/libcurl/src/vauth/ntlm.c
+++ b/libs/libcurl/src/vauth/ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -409,38 +409,38 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
#else
#define NTLM2FLAG 0
#endif
- snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
- NTLMSSP_SIGNATURE "%c"
- "\x01%c%c%c" /* 32-bit type = 1 */
- "%c%c%c%c" /* 32-bit NTLM flag field */
- "%c%c" /* domain length */
- "%c%c" /* domain allocated space */
- "%c%c" /* domain name offset */
- "%c%c" /* 2 zeroes */
- "%c%c" /* host length */
- "%c%c" /* host allocated space */
- "%c%c" /* host name offset */
- "%c%c" /* 2 zeroes */
- "%s" /* host name */
- "%s", /* domain string */
- 0, /* trailing zero */
- 0, 0, 0, /* part of type-1 long */
-
- LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
- NTLMFLAG_REQUEST_TARGET |
- NTLMFLAG_NEGOTIATE_NTLM_KEY |
- NTLM2FLAG |
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
- SHORTPAIR(domlen),
- SHORTPAIR(domlen),
- SHORTPAIR(domoff),
- 0, 0,
- SHORTPAIR(hostlen),
- SHORTPAIR(hostlen),
- SHORTPAIR(hostoff),
- 0, 0,
- host, /* this is empty */
- domain /* this is empty */);
+ msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x01%c%c%c" /* 32-bit type = 1 */
+ "%c%c%c%c" /* 32-bit NTLM flag field */
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host name offset */
+ "%c%c" /* 2 zeroes */
+ "%s" /* host name */
+ "%s", /* domain string */
+ 0, /* trailing zero */
+ 0, 0, 0, /* part of type-1 long */
+
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0, 0,
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0, 0,
+ host, /* this is empty */
+ domain /* this is empty */);
/* Initial packet length */
size = 32 + hostlen + domlen;
@@ -678,88 +678,88 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
hostoff = useroff + userlen;
/* Create the big type-3 message binary blob */
- size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
- NTLMSSP_SIGNATURE "%c"
- "\x03%c%c%c" /* 32-bit type = 3 */
-
- "%c%c" /* LanManager length */
- "%c%c" /* LanManager allocated space */
- "%c%c" /* LanManager offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* NT-response length */
- "%c%c" /* NT-response allocated space */
- "%c%c" /* NT-response offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* domain length */
- "%c%c" /* domain allocated space */
- "%c%c" /* domain name offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* user length */
- "%c%c" /* user allocated space */
- "%c%c" /* user offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* host length */
- "%c%c" /* host allocated space */
- "%c%c" /* host offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* session key length (unknown purpose) */
- "%c%c" /* session key allocated space (unknown purpose) */
- "%c%c" /* session key offset (unknown purpose) */
- "%c%c" /* 2 zeroes */
-
- "%c%c%c%c", /* flags */
-
- /* domain string */
- /* user string */
- /* host string */
- /* LanManager response */
- /* NT response */
-
- 0, /* zero termination */
- 0, 0, 0, /* type-3 long, the 24 upper bits */
-
- SHORTPAIR(0x18), /* LanManager response length, twice */
- SHORTPAIR(0x18),
- SHORTPAIR(lmrespoff),
- 0x0, 0x0,
+ size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x03%c%c%c" /* 32-bit type = 3 */
+
+ "%c%c" /* LanManager length */
+ "%c%c" /* LanManager allocated space */
+ "%c%c" /* LanManager offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* NT-response length */
+ "%c%c" /* NT-response allocated space */
+ "%c%c" /* NT-response offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* user length */
+ "%c%c" /* user allocated space */
+ "%c%c" /* user offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* session key length (unknown purpose) */
+ "%c%c" /* session key allocated space (unknown purpose) */
+ "%c%c" /* session key offset (unknown purpose) */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c%c%c", /* flags */
+
+ /* domain string */
+ /* user string */
+ /* host string */
+ /* LanManager response */
+ /* NT response */
+
+ 0, /* zero termination */
+ 0, 0, 0, /* type-3 long, the 24 upper bits */
+
+ SHORTPAIR(0x18), /* LanManager response length, twice */
+ SHORTPAIR(0x18),
+ SHORTPAIR(lmrespoff),
+ 0x0, 0x0,
#ifdef USE_NTRESPONSES
- SHORTPAIR(ntresplen), /* NT-response length, twice */
- SHORTPAIR(ntresplen),
- SHORTPAIR(ntrespoff),
- 0x0, 0x0,
+ SHORTPAIR(ntresplen), /* NT-response length, twice */
+ SHORTPAIR(ntresplen),
+ SHORTPAIR(ntrespoff),
+ 0x0, 0x0,
#else
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
#endif
- SHORTPAIR(domlen),
- SHORTPAIR(domlen),
- SHORTPAIR(domoff),
- 0x0, 0x0,
-
- SHORTPAIR(userlen),
- SHORTPAIR(userlen),
- SHORTPAIR(useroff),
- 0x0, 0x0,
-
- SHORTPAIR(hostlen),
- SHORTPAIR(hostlen),
- SHORTPAIR(hostoff),
- 0x0, 0x0,
-
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
-
- LONGQUARTET(ntlm->flags));
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0x0, 0x0,
+
+ SHORTPAIR(userlen),
+ SHORTPAIR(userlen),
+ SHORTPAIR(useroff),
+ 0x0, 0x0,
+
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0x0, 0x0,
+
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+
+ LONGQUARTET(ntlm->flags));
DEBUGASSERT(size == 64);
DEBUGASSERT(size == (size_t)lmrespoff);
diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c
index 05c2cd8b06..e553100c21 100644
--- a/libs/libcurl/src/version.c
+++ b/libs/libcurl/src/version.c
@@ -95,7 +95,7 @@ static size_t brotli_version(char *buf, size_t bufsz)
unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
unsigned int patch = brotli_version & 0x00000FFF;
- return snprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+ return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
}
#endif
@@ -126,12 +126,12 @@ char *curl_version(void)
}
#ifdef HAVE_LIBZ
- len = snprintf(ptr, left, " zlib/%s", zlibVersion());
+ len = msnprintf(ptr, left, " zlib/%s", zlibVersion());
left -= len;
ptr += len;
#endif
#ifdef HAVE_BROTLI
- len = snprintf(ptr, left, "%s", " brotli/");
+ len = msnprintf(ptr, left, "%s", " brotli/");
left -= len;
ptr += len;
len = brotli_version(ptr, left);
@@ -140,45 +140,45 @@ char *curl_version(void)
#endif
#ifdef USE_ARES
/* this function is only present in c-ares, not in the original ares */
- len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
+ len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL));
left -= len;
ptr += len;
#endif
#ifdef USE_LIBIDN2
if(idn2_check_version(IDN2_VERSION)) {
- len = snprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
+ len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
left -= len;
ptr += len;
}
#endif
#ifdef USE_LIBPSL
- len = snprintf(ptr, left, " libpsl/%s", psl_get_version());
+ len = msnprintf(ptr, left, " libpsl/%s", psl_get_version());
left -= len;
ptr += len;
#endif
#ifdef USE_WIN32_IDN
- len = snprintf(ptr, left, " WinIDN");
+ len = msnprintf(ptr, left, " WinIDN");
left -= len;
ptr += len;
#endif
#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
#ifdef _LIBICONV_VERSION
- len = snprintf(ptr, left, " iconv/%d.%d",
- _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
+ len = msnprintf(ptr, left, " iconv/%d.%d",
+ _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
#else
/* version unknown */
- len = snprintf(ptr, left, " iconv");
+ len = msnprintf(ptr, left, " iconv");
#endif /* _LIBICONV_VERSION */
left -= len;
ptr += len;
#endif
#ifdef USE_LIBSSH2
- len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
+ len = msnprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
left -= len;
ptr += len;
#endif
#ifdef USE_LIBSSH
- len = snprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION);
+ len = msnprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION);
left -= len;
ptr += len;
#endif
@@ -197,14 +197,14 @@ char *curl_version(void)
else
suff[0] = '\0';
- snprintf(ptr, left, " librtmp/%d.%d%s",
- RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
- suff);
+ msnprintf(ptr, left, " librtmp/%d.%d%s",
+ RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
+ suff);
/*
If another lib version is added below this one, this code would
also have to do:
- len = what snprintf() returned
+ len = what msnprintf() returned
left -= len;
ptr += len;
@@ -436,10 +436,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
#endif
#if defined(USE_LIBSSH2)
- snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
+ msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
version_info.libssh_version = ssh_buffer;
#elif defined(USE_LIBSSH)
- snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION);
+ msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION);
version_info.libssh_version = ssh_buffer;
#endif
diff --git a/libs/libcurl/src/vtls/axtls.c b/libs/libcurl/src/vtls/axtls.c
deleted file mode 100644
index b262392a00..0000000000
--- a/libs/libcurl/src/vtls/axtls.c
+++ /dev/null
@@ -1,741 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * 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 axTLS-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_AXTLS
-
-#error axTLS support has been disabled in curl due to doubts about quality,
-#error user dedication and a lack of use/testing. We urge users to consider
-#error using a more established TLS backend instead.
-
-#include <axTLS/config.h>
-#include <axTLS/ssl.h>
-#include "axtls.h"
-
-#include "sendf.h"
-#include "inet_pton.h"
-#include "vtls.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "curl_printf.h"
-#include "hostcheck.h"
-#include <unistd.h>
-
-/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
-
-struct ssl_backend_data {
- SSL_CTX* ssl_ctx;
- SSL* ssl;
-};
-
-#define BACKEND connssl->backend
-
-static CURLcode map_error_to_curl(int axtls_err)
-{
- switch(axtls_err) {
- case SSL_ERROR_NOT_SUPPORTED:
- case SSL_ERROR_INVALID_VERSION:
- case -70: /* protocol version alert from server */
- return CURLE_UNSUPPORTED_PROTOCOL;
- break;
- case SSL_ERROR_NO_CIPHER:
- return CURLE_SSL_CIPHER;
- break;
- case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
- case SSL_ERROR_NO_CERT_DEFINED:
- case -42: /* bad certificate alert from server */
- case -43: /* unsupported cert alert from server */
- case -44: /* cert revoked alert from server */
- case -45: /* cert expired alert from server */
- case -46: /* cert unknown alert from server */
- return CURLE_SSL_CERTPROBLEM;
- break;
- case SSL_X509_ERROR(X509_NOT_OK):
- case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
- case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
- case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
- case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
- case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
- case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
- case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
- case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
- return CURLE_PEER_FAILED_VERIFICATION;
- break;
- case -48: /* unknown ca alert from server */
- return CURLE_SSL_CACERT;
- break;
- case -49: /* access denied alert from server */
- return CURLE_REMOTE_ACCESS_DENIED;
- break;
- case SSL_ERROR_CONN_LOST:
- case SSL_ERROR_SOCK_SETUP_FAILURE:
- case SSL_ERROR_INVALID_HANDSHAKE:
- case SSL_ERROR_INVALID_PROT_MSG:
- case SSL_ERROR_INVALID_HMAC:
- case SSL_ERROR_INVALID_SESSION:
- case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
- case SSL_ERROR_FINISHED_INVALID:
- case SSL_ERROR_NO_CLIENT_RENOG:
- default:
- return CURLE_SSL_CONNECT_ERROR;
- break;
- }
-}
-
-static Curl_recv axtls_recv;
-static Curl_send axtls_send;
-
-static void free_ssl_structs(struct ssl_connect_data *connssl)
-{
- if(BACKEND->ssl) {
- ssl_free(BACKEND->ssl);
- BACKEND->ssl = NULL;
- }
- if(BACKEND->ssl_ctx) {
- ssl_ctx_free(BACKEND->ssl_ctx);
- BACKEND->ssl_ctx = NULL;
- }
-}
-
-/*
- * For both blocking and non-blocking connects, this function sets up the
- * ssl context and state. This function is called after the TCP connect
- * has completed.
- */
-static CURLcode connect_prep(struct connectdata *conn, int sockindex)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
- SSL_CTX *ssl_ctx;
- SSL *ssl = NULL;
- int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
- int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
- int i, ssl_fcn_return;
-
- /* Assuming users will not compile in custom key/cert to axTLS.
- * Also, even for blocking connects, use axTLS non-blocking feature.
- */
- uint32_t client_option = SSL_NO_DEFAULT_KEY |
- SSL_SERVER_VERIFY_LATER |
- SSL_CONNECT_IN_PARTS;
-
- if(connssl->state == ssl_connection_complete)
- /* to make us tolerant against being called more than once for the
- same connection */
- return CURLE_OK;
-
- if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
- failf(data, "axtls does not support CURL_SSLVERSION_MAX");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
-
- /* axTLS only supports TLSv1 */
- /* check to see if we've been told to use an explicit SSL/TLS version */
- switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- break;
- default:
- failf(data, "axTLS only supports TLS 1.0 and 1.1, "
- "and it cannot be specified which one to use");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
-#ifdef AXTLSDEBUG
- client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
-#endif /* AXTLSDEBUG */
-
- /* Allocate an SSL_CTX struct */
- ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
- if(ssl_ctx == NULL) {
- failf(data, "unable to create client SSL context");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- BACKEND->ssl_ctx = ssl_ctx;
- BACKEND->ssl = NULL;
-
- /* Load the trusted CA cert bundle file */
- if(SSL_CONN_CONFIG(CAfile)) {
- if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
- SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
- infof(data, "error reading ca cert file %s \n",
- SSL_CONN_CONFIG(CAfile));
- if(SSL_CONN_CONFIG(verifypeer)) {
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
- else
- infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
- }
-
- /* gtls.c tasks we're skipping for now:
- * 1) certificate revocation list checking
- * 2) dns name assignment to host
- * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore
- * 4) set certificate priority. axTLS ignores type and sends certs in
- * order added. can probably ignore this.
- */
-
- /* Load client certificate */
- if(SSL_SET_OPTION(cert)) {
- i = 0;
- /* Instead of trying to analyze cert type here, let axTLS try them all. */
- while(cert_types[i] != 0) {
- ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
- SSL_SET_OPTION(cert), NULL);
- if(ssl_fcn_return == SSL_OK) {
- infof(data, "successfully read cert file %s \n",
- SSL_SET_OPTION(cert));
- break;
- }
- i++;
- }
- /* Tried all cert types, none worked. */
- if(cert_types[i] == 0) {
- failf(data, "%s is not x509 or pkcs12 format",
- SSL_SET_OPTION(cert));
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- /* Load client key.
- If a pkcs12 file successfully loaded a cert, then there's nothing to do
- because the key has already been loaded. */
- if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
- i = 0;
- /* Instead of trying to analyze key type here, let axTLS try them all. */
- while(key_types[i] != 0) {
- ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
- SSL_SET_OPTION(key), NULL);
- if(ssl_fcn_return == SSL_OK) {
- infof(data, "successfully read key file %s \n",
- SSL_SET_OPTION(key));
- break;
- }
- i++;
- }
- /* Tried all key types, none worked. */
- if(key_types[i] == 0) {
- failf(data, "Failure: %s is not a supported key file",
- SSL_SET_OPTION(key));
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-
- /* gtls.c does more here that is being left out for now
- * 1) set session credentials. can probably ignore since axtls puts this
- * info in the ssl_ctx struct
- * 2) setting up callbacks. these seem gnutls specific
- */
-
- if(SSL_SET_OPTION(primary.sessionid)) {
- const uint8_t *ssl_sessionid;
- size_t ssl_idsize;
-
- /* In axTLS, handshaking happens inside ssl_client_new. */
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
- sockindex)) {
- /* we got a session id, use it! */
- infof(data, "SSL re-using session ID\n");
- ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
- ssl_sessionid, (uint8_t)ssl_idsize, NULL);
- }
- Curl_ssl_sessionid_unlock(conn);
- }
-
- if(!ssl)
- ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
-
- BACKEND->ssl = ssl;
- return CURLE_OK;
-}
-
-static void Curl_axtls_close(struct connectdata *conn, int sockindex)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
- infof(conn->data, " Curl_axtls_close\n");
-
- /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
- axTLS compat layer does nothing for SSL_shutdown */
-
- /* The following line is from openssl.c. There seems to be no axTLS
- equivalent. ssl_free and ssl_ctx_free close things.
- SSL_set_connect_state(connssl->handle); */
-
- free_ssl_structs(connssl);
-}
-
-/*
- * For both blocking and non-blocking connects, this function finalizes the
- * SSL connection.
- */
-static CURLcode connect_finish(struct connectdata *conn, int sockindex)
-{
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SSL *ssl = BACKEND->ssl;
- const char *peer_CN;
- uint32_t dns_altname_index;
- const char *dns_altname;
- int8_t found_subject_alt_names = 0;
- int8_t found_subject_alt_name_matching_conn = 0;
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
-
- /* Here, gtls.c gets the peer certificates and fails out depending on
- * settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
- */
-
- /* Verify server's certificate */
- if(SSL_CONN_CONFIG(verifypeer)) {
- if(ssl_verify_cert(ssl) != SSL_OK) {
- Curl_axtls_close(conn, sockindex);
- failf(data, "server cert verify failed");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- }
- else
- infof(data, "\t server certificate verification SKIPPED\n");
-
- /* Here, gtls.c does issuer verification. axTLS has no straightforward
- * equivalent, so omitting for now.*/
-
- /* Here, gtls.c does the following
- * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but
- * it seems useful. This is now implemented, by Oscar Koeroo
- * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert
- * 3) displays a bunch of cert information. axTLS doesn't support most of
- * this, but a couple fields are available.
- */
-
- /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
- risk of an inifite loop */
- for(dns_altname_index = 0; ; dns_altname_index++) {
- dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
- if(dns_altname == NULL) {
- break;
- }
- found_subject_alt_names = 1;
-
- infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
- dns_altname, hostname);
- if(Curl_cert_hostcheck(dns_altname, hostname)) {
- found_subject_alt_name_matching_conn = 1;
- break;
- }
- }
-
- /* RFC2818 checks */
- if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
- if(SSL_CONN_CONFIG(verifyhost)) {
- /* Break connection ! */
- Curl_axtls_close(conn, sockindex);
- failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
- }
- else if(found_subject_alt_names == 0) {
- /* Per RFC2818, when no Subject Alt Names were available, examine the peer
- CN as a legacy fallback */
- peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
- if(peer_CN == NULL) {
- if(SSL_CONN_CONFIG(verifyhost)) {
- Curl_axtls_close(conn, sockindex);
- failf(data, "unable to obtain common name from peer certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- infof(data, "unable to obtain common name from peer certificate");
- }
- else {
- if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
- if(SSL_CONN_CONFIG(verifyhost)) {
- /* Break connection ! */
- Curl_axtls_close(conn, sockindex);
- failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
- peer_CN, dispname);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
- peer_CN, dispname);
- }
- }
- }
-
- /* General housekeeping */
- connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = axtls_recv;
- conn->send[sockindex] = axtls_send;
-
- /* Put our freshly minted SSL session in cache */
- if(SSL_SET_OPTION(primary.sessionid)) {
- const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
- size_t ssl_idsize = ssl_get_session_id_size(ssl);
- Curl_ssl_sessionid_lock(conn);
- if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
- sockindex) != CURLE_OK)
- infof(data, "failed to add session to cache\n");
- Curl_ssl_sessionid_unlock(conn);
- }
-
- return CURLE_OK;
-}
-
-/*
- * Use axTLS's non-blocking connection feature to open an SSL connection.
- * This is called after a TCP connection is already established.
- */
-static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- CURLcode conn_step;
- int ssl_fcn_return;
- int i;
-
- *done = FALSE;
- /* connectdata is calloc'd and connecting_state is only changed in this
- function, so this is safe, as the state is effectively initialized. */
- if(connssl->connecting_state == ssl_connect_1) {
- conn_step = connect_prep(conn, sockindex);
- if(conn_step != CURLE_OK) {
- Curl_axtls_close(conn, sockindex);
- return conn_step;
- }
- connssl->connecting_state = ssl_connect_2;
- }
-
- if(connssl->connecting_state == ssl_connect_2) {
- /* Check to make sure handshake was ok. */
- if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) {
- /* Loop to perform more work in between sleeps. This is work around the
- fact that axtls does not expose any knowledge about when work needs
- to be performed. This can save ~25% of time on SSL handshakes. */
- for(i = 0; i<5; i++) {
- ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
- if(ssl_fcn_return < 0) {
- Curl_axtls_close(conn, sockindex);
- ssl_display_error(ssl_fcn_return); /* goes to stdout. */
- return map_error_to_curl(ssl_fcn_return);
- }
- return CURLE_OK;
- }
- }
- infof(conn->data, "handshake completed successfully\n");
- connssl->connecting_state = ssl_connect_3;
- }
-
- if(connssl->connecting_state == ssl_connect_3) {
- conn_step = connect_finish(conn, sockindex);
- if(conn_step != CURLE_OK) {
- Curl_axtls_close(conn, sockindex);
- return conn_step;
- }
-
- /* Reset connect state */
- connssl->connecting_state = ssl_connect_1;
-
- *done = TRUE;
- return CURLE_OK;
- }
-
- /* Unrecognized state. Things are very bad. */
- connssl->state = ssl_connection_none;
- connssl->connecting_state = ssl_connect_1;
- /* Return value perhaps not strictly correct, but distinguishes the issue.*/
- return CURLE_BAD_FUNCTION_ARGUMENT;
-}
-
-
-/*
- * This function is called after the TCP connect has completed. Setup the TLS
- * layer and do all necessary magic for a blocking connect.
- */
-static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
-{
- struct Curl_easy *data = conn->data;
- CURLcode conn_step = connect_prep(conn, sockindex);
- int ssl_fcn_return;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SSL *ssl = BACKEND->ssl;
- long timeout_ms;
-
- if(conn_step != CURLE_OK) {
- Curl_axtls_close(conn, sockindex);
- return conn_step;
- }
-
- /* Check to make sure handshake was ok. */
- while(ssl_handshake_status(ssl) != SSL_OK) {
- /* 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;
- }
-
- ssl_fcn_return = ssl_read(ssl, NULL);
- if(ssl_fcn_return < 0) {
- Curl_axtls_close(conn, sockindex);
- ssl_display_error(ssl_fcn_return); /* goes to stdout. */
- return map_error_to_curl(ssl_fcn_return);
- }
- /* TODO: avoid polling */
- Curl_wait_ms(10);
- }
- infof(conn->data, "handshake completed successfully\n");
-
- conn_step = connect_finish(conn, sockindex);
- if(conn_step != CURLE_OK) {
- Curl_axtls_close(conn, sockindex);
- return conn_step;
- }
-
- return CURLE_OK;
-}
-
-/* return number of sent (non-SSL) bytes */
-static ssize_t axtls_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *err)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
- int rc = ssl_write(BACKEND->ssl, mem, (int)len);
-
- infof(conn->data, " axtls_send\n");
-
- if(rc < 0) {
- *err = map_error_to_curl(rc);
- rc = -1; /* generic error code for send failure */
- }
-
- *err = CURLE_OK;
- return rc;
-}
-
-/*
- * This function is called to shut down the SSL layer but keep the
- * socket open (CCC - Clear Command Channel)
- */
-static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
-{
- /* Outline taken from openssl.c since functions are in axTLS compat layer.
- axTLS's error set is much smaller, so a lot of error-handling was removed.
- */
- int retval = 0;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
- uint8_t *buf;
- ssize_t nread;
-
- infof(conn->data, " Curl_axtls_shutdown\n");
-
- /* This has only been tested on the proftpd server, and the mod_tls code
- sends a close notify alert without waiting for a close notify alert in
- response. Thus we wait for a close notify alert from the server, but
- we do not send one. Let's hope other servers do the same... */
-
- /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
- if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- (void)SSL_shutdown(BACKEND->ssl);
- */
-
- if(BACKEND->ssl) {
- int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
- if(what > 0) {
- /* Something to read, let's do it and hope that it is the close
- notify alert from the server. buf is managed internally by
- axTLS and will be released upon calling ssl_free via
- free_ssl_structs. */
- nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
-
- if(nread < SSL_OK) {
- failf(data, "close notify alert not received during shutdown");
- retval = -1;
- }
- }
- else if(0 == what) {
- /* timeout */
- failf(data, "SSL shutdown timeout");
- }
- else {
- /* anything that gets here is fatally bad */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- retval = -1;
- }
-
- free_ssl_structs(connssl);
- }
- return retval;
-}
-
-static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
- int num, /* socketindex */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
- CURLcode *err)
-{
- struct ssl_connect_data *connssl = &conn->ssl[num];
- ssize_t ret = 0;
- uint8_t *read_buf;
-
- infof(conn->data, " axtls_recv\n");
-
- *err = CURLE_OK;
- if(connssl) {
- ret = ssl_read(BACKEND->ssl, &read_buf);
- if(ret > SSL_OK) {
- /* ssl_read returns SSL_OK if there is more data to read, so if it is
- larger, then all data has been read already. */
- memcpy(buf, read_buf,
- (size_t)ret > buffersize ? buffersize : (size_t)ret);
- }
- else if(ret == SSL_OK) {
- /* more data to be read, signal caller to call again */
- *err = CURLE_AGAIN;
- ret = -1;
- }
- else if(ret == -3) {
- /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
- team approves proposed fix. */
- Curl_axtls_close(conn, num);
- }
- else {
- failf(conn->data, "axTLS recv error (%d)", ret);
- *err = map_error_to_curl((int) ret);
- ret = -1;
- }
- }
-
- return ret;
-}
-
-/*
- * 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_axtls_check_cxn(struct connectdata *conn)
-{
- /* openssl.c line:
- rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
- axTLS compat layer always returns the last argument, so connection is
- always alive? */
-
- infof(conn->data, " Curl_axtls_check_cxn\n");
- return 1; /* connection still in place */
-}
-
-static void Curl_axtls_session_free(void *ptr)
-{
- (void)ptr;
- /* free the ID */
- /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
- compatibility layer does nothing, so we do nothing too. */
-}
-
-static size_t Curl_axtls_version(char *buffer, size_t size)
-{
- return snprintf(buffer, size, "axTLS/%s", ssl_version());
-}
-
-static CURLcode Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
-{
- static bool ssl_seeded = FALSE;
- (void)data;
- if(!ssl_seeded) {
- ssl_seeded = TRUE;
- /* Initialize the seed if not already done. This call is not exactly thread
- * safe (and neither is the ssl_seeded check), but the worst effect of a
- * race condition is that some global resources will leak. */
- RNG_initialize();
- }
- get_random((int)length, entropy);
- return CURLE_OK;
-}
-
-static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- (void)info;
- return BACKEND->ssl;
-}
-
-const struct Curl_ssl Curl_ssl_axtls = {
- { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
- 0, /* no fancy stuff */
- sizeof(struct ssl_backend_data),
-
- /*
- * axTLS has no global init. Everything is done through SSL and SSL_CTX
- * structs stored in connectdata structure.
- */
- Curl_none_init, /* init */
- /* axTLS has no global cleanup. */
- Curl_none_cleanup, /* cleanup */
- Curl_axtls_version, /* version */
- Curl_axtls_check_cxn, /* check_cxn */
- Curl_axtls_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
- Curl_axtls_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
- Curl_axtls_connect, /* connect */
- Curl_axtls_connect_nonblocking, /* connect_nonblocking */
- Curl_axtls_get_internals, /* get_internals */
- Curl_axtls_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_axtls_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_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
-};
-
-#endif /* USE_AXTLS */
diff --git a/libs/libcurl/src/vtls/axtls.h b/libs/libcurl/src/vtls/axtls.h
deleted file mode 100644
index cb8187272d..0000000000
--- a/libs/libcurl/src/vtls/axtls.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef HEADER_CURL_AXTLS_H
-#define HEADER_CURL_AXTLS_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu@directv.com>
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#ifdef USE_AXTLS
-#include "curl/curl.h"
-#include "urldata.h"
-
-extern const struct Curl_ssl Curl_ssl_axtls;
-
-#endif /* USE_AXTLS */
-#endif /* HEADER_CURL_AXTLS_H */
diff --git a/libs/libcurl/src/vtls/cyassl.c b/libs/libcurl/src/vtls/cyassl.c
index e10398ac3f..0d45afbf0c 100644
--- a/libs/libcurl/src/vtls/cyassl.c
+++ b/libs/libcurl/src/vtls/cyassl.c
@@ -777,13 +777,13 @@ static void Curl_cyassl_session_free(void *ptr)
static size_t Curl_cyassl_version(char *buffer, size_t size)
{
#if LIBCYASSL_VERSION_HEX >= 0x03006000
- return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
+ return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
#elif defined(WOLFSSL_VERSION)
- return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
+ return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
#elif defined(CYASSL_VERSION)
- return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
+ return msnprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
#else
- return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
+ return msnprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
#endif
}
diff --git a/libs/libcurl/src/vtls/darwinssl.c b/libs/libcurl/src/vtls/darwinssl.c
index e8116b8a11..25b101282c 100644
--- a/libs/libcurl/src/vtls/darwinssl.c
+++ b/libs/libcurl/src/vtls/darwinssl.c
@@ -950,7 +950,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
if(!c) {
failf(data, "SSL: invalid CA certificate subject");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
/* If the subject is already available as UTF-8 encoded (ie 'direct') then
@@ -970,7 +970,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
if(!CFStringGetCString(c, cbuf, cbuf_size,
kCFStringEncodingUTF8)) {
failf(data, "SSL: invalid CA certificate subject");
- result = CURLE_SSL_CACERT;
+ result = CURLE_PEER_FAILED_VERIFICATION;
}
else
/* pass back the buffer */
@@ -1649,7 +1649,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
CFRelease(cert);
- if(result == CURLE_SSL_CACERT)
+ if(result == CURLE_PEER_FAILED_VERIFICATION)
return CURLE_SSL_CERTPROBLEM;
if(result)
return result;
@@ -2429,37 +2429,37 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* These are all certificate problems with the server: */
case errSSLXCertChainInvalid:
failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLUnknownRootCert:
failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLNoRootCert:
failf(data, "SSL certificate problem: No root certificate");
- return CURLE_SSL_CACERT;
+ 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_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLCertExpired:
case errSSLPeerCertExpired:
failf(data, "SSL certificate problem: Certificate chain had an "
"expired certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLBadCert:
case errSSLPeerBadCert:
failf(data, "SSL certificate problem: Couldn't understand the server "
"certificate format");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerUnsupportedCert:
failf(data, "SSL certificate problem: An unsupported certificate "
"format was encountered");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerCertRevoked:
failf(data, "SSL certificate problem: The certificate was revoked");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerCertUnknown:
failf(data, "SSL certificate problem: The certificate is unknown");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
/* These are all certificate problems with the client: */
case errSecAuthFailed:
@@ -3015,7 +3015,7 @@ static void Curl_darwinssl_session_free(void *ptr)
static size_t Curl_darwinssl_version(char *buffer, size_t size)
{
- return snprintf(buffer, size, "SecureTransport");
+ return msnprintf(buffer, size, "SecureTransport");
}
/*
diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c
index 8d1b3d6afc..c4afc89041 100644
--- a/libs/libcurl/src/vtls/gskit.c
+++ b/libs/libcurl/src/vtls/gskit.c
@@ -1314,7 +1314,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
static size_t Curl_gskit_version(char *buffer, size_t size)
{
- return snprintf(buffer, size, "GSKit");
+ return msnprintf(buffer, size, "GSKit");
}
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index 37662a748f..9035ec483e 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -227,17 +227,17 @@ static void showtime(struct Curl_easy *data,
if(result)
return;
- snprintf(str,
- sizeof(str),
- "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
- text,
- Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
- tm->tm_mday,
- Curl_month[tm->tm_mon],
- tm->tm_year + 1900,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec);
+ msnprintf(str,
+ sizeof(str),
+ "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
+ text,
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
infof(data, "%s\n", str);
}
#endif
@@ -1110,7 +1110,7 @@ gtls_connect_step3(struct connectdata *conn,
"CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
"none",
SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\t server certificate verification FAILED\n");
@@ -1748,7 +1748,7 @@ static void Curl_gtls_session_free(void *ptr)
static size_t Curl_gtls_version(char *buffer, size_t size)
{
- return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
+ return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
#ifndef USE_GNUTLS_NETTLE
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index c5ed8872ef..6a20e276e3 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -580,7 +580,7 @@ mbed_connect_step2(struct connectdata *conn,
if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
failf(data, "Cert verify failed: BADCERT_REVOKED");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
@@ -812,8 +812,8 @@ static void Curl_mbedtls_session_free(void *ptr)
static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
- return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
- (version>>16)&0xff, (version>>8)&0xff);
+ return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
+ (version>>16)&0xff, (version>>8)&0xff);
}
static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
diff --git a/libs/libcurl/src/vtls/mesalink.c b/libs/libcurl/src/vtls/mesalink.c
index 6a2b67e633..db14115593 100644
--- a/libs/libcurl/src/vtls/mesalink.c
+++ b/libs/libcurl/src/vtls/mesalink.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -424,7 +424,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
static size_t
Curl_mesalink_version(char *buffer, size_t size)
{
- return snprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
+ return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
}
static int
diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c
index a3d3e58bbe..08ee1aaaf2 100644
--- a/libs/libcurl/src/vtls/nss.c
+++ b/libs/libcurl/src/vtls/nss.c
@@ -246,6 +246,32 @@ static void nss_print_error_message(struct Curl_easy *data, PRUint32 err)
failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
}
+static char *nss_sslver_to_name(PRUint16 nssver)
+{
+ switch(nssver) {
+ case SSL_LIBRARY_VERSION_2:
+ return strdup("SSLv2");
+ case SSL_LIBRARY_VERSION_3_0:
+ return strdup("SSLv3");
+ case SSL_LIBRARY_VERSION_TLS_1_0:
+ return strdup("TLSv1.0");
+#ifdef SSL_LIBRARY_VERSION_TLS_1_1
+ case SSL_LIBRARY_VERSION_TLS_1_1:
+ return strdup("TLSv1.1");
+#endif
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ return strdup("TLSv1.2");
+#endif
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+ case SSL_LIBRARY_VERSION_TLS_1_3:
+ return strdup("TLSv1.3");
+#endif
+ default:
+ return curl_maprintf("0x%04x", nssver);
+ }
+}
+
static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
char *cipher_list)
{
@@ -1638,17 +1664,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
{
switch(version) {
- case CURL_SSLVERSION_TLSv1:
- /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
-#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
-#elif defined SSL_LIBRARY_VERSION_TLS_1_1
- *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
-#else
- *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
-#endif
- return CURLE_OK;
-
case CURL_SSLVERSION_SSLv2:
*nssver = SSL_LIBRARY_VERSION_2;
return CURLE_OK;
@@ -1709,10 +1724,8 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
}
switch(min) {
- case CURL_SSLVERSION_DEFAULT:
- break;
case CURL_SSLVERSION_TLSv1:
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ case CURL_SSLVERSION_DEFAULT:
break;
default:
result = nss_sslver_from_curl(&sslver->min, min);
@@ -1789,10 +1802,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode result;
bool second_layer = FALSE;
+ SSLVersionRange sslver_supported;
SSLVersionRange sslver = {
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
- SSL_LIBRARY_VERSION_TLS_1_0 /* max */
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+ SSL_LIBRARY_VERSION_TLS_1_3 /* max */
+#elif defined SSL_LIBRARY_VERSION_TLS_1_2
+ SSL_LIBRARY_VERSION_TLS_1_2
+#elif defined SSL_LIBRARY_VERSION_TLS_1_1
+ SSL_LIBRARY_VERSION_TLS_1_1
+#else
+ SSL_LIBRARY_VERSION_TLS_1_0
+#endif
};
BACKEND->data = data;
@@ -1841,6 +1863,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* enable/disable the requested SSL version(s) */
if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
goto error;
+ if(SSL_VersionRangeGetSupported(ssl_variant_stream,
+ &sslver_supported) != SECSuccess)
+ goto error;
+ if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) {
+ char *sslver_req_str, *sslver_supp_str;
+ sslver_req_str = nss_sslver_to_name(sslver.max);
+ sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
+ if(sslver_req_str && sslver_supp_str)
+ infof(data, "Falling back from %s to max supported SSL version (%s)\n",
+ sslver_req_str, sslver_supp_str);
+ free(sslver_req_str);
+ free(sslver_supp_str);
+ sslver.max = sslver_supported.max;
+ }
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
goto error;
@@ -2090,7 +2126,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
result = CURLE_PEER_FAILED_VERIFICATION;
else if(*certverifyresult != 0)
- result = CURLE_SSL_CACERT;
+ result = CURLE_PEER_FAILED_VERIFICATION;
goto error;
}
@@ -2164,7 +2200,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
if(!blocking)
/* CURLE_AGAIN in non-blocking mode is not an error */
return CURLE_OK;
- /* fall through */
+ /* FALLTHROUGH */
default:
return result;
}
@@ -2279,7 +2315,7 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
static size_t Curl_nss_version(char *buffer, size_t size)
{
- return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
+ return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
}
/* data might be NULL */
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index 4c5e8c19c0..8bddb9a8c6 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -69,7 +69,7 @@
#include <openssl/ocsp.h>
#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && /* 0.9.8 or later */ \
+#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \
!defined(OPENSSL_NO_ENGINE)
#define USE_OPENSSL_ENGINE
#include <openssl/engine.h>
@@ -82,6 +82,13 @@
#include "curl_memory.h"
#include "memdebug.h"
+/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
+ renegotiations when built with BoringSSL. Renegotiating is non-compliant
+ with HTTP/2 and "an extremely dangerous protocol feature". Beware.
+
+#define ALLOW_RENEG 1
+ */
+
#ifndef OPENSSL_VERSION_NUMBER
#error "OPENSSL_VERSION_NUMBER not defined"
#endif
@@ -384,6 +391,31 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
return buf;
}
+/* Return an extra data index for the connection data.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_conn_index(void)
+{
+ static int ssl_ex_data_conn_index = -1;
+ if(ssl_ex_data_conn_index < 0) {
+ ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ }
+ return ssl_ex_data_conn_index;
+}
+
+/* Return an extra data index for the sockindex.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_sockindex_index(void)
+{
+ static int ssl_ex_data_sockindex_index = -1;
+ if(ssl_ex_data_sockindex_index < 0) {
+ ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL,
+ NULL);
+ }
+ return ssl_ex_data_sockindex_index;
+}
+
static int passwd_callback(char *buf, int num, int encrypting,
void *global_passwd)
{
@@ -1035,6 +1067,10 @@ static int Curl_ossl_init(void)
}
#endif
+ /* Initialize the extra data indexes */
+ if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
+ return 0;
+
return 1;
}
@@ -1049,7 +1085,7 @@ static void Curl_ossl_cleanup(void)
/* Free ciphers and digests lists */
EVP_cleanup();
-#ifdef HAVE_ENGINE_CLEANUP
+#ifdef USE_OPENSSL_ENGINE
/* Free engine list */
ENGINE_cleanup();
#endif
@@ -1867,15 +1903,8 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
return "Unknown";
}
-static const char *tls_rt_type(int type, const void *buf, size_t buflen)
+static const char *tls_rt_type(int type)
{
- (void)buf;
- (void)buflen;
-#ifdef SSL3_RT_INNER_CONTENT_TYPE
- if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1)
- type = *(unsigned char *)buf;
-#endif
-
switch(type) {
#ifdef SSL3_RT_HEADER
case SSL3_RT_HEADER:
@@ -1945,12 +1974,20 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
case 0:
break;
default:
- snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
+ msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
verstr = unknown;
break;
}
- if(ssl_ver) {
+ /* Log progress for interesting records only (like Handshake or Alert), skip
+ * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
+ * For TLS 1.3, skip notification of the decrypted inner Content Type.
+ */
+ if(ssl_ver
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ && content_type != SSL3_RT_INNER_CONTENT_TYPE
+#endif
+ ) {
const char *msg_name, *tls_rt_name;
char ssl_buf[1024];
int msg_type, txt_len;
@@ -1964,17 +2001,10 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
* is at 'buf[0]'.
*/
if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
- tls_rt_name = tls_rt_type(content_type, buf, len);
+ tls_rt_name = tls_rt_type(content_type);
else
tls_rt_name = "";
-#ifdef SSL3_RT_INNER_CONTENT_TYPE
- if(content_type == SSL3_RT_INNER_CONTENT_TYPE) {
- msg_type = 0;
- msg_name = "[no content]";
- }
- else
-#endif
if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
msg_type = *(char *)buf;
msg_name = "Change cipher spec";
@@ -1988,9 +2018,9 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
msg_name = ssl_msg_type(ssl_ver, msg_type);
}
- txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
- verstr, direction?"OUT":"IN",
- tls_rt_name, msg_name, msg_type);
+ txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
+ verstr, direction?"OUT":"IN",
+ tls_rt_name, msg_name, msg_type);
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
}
@@ -2137,6 +2167,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
}
#else
(void)sockindex;
+ (void)ctx_options;
failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
return CURLE_NOT_BUILT_IN;
#endif
@@ -2189,6 +2220,62 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
return CURLE_OK;
}
+/* The "new session" callback must return zero if the session can be removed
+ * or non-zero if the session has been put into the session cache.
+ */
+static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+{
+ int res = 0;
+ struct connectdata *conn;
+ struct Curl_easy *data;
+ int sockindex;
+ curl_socket_t *sockindex_ptr;
+ int connectdata_idx = ossl_get_ssl_conn_index();
+ int sockindex_idx = ossl_get_ssl_sockindex_index();
+
+ if(connectdata_idx < 0 || sockindex_idx < 0)
+ return 0;
+
+ conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
+ if(!conn)
+ return 0;
+
+ data = conn->data;
+
+ /* The sockindex has been stored as a pointer to an array element */
+ sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
+ sockindex = (int)(sockindex_ptr - conn->sock);
+
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ bool incache;
+ void *old_ssl_sessionid = NULL;
+
+ Curl_ssl_sessionid_lock(conn);
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ sockindex));
+ if(incache) {
+ if(old_ssl_sessionid != ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
+ 0 /* unknown size */, sockindex)) {
+ /* the session has been put into the session cache */
+ res = 1;
+ }
+ else
+ failf(data, "failed to store ssl session");
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+
+ return res;
+}
+
static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
@@ -2585,6 +2672,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
#endif
+ /* Enable the session cache because it's a prerequisite for the "new session"
+ * callback. Use the "external storage" mode to avoid that OpenSSL creates
+ * an internal session cache.
+ */
+ SSL_CTX_set_session_cache_mode(BACKEND->ctx,
+ SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+ SSL_CTX_sess_set_new_cb(BACKEND->ctx, ossl_new_session_cb);
+
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
@@ -2610,6 +2705,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp);
#endif
+#if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG)
+ SSL_set_renegotiate_mode(BACKEND->handle, ssl_renegotiate_freely);
+#endif
+
SSL_set_connect_state(BACKEND->handle);
BACKEND->server_cert = 0x0;
@@ -2627,6 +2726,15 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
+ int connectdata_idx = ossl_get_ssl_conn_index();
+ int sockindex_idx = ossl_get_ssl_sockindex_index();
+
+ if(connectdata_idx >= 0 && sockindex_idx >= 0) {
+ /* Store the data needed for the "new session" callback.
+ * The sockindex is stored as a pointer to an array element. */
+ SSL_set_ex_data(BACKEND->handle, connectdata_idx, conn);
+ SSL_set_ex_data(BACKEND->handle, sockindex_idx, conn->sock + sockindex);
+ }
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
@@ -2721,14 +2829,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
if((lib == ERR_LIB_SSL) &&
(reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
- result = CURLE_SSL_CACERT;
+ result = CURLE_PEER_FAILED_VERIFICATION;
lerr = SSL_get_verify_result(BACKEND->handle);
if(lerr != X509_V_OK) {
*certverifyresult = lerr;
- snprintf(error_buffer, sizeof(error_buffer),
- "SSL certificate problem: %s",
- X509_verify_cert_error_string(lerr));
+ msnprintf(error_buffer, sizeof(error_buffer),
+ "SSL certificate problem: %s",
+ X509_verify_cert_error_string(lerr));
}
else
/* strcpy() is fine here as long as the string fits within
@@ -2839,7 +2947,7 @@ static void pubkey_show(struct Curl_easy *data,
char *ptr;
char namebuf[32];
- snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+ msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
if(bn)
BN_print(mem, bn);
@@ -2900,8 +3008,8 @@ static int X509V3_ext(struct Curl_easy *data,
while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
j++;
if(j<(size_t)biomem->length)
- ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
- biomem->data[j]);
+ ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+ biomem->data[j]);
}
Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
@@ -3214,20 +3322,8 @@ static CURLcode servercert(struct connectdata *conn,
/* we've been asked to gather certificate info! */
(void)get_cert_chain(conn, connssl);
- fp = BIO_new(BIO_s_file());
- if(fp == NULL) {
- failf(data,
- "BIO_new return NULL, " OSSL_PACKAGE
- " error %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- BIO_free(mem);
- return CURLE_OUT_OF_MEMORY;
- }
-
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
if(!BACKEND->server_cert) {
- BIO_free(fp);
BIO_free(mem);
if(!strict)
return CURLE_OK;
@@ -3262,7 +3358,6 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, BACKEND->server_cert);
if(result) {
- BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3284,6 +3379,18 @@ static CURLcode servercert(struct connectdata *conn,
/* e.g. match issuer name with provided issuer certificate */
if(SSL_SET_OPTION(issuercert)) {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
@@ -3319,6 +3426,7 @@ static CURLcode servercert(struct connectdata *conn,
infof(data, " SSL certificate issuer check ok (%s)\n",
SSL_SET_OPTION(issuercert));
+ BIO_free(fp);
X509_free(issuer);
}
@@ -3347,7 +3455,6 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
- BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3367,7 +3474,6 @@ static CURLcode servercert(struct connectdata *conn,
failf(data, "SSL: public key does not match pinned public key!");
}
- BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
@@ -3378,52 +3484,10 @@ static CURLcode servercert(struct connectdata *conn,
static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(SSL_SET_OPTION(primary.sessionid)) {
- bool incache;
- SSL_SESSION *our_ssl_sessionid;
- void *old_ssl_sessionid = NULL;
-
- our_ssl_sessionid = SSL_get1_session(BACKEND->handle);
-
- /* SSL_get1_session() will increment the reference count and the session
- will stay in memory until explicitly freed with SSL_SESSION_free(3),
- regardless of its state. */
-
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
- sockindex));
- if(incache) {
- if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- incache = FALSE;
- }
- }
-
- if(!incache) {
- result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */, sockindex);
- if(result) {
- Curl_ssl_sessionid_unlock(conn);
- failf(data, "failed to store ssl session");
- return result;
- }
- }
- else {
- /* Session was incache, so refcount already incremented earlier.
- * Avoid further increments with each SSL_get1_session() call.
- * This does not free the session as refcount remains > 0
- */
- SSL_SESSION_free(our_ssl_sessionid);
- }
- Curl_ssl_sessionid_unlock(conn);
- }
-
/*
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
@@ -3709,7 +3773,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
static size_t Curl_ossl_version(char *buffer, size_t size)
{
#ifdef OPENSSL_IS_BORINGSSL
- return snprintf(buffer, size, OSSL_PACKAGE);
+ return msnprintf(buffer, size, OSSL_PACKAGE);
#else /* OPENSSL_IS_BORINGSSL */
char sub[3];
unsigned long ssleay_value;
@@ -3736,12 +3800,12 @@ static size_t Curl_ossl_version(char *buffer, size_t size)
sub[0]='\0';
}
- return snprintf(buffer, size, "%s/%lx.%lx.%lx%s",
- OSSL_PACKAGE,
- (ssleay_value>>28)&0xf,
- (ssleay_value>>20)&0xff,
- (ssleay_value>>12)&0xff,
- sub);
+ return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s",
+ OSSL_PACKAGE,
+ (ssleay_value>>28)&0xf,
+ (ssleay_value>>20)&0xff,
+ (ssleay_value>>12)&0xff,
+ sub);
#endif /* OPENSSL_IS_BORINGSSL */
}
diff --git a/libs/libcurl/src/vtls/polarssl.c b/libs/libcurl/src/vtls/polarssl.c
index 27af0ccf3e..6ecabe94b5 100644
--- a/libs/libcurl/src/vtls/polarssl.c
+++ b/libs/libcurl/src/vtls/polarssl.c
@@ -497,7 +497,7 @@ polarssl_connect_step2(struct connectdata *conn,
if(ret & BADCERT_REVOKED) {
failf(data, "Cert verify failed: BADCERT_REVOKED");
- return CURLE_SSL_CACERT;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
if(ret & BADCERT_CN_MISMATCH)
@@ -716,9 +716,9 @@ static void Curl_polarssl_session_free(void *ptr)
static size_t Curl_polarssl_version(char *buffer, size_t size)
{
unsigned int version = version_get_number();
- return snprintf(buffer, size, "%s/%d.%d.%d",
- version >= 0x01030A00?"mbedTLS":"PolarSSL",
- version>>24, (version>>16)&0xff, (version>>8)&0xff);
+ return msnprintf(buffer, size, "%s/%d.%d.%d",
+ version >= 0x01030A00?"mbedTLS":"PolarSSL",
+ version>>24, (version>>16)&0xff, (version>>8)&0xff);
}
static CURLcode
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index e4426924bc..56fd93e1e5 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -23,9 +23,8 @@
***************************************************************************/
/*
- * Source file for all SChannel-specific code for the TLS/SSL layer. No code
+ * Source file for all Schannel-specific code for the TLS/SSL layer. No code
* but vtls.c should ever call or use these functions.
- *
*/
/*
@@ -196,7 +195,7 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "Schannel: TLS 1.3 is not yet supported");
+ failf(data, "schannel: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -434,7 +433,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
- /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and
+ /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
algorithms that may not be supported by all servers. */
infof(data, "schannel: WinSSL version is old and may not be able to "
"connect to some servers due to lack of SNI, algorithms, etc.\n");
@@ -1114,13 +1113,68 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
#ifdef HAS_MANUAL_VERIFY_API
if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
- return verify_certificate(conn, sockindex);
+ return Curl_verify_certificate(conn, sockindex);
}
#endif
return CURLE_OK;
}
+static bool
+valid_cert_encoding(const CERT_CONTEXT *cert_context)
+{
+ return (cert_context != NULL) &&
+ ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
+ (cert_context->pbCertEncoded != NULL) &&
+ (cert_context->cbCertEncoded > 0);
+}
+
+typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg);
+
+static void
+traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
+ void *arg)
+{
+ const CERT_CONTEXT *current_context = NULL;
+ bool should_continue = true;
+ while(should_continue &&
+ (current_context = CertEnumCertificatesInStore(
+ context->hCertStore,
+ current_context)) != NULL)
+ should_continue = func(current_context, arg);
+
+ if(current_context)
+ CertFreeCertificateContext(current_context);
+}
+
+static bool
+cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
+{
+ if(valid_cert_encoding(ccert_context))
+ (*(int *)certs_count)++;
+ return true;
+}
+
+struct Adder_args
+{
+ struct connectdata *conn;
+ CURLcode result;
+ int idx;
+};
+
+static bool
+add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
+{
+ struct Adder_args *args = (struct Adder_args*)raw_arg;
+ args->result = CURLE_OK;
+ if(valid_cert_encoding(ccert_context)) {
+ const char *beg = (const char *) ccert_context->pbCertEncoded;
+ const char *end = beg + ccert_context->cbCertEncoded;
+ args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end);
+ }
+ return args->result == CURLE_OK;
+}
+
static CURLcode
schannel_connect_step3(struct connectdata *conn, int sockindex)
{
@@ -1230,6 +1284,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
if(data->set.ssl.certinfo) {
+ int certs_count = 0;
sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
@@ -1238,15 +1293,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
return CURLE_PEER_FAILED_VERIFICATION;
}
- result = Curl_ssl_init_certinfo(data, 1);
- if(!result) {
- if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
- (ccert_context->cbCertEncoded > 0)) {
+ traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);
- const char *beg = (const char *) ccert_context->pbCertEncoded;
- const char *end = beg + ccert_context->cbCertEncoded;
- result = Curl_extract_certinfo(conn, 0, beg, end);
- }
+ result = Curl_ssl_init_certinfo(data, certs_count);
+ if(!result) {
+ struct Adder_args args;
+ args.conn = conn;
+ args.idx = 0;
+ traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
+ result = args.result;
}
CertFreeCertificateContext(ccert_context);
if(result)
@@ -1994,7 +2049,7 @@ static void Curl_schannel_cleanup(void)
static size_t Curl_schannel_version(char *buffer, size_t size)
{
- size = snprintf(buffer, size, "WinSSL");
+ size = msnprintf(buffer, size, "WinSSL");
return size;
}
diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h
index e491bd4318..ee8d7d47ac 100644
--- a/libs/libcurl/src/vtls/schannel.h
+++ b/libs/libcurl/src/vtls/schannel.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,7 +53,7 @@
extern const struct Curl_ssl Curl_ssl_schannel;
-CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index 2516f56657..8b21624ba4 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -23,7 +23,7 @@
***************************************************************************/
/*
- * Source file for SChannel-specific certificate verification. This code should
+ * Source file for Schannel-specific certificate verification. This code should
* only be invoked by code in schannel.c.
*/
@@ -406,7 +406,7 @@ cleanup:
return result;
}
-CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
{
SECURITY_STATUS status;
struct Curl_easy *data = conn->data;
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index 6af39feab9..5e75f92e99 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -700,7 +700,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
/* sprintf the label and colon */
- snprintf(output, outlen, "%s:", label);
+ msnprintf(output, outlen, "%s:", label);
/* memcpy the value (it might not be zero terminated) */
memcpy(&output[labellen + 1], value, valuelen);
@@ -1170,8 +1170,6 @@ static const struct Curl_ssl Curl_ssl_multi = {
const struct Curl_ssl *Curl_ssl =
#if defined(CURL_WITH_MULTI_SSL)
&Curl_ssl_multi;
-#elif defined(USE_AXTLS)
- &Curl_ssl_axtls;
#elif defined(USE_CYASSL)
&Curl_ssl_cyassl;
#elif defined(USE_DARWINSSL)
@@ -1197,9 +1195,6 @@ const struct Curl_ssl *Curl_ssl =
#endif
static const struct Curl_ssl *available_backends[] = {
-#if defined(USE_AXTLS)
- &Curl_ssl_axtls,
-#endif
#if defined(USE_CYASSL)
&Curl_ssl_cyassl,
#endif
@@ -1318,7 +1313,14 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
*avail = (const curl_ssl_backend **)&available_backends;
if(Curl_ssl != &Curl_ssl_multi)
- return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+ return id == Curl_ssl->info.id ||
+ (name && strcasecompare(name, Curl_ssl->info.name)) ?
+ CURLSSLSET_OK :
+#if defined(CURL_WITH_MULTI_SSL)
+ CURLSSLSET_TOO_LATE;
+#else
+ CURLSSLSET_UNKNOWN_BACKEND;
+#endif
for(i = 0; available_backends[i]; i++) {
if(available_backends[i]->info.id == id ||
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index 5cd11602e7..1f163631f7 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -103,7 +103,6 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#include "nssg.h" /* NSS versions */
#include "gskit.h" /* Global Secure ToolKit versions */
#include "polarssl.h" /* PolarSSL versions */
-#include "axtls.h" /* axTLS versions */
#include "cyassl.h" /* CyaSSL versions */
#include "schannel.h" /* Schannel SSPI version */
#include "darwinssl.h" /* SecureTransport (Darwin) version */
diff --git a/libs/libcurl/src/x509asn1.c b/libs/libcurl/src/x509asn1.c
index a576fc703b..746e1e8e8d 100644
--- a/libs/libcurl/src/x509asn1.c
+++ b/libs/libcurl/src/x509asn1.c
@@ -209,7 +209,7 @@ static const char *octet2str(const char *beg, const char *end)
buf = malloc(3 * n + 1);
if(buf)
for(n = 0; beg < end; n += 3)
- snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+ msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
}
return buf;
}