diff options
Diffstat (limited to 'lib')
184 files changed, 7518 insertions, 9888 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 49a340938..e7886ac55 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -98,7 +98,4 @@ if(WIN32) endif() endif() -install(TARGETS ${LIB_NAME} - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin) +install(TARGETS ${LIB_NAME} DESTINATION lib) diff --git a/lib/Makefile.Watcom b/lib/Makefile.Watcom index 0b7ba59c2..14f5ac844 100644 --- a/lib/Makefile.Watcom +++ b/lib/Makefile.Watcom @@ -101,7 +101,7 @@ ZLIB_ROOT = ../../zlib-1.2.8 !ifdef %libssh2_root LIBSSH2_ROOT = $(%libssh2_root) !else -LIBSSH2_ROOT = ../../libssh2-1.5.0 +LIBSSH2_ROOT = ../../libssh2-1.4.3 !endif !ifdef %librtmp_root @@ -113,7 +113,7 @@ LIBRTMP_ROOT = ../../rtmpdump-2.3 !ifdef %openssl_root OPENSSL_ROOT = $(%openssl_root) !else -OPENSSL_ROOT = ../../openssl-1.0.2a +OPENSSL_ROOT = ../../openssl-0.9.8zc !endif !ifdef %ares_root diff --git a/lib/Makefile.am b/lib/Makefile.am index ef8d124e7..6dffbd9c9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2013, 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 @@ -21,6 +21,10 @@ ########################################################################### AUTOMAKE_OPTIONS = foreign nostdinc +DOCS = README.encoding README.memoryleak README.ares README.curlx \ + README.hostip README.multi_socket README.httpauth README.pipelining \ + README.curl_off_t README.pingpong + CMAKE_DIST = CMakeLists.txt curl_config.h.cmake EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 config-win32.h \ @@ -28,9 +32,9 @@ EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 config-win32.h \ makefile.dj config-dos.h libcurl.plist libcurl.rc config-amigaos.h \ makefile.amiga Makefile.netware nwlib.c nwos.c config-win32ce.h \ config-os400.h setup-os400.h config-symbian.h Makefile.Watcom \ - config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ + config-tpf.h $(DOCS) mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl \ - objnames-test08.sh objnames-test10.sh objnames.inc checksrc.whitelist + objnames-test08.sh objnames-test10.sh objnames.inc lib_LTLIBRARIES = libcurl.la @@ -80,9 +84,9 @@ if SONAME_BUMP # # This conditional soname bump SHOULD be removed at next "proper" bump. # -VERSIONINFO=-version-info 9:0:4 +VERSIONINFO=-version-info 8:0:3 else -VERSIONINFO=-version-info 8:0:4 +VERSIONINFO=-version-info 7:0:3 endif # This flag accepts an argument of the form current[:revision[:age]]. So, diff --git a/lib/Makefile.b32 b/lib/Makefile.b32 index 37c264871..b9531fdf4 100644 --- a/lib/Makefile.b32 +++ b/lib/Makefile.b32 @@ -27,7 +27,7 @@ ZLIB_PATH = ..\..\zlib-1.2.8 # Edit the path below to point to the base of your OpenSSL package. !ifndef OPENSSL_PATH -OPENSSL_PATH = ..\..\openssl-1.0.2a +OPENSSL_PATH = ..\..\openssl-0.9.8zc !endif # Set libcurl static lib, dll and import lib @@ -74,7 +74,7 @@ LINKLIB = $(LINKLIB) $(ZLIB_PATH)\zlib.lib # SSL support is enabled setting WITH_SSL=1 !ifdef WITH_SSL -DEFINES = $(DEFINES) -DUSE_OPENSSL +DEFINES = $(DEFINES) -DUSE_SSLEAY INCDIRS = $(INCDIRS);$(OPENSSL_PATH)\inc32;$(OPENSSL_PATH)\inc32\openssl LINKLIB = $(LINKLIB) $(OPENSSL_PATH)\out32\ssleay32.lib $(OPENSSL_PATH)\out32\libeay32.lib !endif diff --git a/lib/Makefile.in b/lib/Makefile.in index 27bfd1015..5947cf0b5 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -21,7 +21,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -37,17 +37,7 @@ ########################################################################### VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -120,6 +110,10 @@ host_triplet = @host@ @USE_CPPFLAG_CURL_STATICLIB_TRUE@am__append_6 = -DCURL_STATICLIB @DOING_CURL_SYMBOL_HIDING_TRUE@am__append_7 = -DCURL_HIDDEN_SYMBOLS @DOING_CURL_SYMBOL_HIDING_TRUE@am__append_8 = $(CFLAG_CURL_SYMBOL_HIDING) +DIST_COMMON = $(srcdir)/Makefile.inc $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(srcdir)/curl_config.h.in \ + $(top_srcdir)/mkinstalldirs $(srcdir)/libcurl.vers.in \ + $(top_srcdir)/depcomp subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/curl-compilers.m4 \ @@ -141,8 +135,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/curl-compilers.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(install_sh) -d +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = curl_config.h $(top_builddir)/include/curl/curlbuild.h CONFIG_CLEAN_FILES = libcurl.vers CONFIG_CLEAN_VPATH_FILES = @@ -219,19 +212,19 @@ am__objects_1 = libcurl_la-file.lo libcurl_la-timeval.lo \ libcurl_la-curl_ntlm_wb.lo libcurl_la-curl_ntlm_core.lo \ libcurl_la-curl_ntlm_msgs.lo libcurl_la-curl_sasl.lo \ libcurl_la-curl_multibyte.lo libcurl_la-hostcheck.lo \ - libcurl_la-conncache.lo libcurl_la-pipeline.lo \ - libcurl_la-dotdot.lo libcurl_la-x509asn1.lo \ - libcurl_la-http2.lo libcurl_la-curl_sasl_sspi.lo \ - libcurl_la-smb.lo libcurl_la-curl_sasl_gssapi.lo \ - libcurl_la-curl_endian.lo libcurl_la-curl_des.lo + libcurl_la-bundles.lo libcurl_la-conncache.lo \ + libcurl_la-pipeline.lo libcurl_la-dotdot.lo \ + libcurl_la-x509asn1.lo libcurl_la-http2.lo \ + libcurl_la-curl_sasl_sspi.lo libcurl_la-smb.lo \ + libcurl_la-curl_sasl_gssapi.lo libcurl_la-curl_endian.lo am__dirstamp = $(am__leading_dot)dirstamp am__objects_2 = 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-darwinssl.lo \ - vtls/libcurl_la-gskit.lo + vtls/libcurl_la-curl_schannel.lo \ + vtls/libcurl_la-curl_darwinssl.lo vtls/libcurl_la-gskit.lo am__objects_3 = $(am__objects_1) $(am__objects_2) am__objects_4 = am__objects_5 = $(am__objects_4) $(am__objects_4) @@ -289,19 +282,19 @@ am__objects_6 = libcurlu_la-file.lo libcurlu_la-timeval.lo \ libcurlu_la-curl_ntlm.lo libcurlu_la-curl_ntlm_wb.lo \ libcurlu_la-curl_ntlm_core.lo libcurlu_la-curl_ntlm_msgs.lo \ libcurlu_la-curl_sasl.lo libcurlu_la-curl_multibyte.lo \ - libcurlu_la-hostcheck.lo libcurlu_la-conncache.lo \ - libcurlu_la-pipeline.lo libcurlu_la-dotdot.lo \ - libcurlu_la-x509asn1.lo libcurlu_la-http2.lo \ - libcurlu_la-curl_sasl_sspi.lo libcurlu_la-smb.lo \ - libcurlu_la-curl_sasl_gssapi.lo libcurlu_la-curl_endian.lo \ - libcurlu_la-curl_des.lo + libcurlu_la-hostcheck.lo libcurlu_la-bundles.lo \ + libcurlu_la-conncache.lo libcurlu_la-pipeline.lo \ + libcurlu_la-dotdot.lo libcurlu_la-x509asn1.lo \ + libcurlu_la-http2.lo libcurlu_la-curl_sasl_sspi.lo \ + libcurlu_la-smb.lo libcurlu_la-curl_sasl_gssapi.lo \ + libcurlu_la-curl_endian.lo am__objects_7 = 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-darwinssl.lo \ - vtls/libcurlu_la-gskit.lo + vtls/libcurlu_la-curl_schannel.lo \ + vtls/libcurlu_la-curl_darwinssl.lo vtls/libcurlu_la-gskit.lo am__objects_8 = $(am__objects_6) $(am__objects_7) am_libcurlu_la_OBJECTS = $(am__objects_8) $(am__objects_5) libcurlu_la_OBJECTS = $(am_libcurlu_la_OBJECTS) @@ -370,9 +363,6 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \ - $(srcdir)/curl_config.h.in $(srcdir)/libcurl.vers.in \ - $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -433,7 +423,7 @@ GREP = @GREP@ HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ HAVE_LIBZ = @HAVE_LIBZ@ -HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_SSLEAY_SRP = @HAVE_SSLEAY_SRP@ IDN_ENABLED = @IDN_ENABLED@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -488,7 +478,6 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSL_ENABLED = @SSL_ENABLED@ -SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SUPPORT_FEATURES = @SUPPORT_FEATURES@ SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ @@ -505,6 +494,7 @@ USE_NSS = @USE_NSS@ USE_OPENLDAP = @USE_OPENLDAP@ USE_POLARSSL = @USE_POLARSSL@ USE_SCHANNEL = @USE_SCHANNEL@ +USE_SSLEAY = @USE_SSLEAY@ USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ VERSION = @VERSION@ @@ -572,7 +562,7 @@ top_srcdir = @top_srcdir@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2013, 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 @@ -587,15 +577,19 @@ top_srcdir = @top_srcdir@ # ########################################################################### AUTOMAKE_OPTIONS = foreign nostdinc +DOCS = README.encoding README.memoryleak README.ares README.curlx \ + README.hostip README.multi_socket README.httpauth README.pipelining \ + README.curl_off_t README.pingpong + CMAKE_DIST = CMakeLists.txt curl_config.h.cmake EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 config-win32.h \ config-win32ce.h config-riscos.h config-mac.h curl_config.h.in \ makefile.dj config-dos.h libcurl.plist libcurl.rc config-amigaos.h \ makefile.amiga Makefile.netware nwlib.c nwos.c config-win32ce.h \ config-os400.h setup-os400.h config-symbian.h Makefile.Watcom \ - config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ + config-tpf.h $(DOCS) mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl \ - objnames-test08.sh objnames-test10.sh objnames.inc checksrc.whitelist + objnames-test08.sh objnames-test10.sh objnames.inc lib_LTLIBRARIES = libcurl.la @BUILD_UNITTESTS_FALSE@noinst_LTLIBRARIES = @@ -629,7 +623,7 @@ lib_LTLIBRARIES = libcurl.la AM_CPPFLAGS = -I$(top_builddir)/include/curl -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(top_builddir)/lib \ -I$(top_srcdir)/lib $(am__append_1) -DBUILDING_LIBCURL -@SONAME_BUMP_FALSE@VERSIONINFO = -version-info 8:0:4 +@SONAME_BUMP_FALSE@VERSIONINFO = -version-info 7:0:3 # # Bumping of SONAME conditionally may seem like a weird thing to do, and yeah @@ -640,7 +634,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl -I$(top_builddir)/include \ # # This conditional soname bump SHOULD be removed at next "proper" bump. # -@SONAME_BUMP_TRUE@VERSIONINFO = -version-info 9:0:4 +@SONAME_BUMP_TRUE@VERSIONINFO = -version-info 8:0:3 AM_LDFLAGS = AM_CFLAGS = libcurl_la_CPPFLAGS_EXTRA = $(am__append_6) $(am__append_7) @@ -655,11 +649,11 @@ libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) libcurlu_la_CFLAGS = $(AM_CFLAGS) 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/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c + vtls/cyassl.c vtls/curl_schannel.c vtls/curl_darwinssl.c vtls/gskit.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/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h + vtls/cyassl.h vtls/curl_schannel.h vtls/curl_darwinssl.h vtls/gskit.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ @@ -677,9 +671,8 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ http_negotiate_sspi.c http_proxy.c non-ascii.c asyn-ares.c \ asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c \ curl_ntlm_core.c curl_ntlm_msgs.c curl_sasl.c curl_multibyte.c \ - hostcheck.c conncache.c pipeline.c dotdot.c x509asn1.c \ - http2.c curl_sasl_sspi.c smb.c curl_sasl_gssapi.c curl_endian.c \ - curl_des.c + hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \ + http2.c curl_sasl_sspi.c smb.c curl_sasl_gssapi.c curl_endian.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -695,10 +688,9 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \ curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \ curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ - curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h \ + curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h bundles.h \ conncache.h curl_setup_once.h multihandle.h setup-vms.h pipeline.h \ - dotdot.h x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ - curl_printf.h + dotdot.h x509asn1.h http2.h sigpipe.h smb.h curl_endian.h LIB_RCFILES = libcurl.rc CSOURCES = $(LIB_CFILES) $(LIB_VTLS_CFILES) @@ -724,6 +716,7 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Ma echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -732,7 +725,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; -$(srcdir)/Makefile.inc $(am__empty): +$(srcdir)/Makefile.inc: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh @@ -827,9 +820,9 @@ 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) \ +vtls/libcurl_la-curl_schannel.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurl_la-darwinssl.lo: vtls/$(am__dirstamp) \ +vtls/libcurl_la-curl_darwinssl.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurl_la-gskit.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -852,9 +845,9 @@ 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) \ +vtls/libcurlu_la-curl_schannel.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) -vtls/libcurlu_la-darwinssl.lo: vtls/$(am__dirstamp) \ +vtls/libcurlu_la-curl_darwinssl.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) vtls/libcurlu_la-gskit.lo: vtls/$(am__dirstamp) \ vtls/$(DEPDIR)/$(am__dirstamp) @@ -874,12 +867,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-bundles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-conncache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-connect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-content_encoding.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cookie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_des.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_endian.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_fnmatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gethostname.Plo@am__quote@ @@ -978,12 +971,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-bundles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-conncache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-connect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-content_encoding.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cookie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_des.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_endian.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_fnmatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo@am__quote@ @@ -1079,26 +1072,26 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-wildcard.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-x509asn1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-axtls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-curl_darwinssl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-curl_schannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-cyassl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-darwinssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gskit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gtls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-nss.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-openssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-axtls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-curl_darwinssl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-curl_schannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-cyassl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gskit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gtls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-nss.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-openssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls.Plo@am__quote@ .c.o: @@ -1783,6 +1776,13 @@ libcurl_la-hostcheck.lo: hostcheck.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c +libcurl_la-bundles.lo: bundles.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-bundles.lo -MD -MP -MF $(DEPDIR)/libcurl_la-bundles.Tpo -c -o libcurl_la-bundles.lo `test -f 'bundles.c' || echo '$(srcdir)/'`bundles.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-bundles.Tpo $(DEPDIR)/libcurl_la-bundles.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bundles.c' object='libcurl_la-bundles.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-bundles.lo `test -f 'bundles.c' || echo '$(srcdir)/'`bundles.c + libcurl_la-conncache.lo: conncache.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurl_la-conncache.Tpo -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-conncache.Tpo $(DEPDIR)/libcurl_la-conncache.Plo @@ -1846,13 +1846,6 @@ libcurl_la-curl_endian.lo: curl_endian.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c -libcurl_la-curl_des.lo: curl_des.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_des.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_des.Tpo -c -o libcurl_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_des.Tpo $(DEPDIR)/libcurl_la-curl_des.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_des.c' object='libcurl_la-curl_des.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c - vtls/libcurl_la-openssl.lo: vtls/openssl.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-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-openssl.Tpo -c -o vtls/libcurl_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-openssl.Tpo vtls/$(DEPDIR)/libcurl_la-openssl.Plo @@ -1909,19 +1902,19 @@ vtls/libcurl_la-cyassl.lo: vtls/cyassl.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-cyassl.lo `test -f 'vtls/cyassl.c' || echo '$(srcdir)/'`vtls/cyassl.c -vtls/libcurl_la-schannel.lo: vtls/schannel.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-schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-schannel.Tpo -c -o vtls/libcurl_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-schannel.Tpo vtls/$(DEPDIR)/libcurl_la-schannel.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel.c' object='vtls/libcurl_la-schannel.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurl_la-curl_schannel.lo: vtls/curl_schannel.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-curl_schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-curl_schannel.Tpo -c -o vtls/libcurl_la-curl_schannel.lo `test -f 'vtls/curl_schannel.c' || echo '$(srcdir)/'`vtls/curl_schannel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-curl_schannel.Tpo vtls/$(DEPDIR)/libcurl_la-curl_schannel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/curl_schannel.c' object='vtls/libcurl_la-curl_schannel.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-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-curl_schannel.lo `test -f 'vtls/curl_schannel.c' || echo '$(srcdir)/'`vtls/curl_schannel.c -vtls/libcurl_la-darwinssl.lo: vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-darwinssl.Tpo -c -o vtls/libcurl_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-darwinssl.Tpo vtls/$(DEPDIR)/libcurl_la-darwinssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/darwinssl.c' object='vtls/libcurl_la-darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurl_la-curl_darwinssl.lo: vtls/curl_darwinssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-curl_darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-curl_darwinssl.Tpo -c -o vtls/libcurl_la-curl_darwinssl.lo `test -f 'vtls/curl_darwinssl.c' || echo '$(srcdir)/'`vtls/curl_darwinssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-curl_darwinssl.Tpo vtls/$(DEPDIR)/libcurl_la-curl_darwinssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/curl_darwinssl.c' object='vtls/libcurl_la-curl_darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-curl_darwinssl.lo `test -f 'vtls/curl_darwinssl.c' || echo '$(srcdir)/'`vtls/curl_darwinssl.c vtls/libcurl_la-gskit.lo: vtls/gskit.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gskit.Tpo -c -o vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c @@ -2588,6 +2581,13 @@ libcurlu_la-hostcheck.lo: hostcheck.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c +libcurlu_la-bundles.lo: bundles.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-bundles.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-bundles.Tpo -c -o libcurlu_la-bundles.lo `test -f 'bundles.c' || echo '$(srcdir)/'`bundles.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-bundles.Tpo $(DEPDIR)/libcurlu_la-bundles.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bundles.c' object='libcurlu_la-bundles.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-bundles.lo `test -f 'bundles.c' || echo '$(srcdir)/'`bundles.c + libcurlu_la-conncache.lo: conncache.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-conncache.Tpo -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-conncache.Tpo $(DEPDIR)/libcurlu_la-conncache.Plo @@ -2651,13 +2651,6 @@ libcurlu_la-curl_endian.lo: curl_endian.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c -libcurlu_la-curl_des.lo: curl_des.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_des.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_des.Tpo -c -o libcurlu_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_des.Tpo $(DEPDIR)/libcurlu_la-curl_des.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_des.c' object='libcurlu_la-curl_des.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c - vtls/libcurlu_la-openssl.lo: vtls/openssl.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-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo -c -o vtls/libcurlu_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo vtls/$(DEPDIR)/libcurlu_la-openssl.Plo @@ -2714,19 +2707,19 @@ vtls/libcurlu_la-cyassl.lo: vtls/cyassl.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-cyassl.lo `test -f 'vtls/cyassl.c' || echo '$(srcdir)/'`vtls/cyassl.c -vtls/libcurlu_la-schannel.lo: vtls/schannel.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-schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-schannel.Tpo -c -o vtls/libcurlu_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-schannel.Tpo vtls/$(DEPDIR)/libcurlu_la-schannel.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel.c' object='vtls/libcurlu_la-schannel.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurlu_la-curl_schannel.lo: vtls/curl_schannel.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-curl_schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-curl_schannel.Tpo -c -o vtls/libcurlu_la-curl_schannel.lo `test -f 'vtls/curl_schannel.c' || echo '$(srcdir)/'`vtls/curl_schannel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-curl_schannel.Tpo vtls/$(DEPDIR)/libcurlu_la-curl_schannel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/curl_schannel.c' object='vtls/libcurlu_la-curl_schannel.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-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-curl_schannel.lo `test -f 'vtls/curl_schannel.c' || echo '$(srcdir)/'`vtls/curl_schannel.c -vtls/libcurlu_la-darwinssl.lo: vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-darwinssl.Tpo -c -o vtls/libcurlu_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-darwinssl.Tpo vtls/$(DEPDIR)/libcurlu_la-darwinssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/darwinssl.c' object='vtls/libcurlu_la-darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ +vtls/libcurlu_la-curl_darwinssl.lo: vtls/curl_darwinssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-curl_darwinssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-curl_darwinssl.Tpo -c -o vtls/libcurlu_la-curl_darwinssl.lo `test -f 'vtls/curl_darwinssl.c' || echo '$(srcdir)/'`vtls/curl_darwinssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-curl_darwinssl.Tpo vtls/$(DEPDIR)/libcurlu_la-curl_darwinssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/curl_darwinssl.c' object='vtls/libcurlu_la-curl_darwinssl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-darwinssl.lo `test -f 'vtls/darwinssl.c' || echo '$(srcdir)/'`vtls/darwinssl.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-curl_darwinssl.lo `test -f 'vtls/curl_darwinssl.c' || echo '$(srcdir)/'`vtls/curl_darwinssl.c vtls/libcurlu_la-gskit.lo: vtls/gskit.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo -c -o vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c @@ -2952,8 +2945,6 @@ uninstall-am: uninstall-libLTLIBRARIES mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES -.PRECIOUS: Makefile - checksrc: @@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/lib $(CSOURCES) $(HHEADERS) diff --git a/lib/Makefile.inc b/lib/Makefile.inc index d444a6b21..8f9d16d8b 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2014, 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,11 +22,11 @@ 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/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c + vtls/cyassl.c vtls/curl_schannel.c vtls/curl_darwinssl.c vtls/gskit.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/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h + vtls/cyassl.h vtls/curl_schannel.h vtls/curl_darwinssl.h vtls/gskit.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ @@ -44,9 +44,8 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ http_negotiate_sspi.c http_proxy.c non-ascii.c asyn-ares.c \ asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c \ curl_ntlm_core.c curl_ntlm_msgs.c curl_sasl.c curl_multibyte.c \ - hostcheck.c conncache.c pipeline.c dotdot.c x509asn1.c \ - http2.c curl_sasl_sspi.c smb.c curl_sasl_gssapi.c curl_endian.c \ - curl_des.c + hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \ + http2.c curl_sasl_sspi.c smb.c curl_sasl_gssapi.c curl_endian.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -62,10 +61,9 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \ curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \ curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ - curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h \ + curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h bundles.h \ conncache.h curl_setup_once.h multihandle.h setup-vms.h pipeline.h \ - dotdot.h x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ - curl_printf.h + dotdot.h x509asn1.h http2.h sigpipe.h smb.h curl_endian.h LIB_RCFILES = libcurl.rc diff --git a/lib/Makefile.m32 b/lib/Makefile.m32 index 736e600f5..f3673c5a3 100644 --- a/lib/Makefile.m32 +++ b/lib/Makefile.m32 @@ -1,7 +1,7 @@ ########################################################################### # ## Makefile for building libcurl.a with MingW (GCC-3.2 or later) -## and optionally OpenSSL (1.0.2a), libssh2 (1.5), zlib (1.2.8), librtmp (2.4) +## and optionally OpenSSL (0.9.8), libssh2 (1.3), zlib (1.2.5), librtmp (2.3) ## ## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...] ## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn @@ -18,23 +18,23 @@ 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 +OPENSSL_PATH = ../../openssl-0.9.8zc endif # Edit the path below to point to the base of your LibSSH2 package. ifndef LIBSSH2_PATH -LIBSSH2_PATH = ../../libssh2-1.5.0 +LIBSSH2_PATH = ../../libssh2-1.4.3 endif # Edit the path below to point to the base of your librtmp package. ifndef LIBRTMP_PATH -LIBRTMP_PATH = ../../librtmp-2.4 +LIBRTMP_PATH = ../../librtmp-2.3 endif # Edit the path below to point to the base of your libidn package. ifndef LIBIDN_PATH -LIBIDN_PATH = ../../libidn-1.32 +LIBIDN_PATH = ../../libidn-1.18 endif # Edit the path below to point to the base of your MS IDN package. # Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1 -# https://www.microsoft.com/en-us/download/details.aspx?id=734 +# http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ad6158d7-ddba-416a-9109-07607425a815 ifndef WINIDN_PATH WINIDN_PATH = ../../Microsoft IDN Mitigation APIs endif @@ -44,7 +44,7 @@ LDAP_SDK = c:/novell/ndk/cldapsdk/win32 endif # Edit the path below to point to the base of your nghttp2 package. ifndef NGHTTP2_PATH -NGHTTP2_PATH = ../../nghttp2-1.0.0 +NGHTTP2_PATH = ../../nghttp2-0.6.7 endif PROOT = .. @@ -55,10 +55,10 @@ LIBCARES_PATH = $(PROOT)/ares endif CC = $(CROSSPREFIX)gcc -CFLAGS = $(CURL_CFLAG_EXTRAS) -g -O2 -Wall +CFLAGS = -g -O2 -Wall CFLAGS += -fno-strict-aliasing # comment LDFLAGS below to keep debug info -LDFLAGS = $(CURL_LDFLAG_EXTRAS) -s +LDFLAGS = -s AR = $(CROSSPREFIX)ar RANLIB = $(CROSSPREFIX)ranlib RC = $(CROSSPREFIX)windres @@ -75,12 +75,10 @@ endif endif ifeq ($(ARCH),w64) -CFLAGS += -m64 -D_AMD64_ -LDFLAGS += -m64 +CFLAGS += -D_AMD64_ RCFLAGS += -F pe-x86-64 else CFLAGS += -m32 -LDFLAGS += -m32 RCFLAGS += -F pe-i386 endif @@ -216,17 +214,14 @@ ifdef SSL OPENSSL_LIBS = -lcrypto -lssl endif endif - ifndef DYN - OPENSSL_LIBS += -lgdi32 -lcrypt32 - endif INCLUDES += -I"$(OPENSSL_INCLUDE)" - CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \ + CFLAGS += -DUSE_SSLEAY -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \ -DHAVE_ENGINE_LOAD_BUILTIN_ENGINES -DOPENSSL_NO_KRB5 \ -DCURL_WANTS_CA_BUNDLE_ENV DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS) ifdef SRP ifeq "$(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h)" "$(OPENSSL_INCLUDE)/openssl/srp.h" - CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP + CFLAGS += -DHAVE_SSLEAY_SRP -DUSE_TLS_SRP endif endif endif @@ -328,3 +323,5 @@ $(PROOT)/include/curl/curlbuild.h: $(LIBCARES_PATH)/libcares.a: $(MAKE) -C $(LIBCARES_PATH) -f Makefile.m32 + + diff --git a/lib/Makefile.netware b/lib/Makefile.netware index 5a955f889..802959ce9 100644 --- a/lib/Makefile.netware +++ b/lib/Makefile.netware @@ -19,12 +19,12 @@ endif # Edit the path below to point to the base of your OpenSSL package. ifndef OPENSSL_PATH -OPENSSL_PATH = ../../openssl-1.0.2a +OPENSSL_PATH = ../../openssl-0.9.8zc endif # Edit the path below to point to the base of your LibSSH2 package. ifndef LIBSSH2_PATH -LIBSSH2_PATH = ../../libssh2-1.5.0 +LIBSSH2_PATH = ../../libssh2-1.4.3 endif # Edit the path below to point to the base of your axTLS package. @@ -214,11 +214,6 @@ WITH_SSL = else ifeq ($(findstring -ssl,$(CFG)),-ssl) WITH_SSL = 1 -ifeq ($(findstring -srp,$(CFG)),-srp) -ifeq "$(wildcard $(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L)/openssl/srp.h)" "$(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L)/openssl/srp.h" -WITH_SRP = 1 -endif -endif endif endif ifeq ($(findstring -zlib,$(CFG)),-zlib) @@ -643,10 +638,6 @@ ifdef WITH_SSL @echo $(DL)#define HAVE_LIBSSL 1$(DL) >> $@ @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 @@ -699,11 +690,6 @@ ifdef WITH_SSL else @echo SSL support: no endif -ifdef WITH_SRP - @echo SRP support: enabled -else - @echo SRP support: no -endif ifdef WITH_SSH2 @echo SSH2 support: enabled (libssh2) else diff --git a/lib/Makefile.vc10 b/lib/Makefile.vc10 index 987e01edb..461e4f74c 100644 --- a/lib/Makefile.vc10 +++ b/lib/Makefile.vc10 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2014, 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
@@ -65,11 +65,11 @@ !INCLUDE ..\winbuild\Makefile.msvc.names
!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
+OPENSSL_PATH = ../../openssl-0.9.8zc
!ENDIF
!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
+LIBSSH2_PATH = ../../libssh2-1.4.3
!ENDIF
!IFNDEF ZLIB_PATH
@@ -90,7 +90,7 @@ MACHINE = X86 # If, for some reason the Windows SDK is installed but not installed
# in the default location, you can specify WINDOWS_SDK_PATH.
# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
# WINDOWS_SSPI = 1
@@ -105,7 +105,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK" CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
+CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSWINSSL = /DUSE_SCHANNEL
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
@@ -427,7 +427,7 @@ CFGSET = TRUE TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
+CC = $(CCDEBUG) $(RTLIBD)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
@@ -528,12 +528,13 @@ X_OBJS= \ $(DIROBJ)\asyn-thread.obj \
$(DIROBJ)\axtls.obj \
$(DIROBJ)\base64.obj \
+ $(DIROBJ)\bundles.obj \
$(DIROBJ)\conncache.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
+ $(DIROBJ)\curl_darwinssl.obj \
$(DIROBJ)\curl_endian.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
@@ -548,10 +549,10 @@ X_OBJS= \ $(DIROBJ)\curl_sasl.obj \
$(DIROBJ)\curl_sasl_gssapi.obj \
$(DIROBJ)\curl_sasl_sspi.obj \
+ $(DIROBJ)\curl_schannel.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\dotdot.obj \
$(DIROBJ)\easy.obj \
@@ -606,7 +607,6 @@ X_OBJS= \ $(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
diff --git a/lib/Makefile.vc11 b/lib/Makefile.vc11 deleted file mode 100644 index d1bf34a33..000000000 --- a/lib/Makefile.vc11 +++ /dev/null @@ -1,677 +0,0 @@ -#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 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 http://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.
-#
-#***************************************************************************
-
-# All files in the Makefile.vc* series are generated automatically from the
-# one made for MSVC version 6. Alas, if you want to do changes to any of the
-# files and send back to the project, edit the version six, make your diff and
-# mail curl-library.
-
-###########################################################################
-#
-# Makefile for building libcurl with MSVC11
-#
-# Usage: see usage message below
-# Should be invoked from \lib directory
-# Edit the paths and desired library name
-# SSL path is only required if you intend compiling
-# with SSL.
-#
-# This make file leaves the result either a .lib or .dll file
-# in the \lib directory. It should be called from the \lib
-# directory.
-#
-# An option would have been to allow the source directory to
-# be specified, but I saw no requirement.
-#
-# Another option would have been to leave the .lib and .dll
-# files in the "cfg" directory, but then the make file
-# in \src would need to be changed.
-#
-##############################################################
-
-# ----------------------------------------------
-# Verify that current subdir is libcurl's 'lib'
-# ----------------------------------------------
-
-!IF ! EXIST(.\curl_addrinfo.c)
-! MESSAGE Can not process this makefile from outside of libcurl's 'lib' subdirectory.
-! MESSAGE Change to libcurl's 'lib' subdirectory, and try again.
-! ERROR See previous message.
-!ENDIF
-
-# ------------------------------------------------
-# Makefile.msvc.names provides libcurl file names
-# ------------------------------------------------
-
-!INCLUDE ..\winbuild\Makefile.msvc.names
-
-!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-!ENDIF
-
-!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-!ENDIF
-
-!IFNDEF ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-!ENDIF
-
-!IFNDEF MACHINE
-MACHINE = X86
-!ENDIF
-
-# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
-# without an openssl installation and offers the ability to authenticate
-# using the "current logged in user". Since at least with MSVC11 the sspi.h
-# header is broken it is either required to install the Windows SDK,
-# or to fix sspi.h with adding this define at the beginning of sspi.h:
-# #define FreeCredentialHandle FreeCredentialsHandle
-#
-# If, for some reason the Windows SDK is installed but not installed
-# in the default location, you can specify WINDOWS_SDK_PATH.
-# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
-
-# WINDOWS_SSPI = 1
-
-!IFDEF WINDOWS_SSPI
-!IFNDEF WINDOWS_SDK_PATH
-WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
-!ENDIF
-!ENDIF
-
-#############################################################
-## Nothing more to do below this line!
-
-CCNODBG = cl.exe /O2 /DNDEBUG
-CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
-CFLAGSWINSSL = /DUSE_SCHANNEL
-CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
-CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
-CFLAGS = /I. /I../include /nologo /W3 /EHsc /DWIN32 /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
-CFLAGSLIB = /DCURL_STATICLIB
-LNKDLL = link.exe /DLL
-LNKLIB = link.exe /lib
-LFLAGS = /nologo /machine:$(MACHINE)
-SSLLIBS = libeay32.lib ssleay32.lib
-ZLIBLIBSDLL = zdll.lib
-ZLIBLIBS = zlib.lib
-WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
-CFLAGS = $(CFLAGS)
-
-CFGSET = FALSE
-
-!IFDEF WINDOWS_SSPI
-CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
-!ENDIF
-
-!IFDEF USE_IPV6
-CFLAGS = $(CFLAGS) /DUSE_IPV6
-!ENDIF
-
-!IFDEF USE_IDN
-CFLAGS = $(CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
-!ENDIF
-
-##############################################################
-# Runtime library configuration
-
-RTLIB = /MD
-RTLIBD = /MDd
-
-!IF "$(RTLIBCFG)" == "static"
-RTLIB = /MT
-RTLIBD = /MTd
-!ENDIF
-
-
-######################
-# release
-
-!IF "$(CFG)" == "release"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl
-
-!IF "$(CFG)" == "release-ssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl
-
-!IF "$(CFG)" == "release-winssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib
-
-!IF "$(CFG)" == "release-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-zlib
-
-!IF "$(CFG)" == "release-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl-zlib
-
-!IF "$(CFG)" == "release-winssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "release-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll
-
-!IF "$(CFG)" == "release-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib-dll
-
-!IF "$(CFG)" == "release-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-dll
-
-!IF "$(CFG)" == "release-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug
-
-!IF "$(CFG)" == "debug"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl
-
-!IF "$(CFG)" == "debug-ssl"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib
-
-!IF "$(CFG)" == "debug-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-zlib
-
-!IF "$(CFG)" == "debug-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll
-
-!IF "$(CFG)" == "debug-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)\out32dll
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib-dll
-
-!IF "$(CFG)" == "debug-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-dll
-
-!IF "$(CFG)" == "debug-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-#######################
-# Usage
-#
-!IF "$(CFGSET)" == "FALSE" && "$(CFG)" != ""
-!MESSAGE Usage: nmake /f makefile.vc11 CFG=<config> <target>
-!MESSAGE where <config> is one of:
-!MESSAGE release - release static library
-!MESSAGE release-ssl - release static library with ssl
-!MESSAGE release-zlib - release static library with zlib
-!MESSAGE release-ssl-zlib - release static library with ssl and zlib
-!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
-!MESSAGE release-ssl-dll - release static library with dynamic ssl
-!MESSAGE release-zlib-dll - release static library with dynamic zlib
-!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
-!MESSAGE release-dll - release dynamic library
-!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
-!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
-!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE debug - debug static library
-!MESSAGE debug-ssl - debug static library with ssl
-!MESSAGE debug-zlib - debug static library with zlib
-!MESSAGE debug-ssl-zlib - debug static library with ssl and zlib
-!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
-!MESSAGE debug-ssl-dll - debug static library with dynamic ssl
-!MESSAGE debug-zlib-dll - debug static library with dynamic zlib
-!MESSAGE debug-ssl-dll-zlib-dll - debug static library with dynamic ssl and dynamic zlib
-!MESSAGE debug-dll - debug dynamic library
-!MESSAGE debug-dll-ssl-dll - debug dynamic library with dynamic ssl
-!MESSAGE debug-dll-zlib-dll - debug dynamic library with dynamic zlib1
-!MESSAGE debug-dll-ssl-dll-zlib-dll - debug dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE <target> can be left blank in which case all is assumed
-!ERROR please choose a valid configuration "$(CFG)"
-!ENDIF
-
-#######################
-# Only the clean target can be used if a config was not provided.
-#
-!IF "$(CFGSET)" == "FALSE"
-clean:
- @-erase /s *.dll 2> NUL
- @-erase /s *.exp 2> NUL
- @-erase /s *.idb 2> NUL
- @-erase /s *.lib 2> NUL
- @-erase /s *.obj 2> NUL
- @-erase /s *.pch 2> NUL
- @-erase /s *.pdb 2> NUL
- @-erase /s *.res 2> NUL
-!ELSE
-# A config was provided, so the library can be built.
-#
-X_OBJS= \
- $(DIROBJ)\amigaos.obj \
- $(DIROBJ)\asyn-ares.obj \
- $(DIROBJ)\asyn-thread.obj \
- $(DIROBJ)\axtls.obj \
- $(DIROBJ)\base64.obj \
- $(DIROBJ)\conncache.obj \
- $(DIROBJ)\connect.obj \
- $(DIROBJ)\content_encoding.obj \
- $(DIROBJ)\cookie.obj \
- $(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
- $(DIROBJ)\curl_endian.obj \
- $(DIROBJ)\curl_fnmatch.obj \
- $(DIROBJ)\curl_gethostname.obj \
- $(DIROBJ)\curl_gssapi.obj \
- $(DIROBJ)\curl_memrchr.obj \
- $(DIROBJ)\curl_multibyte.obj \
- $(DIROBJ)\curl_ntlm.obj \
- $(DIROBJ)\curl_ntlm_core.obj \
- $(DIROBJ)\curl_ntlm_msgs.obj \
- $(DIROBJ)\curl_ntlm_wb.obj \
- $(DIROBJ)\curl_rtmp.obj \
- $(DIROBJ)\curl_sasl.obj \
- $(DIROBJ)\curl_sasl_gssapi.obj \
- $(DIROBJ)\curl_sasl_sspi.obj \
- $(DIROBJ)\curl_sspi.obj \
- $(DIROBJ)\curl_threads.obj \
- $(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
- $(DIROBJ)\dict.obj \
- $(DIROBJ)\dotdot.obj \
- $(DIROBJ)\easy.obj \
- $(DIROBJ)\escape.obj \
- $(DIROBJ)\file.obj \
- $(DIROBJ)\fileinfo.obj \
- $(DIROBJ)\formdata.obj \
- $(DIROBJ)\ftp.obj \
- $(DIROBJ)\ftplistparser.obj \
- $(DIROBJ)\getenv.obj \
- $(DIROBJ)\getinfo.obj \
- $(DIROBJ)\gopher.obj \
- $(DIROBJ)\gtls.obj \
- $(DIROBJ)\hash.obj \
- $(DIROBJ)\hmac.obj \
- $(DIROBJ)\hostasyn.obj \
- $(DIROBJ)\hostcheck.obj \
- $(DIROBJ)\hostip.obj \
- $(DIROBJ)\hostip4.obj \
- $(DIROBJ)\hostip6.obj \
- $(DIROBJ)\hostsyn.obj \
- $(DIROBJ)\http.obj \
- $(DIROBJ)\http_chunks.obj \
- $(DIROBJ)\http_digest.obj \
- $(DIROBJ)\http_negotiate.obj \
- $(DIROBJ)\http_negotiate_sspi.obj \
- $(DIROBJ)\http_proxy.obj \
- $(DIROBJ)\idn_win32.obj \
- $(DIROBJ)\if2ip.obj \
- $(DIROBJ)\imap.obj \
- $(DIROBJ)\inet_ntop.obj \
- $(DIROBJ)\inet_pton.obj \
- $(DIROBJ)\krb5.obj \
- $(DIROBJ)\ldap.obj \
- $(DIROBJ)\llist.obj \
- $(DIROBJ)\md4.obj \
- $(DIROBJ)\md5.obj \
- $(DIROBJ)\memdebug.obj \
- $(DIROBJ)\mprintf.obj \
- $(DIROBJ)\multi.obj \
- $(DIROBJ)\netrc.obj \
- $(DIROBJ)\non-ascii.obj \
- $(DIROBJ)\nonblock.obj \
- $(DIROBJ)\nss.obj \
- $(DIROBJ)\openldap.obj \
- $(DIROBJ)\parsedate.obj \
- $(DIROBJ)\pingpong.obj \
- $(DIROBJ)\pipeline.obj \
- $(DIROBJ)\polarssl.obj \
- $(DIROBJ)\polarssl_threadlock.obj \
- $(DIROBJ)\pop3.obj \
- $(DIROBJ)\progress.obj \
- $(DIROBJ)\rawstr.obj \
- $(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
- $(DIROBJ)\security.obj \
- $(DIROBJ)\select.obj \
- $(DIROBJ)\sendf.obj \
- $(DIROBJ)\share.obj \
- $(DIROBJ)\slist.obj \
- $(DIROBJ)\smb.obj \
- $(DIROBJ)\smtp.obj \
- $(DIROBJ)\socks.obj \
- $(DIROBJ)\socks_gssapi.obj \
- $(DIROBJ)\socks_sspi.obj \
- $(DIROBJ)\speedcheck.obj \
- $(DIROBJ)\splay.obj \
- $(DIROBJ)\ssh.obj \
- $(DIROBJ)\vtls.obj \
- $(DIROBJ)\openssl.obj \
- $(DIROBJ)\strdup.obj \
- $(DIROBJ)\strequal.obj \
- $(DIROBJ)\strerror.obj \
- $(DIROBJ)\strtok.obj \
- $(DIROBJ)\strtoofft.obj \
- $(DIROBJ)\telnet.obj \
- $(DIROBJ)\tftp.obj \
- $(DIROBJ)\timeval.obj \
- $(DIROBJ)\transfer.obj \
- $(DIROBJ)\url.obj \
- $(DIROBJ)\version.obj \
- $(DIROBJ)\warnless.obj \
- $(DIROBJ)\wildcard.obj \
- $(RESOURCE)
-
-all : $(TARGET)
-
-$(TARGET): $(X_OBJS)
- $(LNK) $(LFLAGS) $(X_OBJS)
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) . /y
- -xcopy $(DIROBJ)\*.exp . /y
- -xcopy $(DIROBJ)\*.pdb . /y
-
-$(X_OBJS): $(DIROBJ)
-
-$(DIROBJ):
- @if not exist "$(DIROBJ)" mkdir $(DIROBJ)
-
-.SUFFIXES: .c .obj .res
-
-{.\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-{.\vtls\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-debug-dll\libcurl.res \
-debug-dll-ssl-dll\libcurl.res \
-debug-dll-zlib-dll\libcurl.res \
-debug-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=1 /Fo $@ libcurl.rc
-
-release-dll\libcurl.res \
-release-dll-ssl-dll\libcurl.res \
-release-dll-zlib-dll\libcurl.res \
-release-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=0 /Fo $@ libcurl.rc
-!ENDIF # End of case where a config was provided.
diff --git a/lib/Makefile.vc12 b/lib/Makefile.vc12 deleted file mode 100644 index 7590de455..000000000 --- a/lib/Makefile.vc12 +++ /dev/null @@ -1,677 +0,0 @@ -#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 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 http://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.
-#
-#***************************************************************************
-
-# All files in the Makefile.vc* series are generated automatically from the
-# one made for MSVC version 6. Alas, if you want to do changes to any of the
-# files and send back to the project, edit the version six, make your diff and
-# mail curl-library.
-
-###########################################################################
-#
-# Makefile for building libcurl with MSVC12
-#
-# Usage: see usage message below
-# Should be invoked from \lib directory
-# Edit the paths and desired library name
-# SSL path is only required if you intend compiling
-# with SSL.
-#
-# This make file leaves the result either a .lib or .dll file
-# in the \lib directory. It should be called from the \lib
-# directory.
-#
-# An option would have been to allow the source directory to
-# be specified, but I saw no requirement.
-#
-# Another option would have been to leave the .lib and .dll
-# files in the "cfg" directory, but then the make file
-# in \src would need to be changed.
-#
-##############################################################
-
-# ----------------------------------------------
-# Verify that current subdir is libcurl's 'lib'
-# ----------------------------------------------
-
-!IF ! EXIST(.\curl_addrinfo.c)
-! MESSAGE Can not process this makefile from outside of libcurl's 'lib' subdirectory.
-! MESSAGE Change to libcurl's 'lib' subdirectory, and try again.
-! ERROR See previous message.
-!ENDIF
-
-# ------------------------------------------------
-# Makefile.msvc.names provides libcurl file names
-# ------------------------------------------------
-
-!INCLUDE ..\winbuild\Makefile.msvc.names
-
-!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-!ENDIF
-
-!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-!ENDIF
-
-!IFNDEF ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-!ENDIF
-
-!IFNDEF MACHINE
-MACHINE = X86
-!ENDIF
-
-# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
-# without an openssl installation and offers the ability to authenticate
-# using the "current logged in user". Since at least with MSVC12 the sspi.h
-# header is broken it is either required to install the Windows SDK,
-# or to fix sspi.h with adding this define at the beginning of sspi.h:
-# #define FreeCredentialHandle FreeCredentialsHandle
-#
-# If, for some reason the Windows SDK is installed but not installed
-# in the default location, you can specify WINDOWS_SDK_PATH.
-# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
-
-# WINDOWS_SSPI = 1
-
-!IFDEF WINDOWS_SSPI
-!IFNDEF WINDOWS_SDK_PATH
-WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
-!ENDIF
-!ENDIF
-
-#############################################################
-## Nothing more to do below this line!
-
-CCNODBG = cl.exe /O2 /DNDEBUG
-CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
-CFLAGSWINSSL = /DUSE_SCHANNEL
-CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
-CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
-CFLAGS = /I. /I../include /nologo /W3 /EHsc /DWIN32 /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
-CFLAGSLIB = /DCURL_STATICLIB
-LNKDLL = link.exe /DLL
-LNKLIB = link.exe /lib
-LFLAGS = /nologo /machine:$(MACHINE)
-SSLLIBS = libeay32.lib ssleay32.lib
-ZLIBLIBSDLL = zdll.lib
-ZLIBLIBS = zlib.lib
-WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
-CFLAGS = $(CFLAGS)
-
-CFGSET = FALSE
-
-!IFDEF WINDOWS_SSPI
-CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
-!ENDIF
-
-!IFDEF USE_IPV6
-CFLAGS = $(CFLAGS) /DUSE_IPV6
-!ENDIF
-
-!IFDEF USE_IDN
-CFLAGS = $(CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
-!ENDIF
-
-##############################################################
-# Runtime library configuration
-
-RTLIB = /MD
-RTLIBD = /MDd
-
-!IF "$(RTLIBCFG)" == "static"
-RTLIB = /MT
-RTLIBD = /MTd
-!ENDIF
-
-
-######################
-# release
-
-!IF "$(CFG)" == "release"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl
-
-!IF "$(CFG)" == "release-ssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl
-
-!IF "$(CFG)" == "release-winssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib
-
-!IF "$(CFG)" == "release-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-zlib
-
-!IF "$(CFG)" == "release-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl-zlib
-
-!IF "$(CFG)" == "release-winssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "release-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll
-
-!IF "$(CFG)" == "release-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib-dll
-
-!IF "$(CFG)" == "release-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-dll
-
-!IF "$(CFG)" == "release-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug
-
-!IF "$(CFG)" == "debug"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl
-
-!IF "$(CFG)" == "debug-ssl"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib
-
-!IF "$(CFG)" == "debug-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-zlib
-
-!IF "$(CFG)" == "debug-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll
-
-!IF "$(CFG)" == "debug-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)\out32dll
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib-dll
-
-!IF "$(CFG)" == "debug-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-dll
-
-!IF "$(CFG)" == "debug-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-#######################
-# Usage
-#
-!IF "$(CFGSET)" == "FALSE" && "$(CFG)" != ""
-!MESSAGE Usage: nmake /f makefile.vc12 CFG=<config> <target>
-!MESSAGE where <config> is one of:
-!MESSAGE release - release static library
-!MESSAGE release-ssl - release static library with ssl
-!MESSAGE release-zlib - release static library with zlib
-!MESSAGE release-ssl-zlib - release static library with ssl and zlib
-!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
-!MESSAGE release-ssl-dll - release static library with dynamic ssl
-!MESSAGE release-zlib-dll - release static library with dynamic zlib
-!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
-!MESSAGE release-dll - release dynamic library
-!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
-!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
-!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE debug - debug static library
-!MESSAGE debug-ssl - debug static library with ssl
-!MESSAGE debug-zlib - debug static library with zlib
-!MESSAGE debug-ssl-zlib - debug static library with ssl and zlib
-!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
-!MESSAGE debug-ssl-dll - debug static library with dynamic ssl
-!MESSAGE debug-zlib-dll - debug static library with dynamic zlib
-!MESSAGE debug-ssl-dll-zlib-dll - debug static library with dynamic ssl and dynamic zlib
-!MESSAGE debug-dll - debug dynamic library
-!MESSAGE debug-dll-ssl-dll - debug dynamic library with dynamic ssl
-!MESSAGE debug-dll-zlib-dll - debug dynamic library with dynamic zlib1
-!MESSAGE debug-dll-ssl-dll-zlib-dll - debug dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE <target> can be left blank in which case all is assumed
-!ERROR please choose a valid configuration "$(CFG)"
-!ENDIF
-
-#######################
-# Only the clean target can be used if a config was not provided.
-#
-!IF "$(CFGSET)" == "FALSE"
-clean:
- @-erase /s *.dll 2> NUL
- @-erase /s *.exp 2> NUL
- @-erase /s *.idb 2> NUL
- @-erase /s *.lib 2> NUL
- @-erase /s *.obj 2> NUL
- @-erase /s *.pch 2> NUL
- @-erase /s *.pdb 2> NUL
- @-erase /s *.res 2> NUL
-!ELSE
-# A config was provided, so the library can be built.
-#
-X_OBJS= \
- $(DIROBJ)\amigaos.obj \
- $(DIROBJ)\asyn-ares.obj \
- $(DIROBJ)\asyn-thread.obj \
- $(DIROBJ)\axtls.obj \
- $(DIROBJ)\base64.obj \
- $(DIROBJ)\conncache.obj \
- $(DIROBJ)\connect.obj \
- $(DIROBJ)\content_encoding.obj \
- $(DIROBJ)\cookie.obj \
- $(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
- $(DIROBJ)\curl_endian.obj \
- $(DIROBJ)\curl_fnmatch.obj \
- $(DIROBJ)\curl_gethostname.obj \
- $(DIROBJ)\curl_gssapi.obj \
- $(DIROBJ)\curl_memrchr.obj \
- $(DIROBJ)\curl_multibyte.obj \
- $(DIROBJ)\curl_ntlm.obj \
- $(DIROBJ)\curl_ntlm_core.obj \
- $(DIROBJ)\curl_ntlm_msgs.obj \
- $(DIROBJ)\curl_ntlm_wb.obj \
- $(DIROBJ)\curl_rtmp.obj \
- $(DIROBJ)\curl_sasl.obj \
- $(DIROBJ)\curl_sasl_gssapi.obj \
- $(DIROBJ)\curl_sasl_sspi.obj \
- $(DIROBJ)\curl_sspi.obj \
- $(DIROBJ)\curl_threads.obj \
- $(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
- $(DIROBJ)\dict.obj \
- $(DIROBJ)\dotdot.obj \
- $(DIROBJ)\easy.obj \
- $(DIROBJ)\escape.obj \
- $(DIROBJ)\file.obj \
- $(DIROBJ)\fileinfo.obj \
- $(DIROBJ)\formdata.obj \
- $(DIROBJ)\ftp.obj \
- $(DIROBJ)\ftplistparser.obj \
- $(DIROBJ)\getenv.obj \
- $(DIROBJ)\getinfo.obj \
- $(DIROBJ)\gopher.obj \
- $(DIROBJ)\gtls.obj \
- $(DIROBJ)\hash.obj \
- $(DIROBJ)\hmac.obj \
- $(DIROBJ)\hostasyn.obj \
- $(DIROBJ)\hostcheck.obj \
- $(DIROBJ)\hostip.obj \
- $(DIROBJ)\hostip4.obj \
- $(DIROBJ)\hostip6.obj \
- $(DIROBJ)\hostsyn.obj \
- $(DIROBJ)\http.obj \
- $(DIROBJ)\http_chunks.obj \
- $(DIROBJ)\http_digest.obj \
- $(DIROBJ)\http_negotiate.obj \
- $(DIROBJ)\http_negotiate_sspi.obj \
- $(DIROBJ)\http_proxy.obj \
- $(DIROBJ)\idn_win32.obj \
- $(DIROBJ)\if2ip.obj \
- $(DIROBJ)\imap.obj \
- $(DIROBJ)\inet_ntop.obj \
- $(DIROBJ)\inet_pton.obj \
- $(DIROBJ)\krb5.obj \
- $(DIROBJ)\ldap.obj \
- $(DIROBJ)\llist.obj \
- $(DIROBJ)\md4.obj \
- $(DIROBJ)\md5.obj \
- $(DIROBJ)\memdebug.obj \
- $(DIROBJ)\mprintf.obj \
- $(DIROBJ)\multi.obj \
- $(DIROBJ)\netrc.obj \
- $(DIROBJ)\non-ascii.obj \
- $(DIROBJ)\nonblock.obj \
- $(DIROBJ)\nss.obj \
- $(DIROBJ)\openldap.obj \
- $(DIROBJ)\parsedate.obj \
- $(DIROBJ)\pingpong.obj \
- $(DIROBJ)\pipeline.obj \
- $(DIROBJ)\polarssl.obj \
- $(DIROBJ)\polarssl_threadlock.obj \
- $(DIROBJ)\pop3.obj \
- $(DIROBJ)\progress.obj \
- $(DIROBJ)\rawstr.obj \
- $(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
- $(DIROBJ)\security.obj \
- $(DIROBJ)\select.obj \
- $(DIROBJ)\sendf.obj \
- $(DIROBJ)\share.obj \
- $(DIROBJ)\slist.obj \
- $(DIROBJ)\smb.obj \
- $(DIROBJ)\smtp.obj \
- $(DIROBJ)\socks.obj \
- $(DIROBJ)\socks_gssapi.obj \
- $(DIROBJ)\socks_sspi.obj \
- $(DIROBJ)\speedcheck.obj \
- $(DIROBJ)\splay.obj \
- $(DIROBJ)\ssh.obj \
- $(DIROBJ)\vtls.obj \
- $(DIROBJ)\openssl.obj \
- $(DIROBJ)\strdup.obj \
- $(DIROBJ)\strequal.obj \
- $(DIROBJ)\strerror.obj \
- $(DIROBJ)\strtok.obj \
- $(DIROBJ)\strtoofft.obj \
- $(DIROBJ)\telnet.obj \
- $(DIROBJ)\tftp.obj \
- $(DIROBJ)\timeval.obj \
- $(DIROBJ)\transfer.obj \
- $(DIROBJ)\url.obj \
- $(DIROBJ)\version.obj \
- $(DIROBJ)\warnless.obj \
- $(DIROBJ)\wildcard.obj \
- $(RESOURCE)
-
-all : $(TARGET)
-
-$(TARGET): $(X_OBJS)
- $(LNK) $(LFLAGS) $(X_OBJS)
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) . /y
- -xcopy $(DIROBJ)\*.exp . /y
- -xcopy $(DIROBJ)\*.pdb . /y
-
-$(X_OBJS): $(DIROBJ)
-
-$(DIROBJ):
- @if not exist "$(DIROBJ)" mkdir $(DIROBJ)
-
-.SUFFIXES: .c .obj .res
-
-{.\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-{.\vtls\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-debug-dll\libcurl.res \
-debug-dll-ssl-dll\libcurl.res \
-debug-dll-zlib-dll\libcurl.res \
-debug-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=1 /Fo $@ libcurl.rc
-
-release-dll\libcurl.res \
-release-dll-ssl-dll\libcurl.res \
-release-dll-zlib-dll\libcurl.res \
-release-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=0 /Fo $@ libcurl.rc
-!ENDIF # End of case where a config was provided.
diff --git a/lib/Makefile.vc14 b/lib/Makefile.vc14 deleted file mode 100644 index 226d27a77..000000000 --- a/lib/Makefile.vc14 +++ /dev/null @@ -1,677 +0,0 @@ -#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 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 http://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.
-#
-#***************************************************************************
-
-# All files in the Makefile.vc* series are generated automatically from the
-# one made for MSVC version 6. Alas, if you want to do changes to any of the
-# files and send back to the project, edit the version six, make your diff and
-# mail curl-library.
-
-###########################################################################
-#
-# Makefile for building libcurl with MSVC14
-#
-# Usage: see usage message below
-# Should be invoked from \lib directory
-# Edit the paths and desired library name
-# SSL path is only required if you intend compiling
-# with SSL.
-#
-# This make file leaves the result either a .lib or .dll file
-# in the \lib directory. It should be called from the \lib
-# directory.
-#
-# An option would have been to allow the source directory to
-# be specified, but I saw no requirement.
-#
-# Another option would have been to leave the .lib and .dll
-# files in the "cfg" directory, but then the make file
-# in \src would need to be changed.
-#
-##############################################################
-
-# ----------------------------------------------
-# Verify that current subdir is libcurl's 'lib'
-# ----------------------------------------------
-
-!IF ! EXIST(.\curl_addrinfo.c)
-! MESSAGE Can not process this makefile from outside of libcurl's 'lib' subdirectory.
-! MESSAGE Change to libcurl's 'lib' subdirectory, and try again.
-! ERROR See previous message.
-!ENDIF
-
-# ------------------------------------------------
-# Makefile.msvc.names provides libcurl file names
-# ------------------------------------------------
-
-!INCLUDE ..\winbuild\Makefile.msvc.names
-
-!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-!ENDIF
-
-!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-!ENDIF
-
-!IFNDEF ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-!ENDIF
-
-!IFNDEF MACHINE
-MACHINE = X86
-!ENDIF
-
-# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
-# without an openssl installation and offers the ability to authenticate
-# using the "current logged in user". Since at least with MSVC14 the sspi.h
-# header is broken it is either required to install the Windows SDK,
-# or to fix sspi.h with adding this define at the beginning of sspi.h:
-# #define FreeCredentialHandle FreeCredentialsHandle
-#
-# If, for some reason the Windows SDK is installed but not installed
-# in the default location, you can specify WINDOWS_SDK_PATH.
-# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
-
-# WINDOWS_SSPI = 1
-
-!IFDEF WINDOWS_SSPI
-!IFNDEF WINDOWS_SDK_PATH
-WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
-!ENDIF
-!ENDIF
-
-#############################################################
-## Nothing more to do below this line!
-
-CCNODBG = cl.exe /O2 /DNDEBUG
-CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
-CFLAGSWINSSL = /DUSE_SCHANNEL
-CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
-CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
-CFLAGS = /I. /I../include /nologo /W3 /EHsc /DWIN32 /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
-CFLAGSLIB = /DCURL_STATICLIB
-LNKDLL = link.exe /DLL
-LNKLIB = link.exe /lib
-LFLAGS = /nologo /machine:$(MACHINE)
-SSLLIBS = libeay32.lib ssleay32.lib
-ZLIBLIBSDLL = zdll.lib
-ZLIBLIBS = zlib.lib
-WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
-CFLAGS = $(CFLAGS)
-
-CFGSET = FALSE
-
-!IFDEF WINDOWS_SSPI
-CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
-!ENDIF
-
-!IFDEF USE_IPV6
-CFLAGS = $(CFLAGS) /DUSE_IPV6
-!ENDIF
-
-!IFDEF USE_IDN
-CFLAGS = $(CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
-!ENDIF
-
-##############################################################
-# Runtime library configuration
-
-RTLIB = /MD
-RTLIBD = /MDd
-
-!IF "$(RTLIBCFG)" == "static"
-RTLIB = /MT
-RTLIBD = /MTd
-!ENDIF
-
-
-######################
-# release
-
-!IF "$(CFG)" == "release"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl
-
-!IF "$(CFG)" == "release-ssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl
-
-!IF "$(CFG)" == "release-winssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib
-
-!IF "$(CFG)" == "release-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-zlib
-
-!IF "$(CFG)" == "release-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl-zlib
-
-!IF "$(CFG)" == "release-winssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "release-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll
-
-!IF "$(CFG)" == "release-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib-dll
-
-!IF "$(CFG)" == "release-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-dll
-
-!IF "$(CFG)" == "release-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug
-
-!IF "$(CFG)" == "debug"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl
-
-!IF "$(CFG)" == "debug-ssl"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib
-
-!IF "$(CFG)" == "debug-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-zlib
-
-!IF "$(CFG)" == "debug-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll
-
-!IF "$(CFG)" == "debug-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)\out32dll
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib-dll
-
-!IF "$(CFG)" == "debug-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-dll
-
-!IF "$(CFG)" == "debug-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-#######################
-# Usage
-#
-!IF "$(CFGSET)" == "FALSE" && "$(CFG)" != ""
-!MESSAGE Usage: nmake /f makefile.vc14 CFG=<config> <target>
-!MESSAGE where <config> is one of:
-!MESSAGE release - release static library
-!MESSAGE release-ssl - release static library with ssl
-!MESSAGE release-zlib - release static library with zlib
-!MESSAGE release-ssl-zlib - release static library with ssl and zlib
-!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
-!MESSAGE release-ssl-dll - release static library with dynamic ssl
-!MESSAGE release-zlib-dll - release static library with dynamic zlib
-!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
-!MESSAGE release-dll - release dynamic library
-!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
-!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
-!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE debug - debug static library
-!MESSAGE debug-ssl - debug static library with ssl
-!MESSAGE debug-zlib - debug static library with zlib
-!MESSAGE debug-ssl-zlib - debug static library with ssl and zlib
-!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
-!MESSAGE debug-ssl-dll - debug static library with dynamic ssl
-!MESSAGE debug-zlib-dll - debug static library with dynamic zlib
-!MESSAGE debug-ssl-dll-zlib-dll - debug static library with dynamic ssl and dynamic zlib
-!MESSAGE debug-dll - debug dynamic library
-!MESSAGE debug-dll-ssl-dll - debug dynamic library with dynamic ssl
-!MESSAGE debug-dll-zlib-dll - debug dynamic library with dynamic zlib1
-!MESSAGE debug-dll-ssl-dll-zlib-dll - debug dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE <target> can be left blank in which case all is assumed
-!ERROR please choose a valid configuration "$(CFG)"
-!ENDIF
-
-#######################
-# Only the clean target can be used if a config was not provided.
-#
-!IF "$(CFGSET)" == "FALSE"
-clean:
- @-erase /s *.dll 2> NUL
- @-erase /s *.exp 2> NUL
- @-erase /s *.idb 2> NUL
- @-erase /s *.lib 2> NUL
- @-erase /s *.obj 2> NUL
- @-erase /s *.pch 2> NUL
- @-erase /s *.pdb 2> NUL
- @-erase /s *.res 2> NUL
-!ELSE
-# A config was provided, so the library can be built.
-#
-X_OBJS= \
- $(DIROBJ)\amigaos.obj \
- $(DIROBJ)\asyn-ares.obj \
- $(DIROBJ)\asyn-thread.obj \
- $(DIROBJ)\axtls.obj \
- $(DIROBJ)\base64.obj \
- $(DIROBJ)\conncache.obj \
- $(DIROBJ)\connect.obj \
- $(DIROBJ)\content_encoding.obj \
- $(DIROBJ)\cookie.obj \
- $(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
- $(DIROBJ)\curl_endian.obj \
- $(DIROBJ)\curl_fnmatch.obj \
- $(DIROBJ)\curl_gethostname.obj \
- $(DIROBJ)\curl_gssapi.obj \
- $(DIROBJ)\curl_memrchr.obj \
- $(DIROBJ)\curl_multibyte.obj \
- $(DIROBJ)\curl_ntlm.obj \
- $(DIROBJ)\curl_ntlm_core.obj \
- $(DIROBJ)\curl_ntlm_msgs.obj \
- $(DIROBJ)\curl_ntlm_wb.obj \
- $(DIROBJ)\curl_rtmp.obj \
- $(DIROBJ)\curl_sasl.obj \
- $(DIROBJ)\curl_sasl_gssapi.obj \
- $(DIROBJ)\curl_sasl_sspi.obj \
- $(DIROBJ)\curl_sspi.obj \
- $(DIROBJ)\curl_threads.obj \
- $(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
- $(DIROBJ)\dict.obj \
- $(DIROBJ)\dotdot.obj \
- $(DIROBJ)\easy.obj \
- $(DIROBJ)\escape.obj \
- $(DIROBJ)\file.obj \
- $(DIROBJ)\fileinfo.obj \
- $(DIROBJ)\formdata.obj \
- $(DIROBJ)\ftp.obj \
- $(DIROBJ)\ftplistparser.obj \
- $(DIROBJ)\getenv.obj \
- $(DIROBJ)\getinfo.obj \
- $(DIROBJ)\gopher.obj \
- $(DIROBJ)\gtls.obj \
- $(DIROBJ)\hash.obj \
- $(DIROBJ)\hmac.obj \
- $(DIROBJ)\hostasyn.obj \
- $(DIROBJ)\hostcheck.obj \
- $(DIROBJ)\hostip.obj \
- $(DIROBJ)\hostip4.obj \
- $(DIROBJ)\hostip6.obj \
- $(DIROBJ)\hostsyn.obj \
- $(DIROBJ)\http.obj \
- $(DIROBJ)\http_chunks.obj \
- $(DIROBJ)\http_digest.obj \
- $(DIROBJ)\http_negotiate.obj \
- $(DIROBJ)\http_negotiate_sspi.obj \
- $(DIROBJ)\http_proxy.obj \
- $(DIROBJ)\idn_win32.obj \
- $(DIROBJ)\if2ip.obj \
- $(DIROBJ)\imap.obj \
- $(DIROBJ)\inet_ntop.obj \
- $(DIROBJ)\inet_pton.obj \
- $(DIROBJ)\krb5.obj \
- $(DIROBJ)\ldap.obj \
- $(DIROBJ)\llist.obj \
- $(DIROBJ)\md4.obj \
- $(DIROBJ)\md5.obj \
- $(DIROBJ)\memdebug.obj \
- $(DIROBJ)\mprintf.obj \
- $(DIROBJ)\multi.obj \
- $(DIROBJ)\netrc.obj \
- $(DIROBJ)\non-ascii.obj \
- $(DIROBJ)\nonblock.obj \
- $(DIROBJ)\nss.obj \
- $(DIROBJ)\openldap.obj \
- $(DIROBJ)\parsedate.obj \
- $(DIROBJ)\pingpong.obj \
- $(DIROBJ)\pipeline.obj \
- $(DIROBJ)\polarssl.obj \
- $(DIROBJ)\polarssl_threadlock.obj \
- $(DIROBJ)\pop3.obj \
- $(DIROBJ)\progress.obj \
- $(DIROBJ)\rawstr.obj \
- $(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
- $(DIROBJ)\security.obj \
- $(DIROBJ)\select.obj \
- $(DIROBJ)\sendf.obj \
- $(DIROBJ)\share.obj \
- $(DIROBJ)\slist.obj \
- $(DIROBJ)\smb.obj \
- $(DIROBJ)\smtp.obj \
- $(DIROBJ)\socks.obj \
- $(DIROBJ)\socks_gssapi.obj \
- $(DIROBJ)\socks_sspi.obj \
- $(DIROBJ)\speedcheck.obj \
- $(DIROBJ)\splay.obj \
- $(DIROBJ)\ssh.obj \
- $(DIROBJ)\vtls.obj \
- $(DIROBJ)\openssl.obj \
- $(DIROBJ)\strdup.obj \
- $(DIROBJ)\strequal.obj \
- $(DIROBJ)\strerror.obj \
- $(DIROBJ)\strtok.obj \
- $(DIROBJ)\strtoofft.obj \
- $(DIROBJ)\telnet.obj \
- $(DIROBJ)\tftp.obj \
- $(DIROBJ)\timeval.obj \
- $(DIROBJ)\transfer.obj \
- $(DIROBJ)\url.obj \
- $(DIROBJ)\version.obj \
- $(DIROBJ)\warnless.obj \
- $(DIROBJ)\wildcard.obj \
- $(RESOURCE)
-
-all : $(TARGET)
-
-$(TARGET): $(X_OBJS)
- $(LNK) $(LFLAGS) $(X_OBJS)
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) . /y
- -xcopy $(DIROBJ)\*.exp . /y
- -xcopy $(DIROBJ)\*.pdb . /y
-
-$(X_OBJS): $(DIROBJ)
-
-$(DIROBJ):
- @if not exist "$(DIROBJ)" mkdir $(DIROBJ)
-
-.SUFFIXES: .c .obj .res
-
-{.\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-{.\vtls\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-debug-dll\libcurl.res \
-debug-dll-ssl-dll\libcurl.res \
-debug-dll-zlib-dll\libcurl.res \
-debug-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=1 /Fo $@ libcurl.rc
-
-release-dll\libcurl.res \
-release-dll-ssl-dll\libcurl.res \
-release-dll-zlib-dll\libcurl.res \
-release-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=0 /Fo $@ libcurl.rc
-!ENDIF # End of case where a config was provided.
diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6 index c34c3dbc7..ee20ebe12 100644 --- a/lib/Makefile.vc6 +++ b/lib/Makefile.vc6 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2014, 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
@@ -65,11 +65,11 @@ !INCLUDE ..\winbuild\Makefile.msvc.names
!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
+OPENSSL_PATH = ../../openssl-0.9.8zc
!ENDIF
!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
+LIBSSH2_PATH = ../../libssh2-1.4.3
!ENDIF
!IFNDEF ZLIB_PATH
@@ -90,7 +90,7 @@ MACHINE = X86 # If, for some reason the Windows SDK is installed but not installed
# in the default location, you can specify WINDOWS_SDK_PATH.
# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
# WINDOWS_SSPI = 1
@@ -105,7 +105,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK" CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
+CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSWINSSL = /DUSE_SCHANNEL
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
@@ -427,7 +427,7 @@ CFGSET = TRUE TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
+CC = $(CCDEBUG) $(RTLIBD)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
@@ -528,12 +528,13 @@ X_OBJS= \ $(DIROBJ)\asyn-thread.obj \
$(DIROBJ)\axtls.obj \
$(DIROBJ)\base64.obj \
+ $(DIROBJ)\bundles.obj \
$(DIROBJ)\conncache.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
+ $(DIROBJ)\curl_darwinssl.obj \
$(DIROBJ)\curl_endian.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
@@ -548,10 +549,10 @@ X_OBJS= \ $(DIROBJ)\curl_sasl.obj \
$(DIROBJ)\curl_sasl_gssapi.obj \
$(DIROBJ)\curl_sasl_sspi.obj \
+ $(DIROBJ)\curl_schannel.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\dotdot.obj \
$(DIROBJ)\easy.obj \
@@ -606,7 +607,6 @@ X_OBJS= \ $(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
diff --git a/lib/Makefile.vc7 b/lib/Makefile.vc7 deleted file mode 100644 index 97c4773a5..000000000 --- a/lib/Makefile.vc7 +++ /dev/null @@ -1,677 +0,0 @@ -#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 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 http://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.
-#
-#***************************************************************************
-
-# All files in the Makefile.vc* series are generated automatically from the
-# one made for MSVC version 6. Alas, if you want to do changes to any of the
-# files and send back to the project, edit the version six, make your diff and
-# mail curl-library.
-
-###########################################################################
-#
-# Makefile for building libcurl with MSVC7
-#
-# Usage: see usage message below
-# Should be invoked from \lib directory
-# Edit the paths and desired library name
-# SSL path is only required if you intend compiling
-# with SSL.
-#
-# This make file leaves the result either a .lib or .dll file
-# in the \lib directory. It should be called from the \lib
-# directory.
-#
-# An option would have been to allow the source directory to
-# be specified, but I saw no requirement.
-#
-# Another option would have been to leave the .lib and .dll
-# files in the "cfg" directory, but then the make file
-# in \src would need to be changed.
-#
-##############################################################
-
-# ----------------------------------------------
-# Verify that current subdir is libcurl's 'lib'
-# ----------------------------------------------
-
-!IF ! EXIST(.\curl_addrinfo.c)
-! MESSAGE Can not process this makefile from outside of libcurl's 'lib' subdirectory.
-! MESSAGE Change to libcurl's 'lib' subdirectory, and try again.
-! ERROR See previous message.
-!ENDIF
-
-# ------------------------------------------------
-# Makefile.msvc.names provides libcurl file names
-# ------------------------------------------------
-
-!INCLUDE ..\winbuild\Makefile.msvc.names
-
-!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-!ENDIF
-
-!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-!ENDIF
-
-!IFNDEF ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-!ENDIF
-
-!IFNDEF MACHINE
-MACHINE = X86
-!ENDIF
-
-# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
-# without an openssl installation and offers the ability to authenticate
-# using the "current logged in user". Since at least with MSVC7 the sspi.h
-# header is broken it is either required to install the Windows SDK,
-# or to fix sspi.h with adding this define at the beginning of sspi.h:
-# #define FreeCredentialHandle FreeCredentialsHandle
-#
-# If, for some reason the Windows SDK is installed but not installed
-# in the default location, you can specify WINDOWS_SDK_PATH.
-# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
-
-# WINDOWS_SSPI = 1
-
-!IFDEF WINDOWS_SSPI
-!IFNDEF WINDOWS_SDK_PATH
-WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
-!ENDIF
-!ENDIF
-
-#############################################################
-## Nothing more to do below this line!
-
-CCNODBG = cl.exe /O2 /DNDEBUG
-CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
-CFLAGSWINSSL = /DUSE_SCHANNEL
-CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
-CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
-CFLAGS = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
-CFLAGSLIB = /DCURL_STATICLIB
-LNKDLL = link.exe /DLL
-LNKLIB = link.exe /lib
-LFLAGS = /nologo /machine:$(MACHINE)
-SSLLIBS = libeay32.lib ssleay32.lib
-ZLIBLIBSDLL = zdll.lib
-ZLIBLIBS = zlib.lib
-WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
-CFLAGS = $(CFLAGS)
-
-CFGSET = FALSE
-
-!IFDEF WINDOWS_SSPI
-CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
-!ENDIF
-
-!IFDEF USE_IPV6
-CFLAGS = $(CFLAGS) /DUSE_IPV6
-!ENDIF
-
-!IFDEF USE_IDN
-CFLAGS = $(CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
-!ENDIF
-
-##############################################################
-# Runtime library configuration
-
-RTLIB = /MD
-RTLIBD = /MDd
-
-!IF "$(RTLIBCFG)" == "static"
-RTLIB = /MT
-RTLIBD = /MTd
-!ENDIF
-
-
-######################
-# release
-
-!IF "$(CFG)" == "release"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl
-
-!IF "$(CFG)" == "release-ssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl
-
-!IF "$(CFG)" == "release-winssl"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib
-
-!IF "$(CFG)" == "release-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-zlib
-
-!IF "$(CFG)" == "release-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-winssl-zlib
-
-!IF "$(CFG)" == "release-winssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "release-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll
-
-!IF "$(CFG)" == "release-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-zlib-dll
-
-!IF "$(CFG)" == "release-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# release-dll
-
-!IF "$(CFG)" == "release-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# release-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "release-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_REL)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
-CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug
-
-!IF "$(CFG)" == "debug"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl
-
-!IF "$(CFG)" == "debug-ssl"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib
-
-!IF "$(CFG)" == "debug-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-zlib
-
-!IF "$(CFG)" == "debug-ssl-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-ssh2-zlib
-
-!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
-LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll
-
-!IF "$(CFG)" == "debug-ssl-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)\out32dll
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-zlib-dll
-
-!IF "$(CFG)" == "debug-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_STA_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
-CFGSET = TRUE
-!ENDIF
-
-######################
-# debug-dll
-
-!IF "$(CFG)" == "debug-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-######################
-# debug-dll-ssl-dll-zlib-dll
-
-!IF "$(CFG)" == "debug-dll-ssl-dll-zlib-dll"
-TARGET = $(LIBCURL_DYN_LIB_DBG)
-DIROBJ = $(CFG)
-LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
-LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
-LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB)
-CFGSET = TRUE
-RESOURCE = $(DIROBJ)\libcurl.res
-!ENDIF
-
-#######################
-# Usage
-#
-!IF "$(CFGSET)" == "FALSE" && "$(CFG)" != ""
-!MESSAGE Usage: nmake /f makefile.vc6 CFG=<config> <target>
-!MESSAGE where <config> is one of:
-!MESSAGE release - release static library
-!MESSAGE release-ssl - release static library with ssl
-!MESSAGE release-zlib - release static library with zlib
-!MESSAGE release-ssl-zlib - release static library with ssl and zlib
-!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
-!MESSAGE release-ssl-dll - release static library with dynamic ssl
-!MESSAGE release-zlib-dll - release static library with dynamic zlib
-!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
-!MESSAGE release-dll - release dynamic library
-!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
-!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
-!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE debug - debug static library
-!MESSAGE debug-ssl - debug static library with ssl
-!MESSAGE debug-zlib - debug static library with zlib
-!MESSAGE debug-ssl-zlib - debug static library with ssl and zlib
-!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
-!MESSAGE debug-ssl-dll - debug static library with dynamic ssl
-!MESSAGE debug-zlib-dll - debug static library with dynamic zlib
-!MESSAGE debug-ssl-dll-zlib-dll - debug static library with dynamic ssl and dynamic zlib
-!MESSAGE debug-dll - debug dynamic library
-!MESSAGE debug-dll-ssl-dll - debug dynamic library with dynamic ssl
-!MESSAGE debug-dll-zlib-dll - debug dynamic library with dynamic zlib1
-!MESSAGE debug-dll-ssl-dll-zlib-dll - debug dynamic library with dynamic ssl and dynamic zlib
-!MESSAGE <target> can be left blank in which case all is assumed
-!ERROR please choose a valid configuration "$(CFG)"
-!ENDIF
-
-#######################
-# Only the clean target can be used if a config was not provided.
-#
-!IF "$(CFGSET)" == "FALSE"
-clean:
- @-erase /s *.dll 2> NUL
- @-erase /s *.exp 2> NUL
- @-erase /s *.idb 2> NUL
- @-erase /s *.lib 2> NUL
- @-erase /s *.obj 2> NUL
- @-erase /s *.pch 2> NUL
- @-erase /s *.pdb 2> NUL
- @-erase /s *.res 2> NUL
-!ELSE
-# A config was provided, so the library can be built.
-#
-X_OBJS= \
- $(DIROBJ)\amigaos.obj \
- $(DIROBJ)\asyn-ares.obj \
- $(DIROBJ)\asyn-thread.obj \
- $(DIROBJ)\axtls.obj \
- $(DIROBJ)\base64.obj \
- $(DIROBJ)\conncache.obj \
- $(DIROBJ)\connect.obj \
- $(DIROBJ)\content_encoding.obj \
- $(DIROBJ)\cookie.obj \
- $(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
- $(DIROBJ)\curl_endian.obj \
- $(DIROBJ)\curl_fnmatch.obj \
- $(DIROBJ)\curl_gethostname.obj \
- $(DIROBJ)\curl_gssapi.obj \
- $(DIROBJ)\curl_memrchr.obj \
- $(DIROBJ)\curl_multibyte.obj \
- $(DIROBJ)\curl_ntlm.obj \
- $(DIROBJ)\curl_ntlm_core.obj \
- $(DIROBJ)\curl_ntlm_msgs.obj \
- $(DIROBJ)\curl_ntlm_wb.obj \
- $(DIROBJ)\curl_rtmp.obj \
- $(DIROBJ)\curl_sasl.obj \
- $(DIROBJ)\curl_sasl_gssapi.obj \
- $(DIROBJ)\curl_sasl_sspi.obj \
- $(DIROBJ)\curl_sspi.obj \
- $(DIROBJ)\curl_threads.obj \
- $(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
- $(DIROBJ)\dict.obj \
- $(DIROBJ)\dotdot.obj \
- $(DIROBJ)\easy.obj \
- $(DIROBJ)\escape.obj \
- $(DIROBJ)\file.obj \
- $(DIROBJ)\fileinfo.obj \
- $(DIROBJ)\formdata.obj \
- $(DIROBJ)\ftp.obj \
- $(DIROBJ)\ftplistparser.obj \
- $(DIROBJ)\getenv.obj \
- $(DIROBJ)\getinfo.obj \
- $(DIROBJ)\gopher.obj \
- $(DIROBJ)\gtls.obj \
- $(DIROBJ)\hash.obj \
- $(DIROBJ)\hmac.obj \
- $(DIROBJ)\hostasyn.obj \
- $(DIROBJ)\hostcheck.obj \
- $(DIROBJ)\hostip.obj \
- $(DIROBJ)\hostip4.obj \
- $(DIROBJ)\hostip6.obj \
- $(DIROBJ)\hostsyn.obj \
- $(DIROBJ)\http.obj \
- $(DIROBJ)\http_chunks.obj \
- $(DIROBJ)\http_digest.obj \
- $(DIROBJ)\http_negotiate.obj \
- $(DIROBJ)\http_negotiate_sspi.obj \
- $(DIROBJ)\http_proxy.obj \
- $(DIROBJ)\idn_win32.obj \
- $(DIROBJ)\if2ip.obj \
- $(DIROBJ)\imap.obj \
- $(DIROBJ)\inet_ntop.obj \
- $(DIROBJ)\inet_pton.obj \
- $(DIROBJ)\krb5.obj \
- $(DIROBJ)\ldap.obj \
- $(DIROBJ)\llist.obj \
- $(DIROBJ)\md4.obj \
- $(DIROBJ)\md5.obj \
- $(DIROBJ)\memdebug.obj \
- $(DIROBJ)\mprintf.obj \
- $(DIROBJ)\multi.obj \
- $(DIROBJ)\netrc.obj \
- $(DIROBJ)\non-ascii.obj \
- $(DIROBJ)\nonblock.obj \
- $(DIROBJ)\nss.obj \
- $(DIROBJ)\openldap.obj \
- $(DIROBJ)\parsedate.obj \
- $(DIROBJ)\pingpong.obj \
- $(DIROBJ)\pipeline.obj \
- $(DIROBJ)\polarssl.obj \
- $(DIROBJ)\polarssl_threadlock.obj \
- $(DIROBJ)\pop3.obj \
- $(DIROBJ)\progress.obj \
- $(DIROBJ)\rawstr.obj \
- $(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
- $(DIROBJ)\security.obj \
- $(DIROBJ)\select.obj \
- $(DIROBJ)\sendf.obj \
- $(DIROBJ)\share.obj \
- $(DIROBJ)\slist.obj \
- $(DIROBJ)\smb.obj \
- $(DIROBJ)\smtp.obj \
- $(DIROBJ)\socks.obj \
- $(DIROBJ)\socks_gssapi.obj \
- $(DIROBJ)\socks_sspi.obj \
- $(DIROBJ)\speedcheck.obj \
- $(DIROBJ)\splay.obj \
- $(DIROBJ)\ssh.obj \
- $(DIROBJ)\vtls.obj \
- $(DIROBJ)\openssl.obj \
- $(DIROBJ)\strdup.obj \
- $(DIROBJ)\strequal.obj \
- $(DIROBJ)\strerror.obj \
- $(DIROBJ)\strtok.obj \
- $(DIROBJ)\strtoofft.obj \
- $(DIROBJ)\telnet.obj \
- $(DIROBJ)\tftp.obj \
- $(DIROBJ)\timeval.obj \
- $(DIROBJ)\transfer.obj \
- $(DIROBJ)\url.obj \
- $(DIROBJ)\version.obj \
- $(DIROBJ)\warnless.obj \
- $(DIROBJ)\wildcard.obj \
- $(RESOURCE)
-
-all : $(TARGET)
-
-$(TARGET): $(X_OBJS)
- $(LNK) $(LFLAGS) $(X_OBJS)
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_DBG) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_REL) . /y
- -xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) . /y
- -xcopy $(DIROBJ)\*.exp . /y
- -xcopy $(DIROBJ)\*.pdb . /y
-
-$(X_OBJS): $(DIROBJ)
-
-$(DIROBJ):
- @if not exist "$(DIROBJ)" mkdir $(DIROBJ)
-
-.SUFFIXES: .c .obj .res
-
-{.\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-{.\vtls\}.c{$(DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
-
-debug-dll\libcurl.res \
-debug-dll-ssl-dll\libcurl.res \
-debug-dll-zlib-dll\libcurl.res \
-debug-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=1 /Fo $@ libcurl.rc
-
-release-dll\libcurl.res \
-release-dll-ssl-dll\libcurl.res \
-release-dll-zlib-dll\libcurl.res \
-release-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
- rc /dDEBUGBUILD=0 /Fo $@ libcurl.rc
-!ENDIF # End of case where a config was provided.
diff --git a/lib/Makefile.vc8 b/lib/Makefile.vc8 index 10732f9ba..0d10ac570 100644 --- a/lib/Makefile.vc8 +++ b/lib/Makefile.vc8 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2014, 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
@@ -65,11 +65,11 @@ !INCLUDE ..\winbuild\Makefile.msvc.names
!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
+OPENSSL_PATH = ../../openssl-0.9.8zc
!ENDIF
!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
+LIBSSH2_PATH = ../../libssh2-1.4.3
!ENDIF
!IFNDEF ZLIB_PATH
@@ -90,7 +90,7 @@ MACHINE = X86 # If, for some reason the Windows SDK is installed but not installed
# in the default location, you can specify WINDOWS_SDK_PATH.
# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
# WINDOWS_SSPI = 1
@@ -105,7 +105,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK" CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
+CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSWINSSL = /DUSE_SCHANNEL
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
@@ -427,7 +427,7 @@ CFGSET = TRUE TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
+CC = $(CCDEBUG) $(RTLIBD)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
@@ -528,12 +528,13 @@ X_OBJS= \ $(DIROBJ)\asyn-thread.obj \
$(DIROBJ)\axtls.obj \
$(DIROBJ)\base64.obj \
+ $(DIROBJ)\bundles.obj \
$(DIROBJ)\conncache.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
+ $(DIROBJ)\curl_darwinssl.obj \
$(DIROBJ)\curl_endian.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
@@ -548,10 +549,10 @@ X_OBJS= \ $(DIROBJ)\curl_sasl.obj \
$(DIROBJ)\curl_sasl_gssapi.obj \
$(DIROBJ)\curl_sasl_sspi.obj \
+ $(DIROBJ)\curl_schannel.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\dotdot.obj \
$(DIROBJ)\easy.obj \
@@ -606,7 +607,6 @@ X_OBJS= \ $(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
diff --git a/lib/Makefile.vc9 b/lib/Makefile.vc9 index 0d9d951f8..9f1b8d44a 100644 --- a/lib/Makefile.vc9 +++ b/lib/Makefile.vc9 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2014, 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
@@ -65,11 +65,11 @@ !INCLUDE ..\winbuild\Makefile.msvc.names
!IFNDEF OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
+OPENSSL_PATH = ../../openssl-0.9.8zc
!ENDIF
!IFNDEF LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
+LIBSSH2_PATH = ../../libssh2-1.4.3
!ENDIF
!IFNDEF ZLIB_PATH
@@ -90,7 +90,7 @@ MACHINE = X86 # If, for some reason the Windows SDK is installed but not installed
# in the default location, you can specify WINDOWS_SDK_PATH.
# It can be downloaded from:
-# https://msdn.microsoft.com/windows/bb980924.aspx
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
# WINDOWS_SSPI = 1
@@ -105,7 +105,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK" CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /RTC1
-CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
+CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSWINSSL = /DUSE_SCHANNEL
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
@@ -427,7 +427,7 @@ CFGSET = TRUE TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
-CC = $(CCDEBUG) $(RTLIBD)
+CC = $(CCDEBUG) $(RTLIBD)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
@@ -528,12 +528,13 @@ X_OBJS= \ $(DIROBJ)\asyn-thread.obj \
$(DIROBJ)\axtls.obj \
$(DIROBJ)\base64.obj \
+ $(DIROBJ)\bundles.obj \
$(DIROBJ)\conncache.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
- $(DIROBJ)\curl_des.obj \
+ $(DIROBJ)\curl_darwinssl.obj \
$(DIROBJ)\curl_endian.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
@@ -548,10 +549,10 @@ X_OBJS= \ $(DIROBJ)\curl_sasl.obj \
$(DIROBJ)\curl_sasl_gssapi.obj \
$(DIROBJ)\curl_sasl_sspi.obj \
+ $(DIROBJ)\curl_schannel.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\cyassl.obj \
- $(DIROBJ)\darwinssl.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\dotdot.obj \
$(DIROBJ)\easy.obj \
@@ -606,7 +607,6 @@ X_OBJS= \ $(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
- $(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
diff --git a/lib/README.ares b/lib/README.ares new file mode 100644 index 000000000..8c77937eb --- /dev/null +++ b/lib/README.ares @@ -0,0 +1,69 @@ + _ _ ____ _ + ___| | | | _ \| | + / __| | | | |_) | | + | (__| |_| | _ <| |___ + \___|\___/|_| \_\_____| + + How To Build libcurl to Use c-ares For Asynch Name Resolves + =========================================================== + +c-ares: + http://c-ares.haxx.se/ + +NOTE + The latest libcurl version requires c-ares 1.6.0 or later. + + Once upon the time libcurl built fine with the "original" ares. That is no + longer true. You need to use c-ares. + +Build c-ares +============ + +1. unpack the c-ares archive +2. cd c-ares-dir +3. ./configure +4. make +5. make install + +Build libcurl to use c-ares in the curl source tree +=================================================== + +1. name or symlink the c-ares source directory 'ares' in the curl source + directory +2. ./configure --enable-ares + + Optionally, you can point out the c-ares install tree root with the the + --enable-ares option. + +3. make + +Build libcurl to use an installed c-ares +======================================== + +1. ./configure --enable-ares=/path/to/ares/install +2. make + +c-ares on win32 +=============== +(description brought by Dominick Meglio) + +First I compiled c-ares. I changed the default C runtime library to be the +single-threaded rather than the multi-threaded (this seems to be required to +prevent linking errors later on). Then I simply build the areslib project (the +other projects adig/ahost seem to fail under MSVC). + +Next was libcurl. I opened lib/config-win32.h and I added a: + #define USE_ARES 1 + +Next thing I did was I added the path for the ares includes to the include +path, and the libares.lib to the libraries. + +Lastly, I also changed libcurl to be single-threaded rather than +multi-threaded, again this was to prevent some duplicate symbol errors. I'm +not sure why I needed to change everything to single-threaded, but when I +didn't I got redefinition errors for several CRT functions (malloc, stricmp, +etc.) + +I would have modified the MSVC++ project files, but I only have VC.NET and it +uses a different format than VC6.0 so I didn't want to go and change +everything and remove VC6.0 support from libcurl. diff --git a/lib/README.curl_off_t b/lib/README.curl_off_t new file mode 100644 index 000000000..923b2774c --- /dev/null +++ b/lib/README.curl_off_t @@ -0,0 +1,68 @@ + + curl_off_t explained + ==================== + +curl_off_t is a data type provided by the external libcurl include headers. It +is the type meant to be used for the curl_easy_setopt() options that end with +LARGE. The type is 64bit large on most modern platforms. + +Transition from < 7.19.0 to >= 7.19.0 +------------------------------------- + +Applications that used libcurl before 7.19.0 that are rebuilt with a libcurl +that is 7.19.0 or later may or may not have to worry about anything of +this. We have made a significant effort to make the transition really seamless +and transparent. + +You have have to take notice if you are in one of the following situations: + +o Your app is using or will after the transition use a libcurl that is built + with LFS (large file support) disabled even though your system otherwise + supports it. + +o Your app is using or will after the transition use a libcurl that doesn't + support LFS at all, but your system and compiler support 64bit data types. + +In both these cases, the curl_off_t type will now (after the transition) be +64bit where it previously was 32bit. This will cause a binary incompatibility +that you MAY need to deal with. + +Benefits +-------- + +This new way has several benefits: + +o Platforms without LFS support can still use libcurl to do >32 bit file + transfers and range operations etc as long as they have >32 bit data-types + supported. + +o Applications will no longer easily build with the curl_off_t size + mismatched, which has been a very frequent (and annoying) problem with + libcurl <= 7.18.2 + +Historically +------------ + +Previously, before 7.19.0, the curl_off_t type would be rather strongly +connected to the size of the system off_t type, where currently curl_off_t is +independent of that. + +The strong connection to off_t made it troublesome for application authors +since when they did mistakes, they could get curl_off_t type of different +sizes in the app vs libcurl, and that caused strange effects that were hard to +track and detect by users of libcurl. + +SONAME +------ + +We opted to not bump the soname for the library unconditionally, simply +because soname bumping is causing a lot of grief and moaning all over the +community so we try to keep that at minimum. Also, our selected design path +should be 100% backwards compatible for the vast majority of all libcurl +users. + +Enforce SONAME bump +------------------- + +If configure doesn't detect your case where a bump is necessary, re-run it +with the --enable-soname-bump command line option! diff --git a/lib/README.curlx b/lib/README.curlx new file mode 100644 index 000000000..5375b0d1d --- /dev/null +++ b/lib/README.curlx @@ -0,0 +1,61 @@ + _ _ ____ _ + ___| | | | _ \| | + / __| | | | |_) | | + | (__| |_| | _ <| |___ + \___|\___/|_| \_\_____| + + Source Code Functions Apps Might Use + ==================================== + +The libcurl source code offers a few functions by source only. They are not +part of the official libcurl API, but the source files might be useful for +others so apps can optionally compile/build with these sources to gain +additional functions. + +We provide them through a single header file for easy access for apps: +"curlx.h" + + curlx_strtoofft() + + A macro that converts a string containing a number to a curl_off_t number. + This might use the curlx_strtoll() function which is provided as source + code in strtoofft.c. Note that the function is only provided if no + strtoll() (or equivalent) function exist on your platform. If curl_off_t + is only a 32 bit number on your platform, this macro uses strtol(). + + curlx_tvnow() + + returns a struct timeval for the current time. + + curlx_tvdiff() + + returns the difference between two timeval structs, in number of + milliseconds. + + curlx_tvdiff_secs() + + returns the same as curlx_tvdiff but with full usec resolution (as a + double) + +FUTURE +====== + + Several functions will be removed from the public curl_ name space in a + future libcurl release. They will then only become available as curlx_ + functions instead. To make the transition easier, we already today provide + these functions with the curlx_ prefix to allow sources to get built properly + with the new function names. The functions this concerns are: + + curlx_getenv + curlx_strequal + curlx_strnequal + curlx_mvsnprintf + curlx_msnprintf + curlx_maprintf + curlx_mvaprintf + curlx_msprintf + curlx_mprintf + curlx_mfprintf + curlx_mvsprintf + curlx_mvprintf + curlx_mvfprintf diff --git a/lib/README.encoding b/lib/README.encoding new file mode 100644 index 000000000..1012bb9ec --- /dev/null +++ b/lib/README.encoding @@ -0,0 +1,60 @@ + + Content Encoding Support for libcurl + +* About content encodings: + +HTTP/1.1 [RFC 2616] specifies that a client may request that a server encode +its response. This is usually used to compress a response using one of a set +of commonly available compression techniques. These schemes are `deflate' (the +zlib algorithm), `gzip' and `compress' [sec 3.5, RFC 2616]. A client requests +that the sever perform an encoding by including an Accept-Encoding header in +the request document. The value of the header should be one of the recognized +tokens `deflate', ... (there's a way to register new schemes/tokens, see sec +3.5 of the spec). A server MAY honor the client's encoding request. When a +response is encoded, the server includes a Content-Encoding header in the +response. The value of the Content-Encoding header indicates which scheme was +used to encode the data. + +A client may tell a server that it can understand several different encoding +schemes. In this case the server may choose any one of those and use it to +encode the response (indicating which one using the Content-Encoding header). +It's also possible for a client to attach priorities to different schemes so +that the server knows which it prefers. See sec 14.3 of RFC 2616 for more +information on the Accept-Encoding header. + +* Current support for content encoding: + +Support for the 'deflate' and 'gzip' content encoding are supported by +libcurl. Both regular and chunked transfers should work fine. The library +zlib is required for this feature. 'deflate' support was added by James +Gallagher, and support for the 'gzip' encoding was added by Dan Fandrich. + +* The libcurl interface: + +To cause libcurl to request a content encoding use: + + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, <string>) + +where <string> is the intended value of the Accept-Encoding header. + +Currently, libcurl only understands how to process responses that use the +"deflate" or "gzip" Content-Encoding, so the only values for +CURLOPT_ACCEPT_ENCODING that will work (besides "identity," which does +nothing) are "deflate" and "gzip" If a response is encoded using the +"compress" or methods, libcurl will return an error indicating that the +response could not be decoded. If <string> is NULL no Accept-Encoding header +is generated. If <string> is a zero-length string, then an Accept-Encoding +header containing all supported encodings will be generated. + +The CURLOPT_ACCEPT_ENCODING must be set to any non-NULL value for content to +be automatically decoded. If it is not set and the server still sends encoded +content (despite not having been asked), the data is returned in its raw form +and the Content-Encoding type is not checked. + +* The curl interface: + +Use the --compressed option with curl to cause it to ask servers to compress +responses using any format supported by curl. + +James Gallagher <jgallagher@gso.uri.edu> +Dan Fandrich <dan@coneharvesters.com> diff --git a/lib/README.hostip b/lib/README.hostip new file mode 100644 index 000000000..d5688fff1 --- /dev/null +++ b/lib/README.hostip @@ -0,0 +1,35 @@ + hostip.c explained + ================== + + The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c + source file are these: + + CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use + that. The host may not be able to resolve IPv6, but we don't really have to + take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 + defined. + + CURLRES_ARES - is defined if libcurl is built to use c-ares for asynchronous + name resolves. This can be Windows or *nix. + + CURLRES_THREADED - is defined if libcurl is built to use threading for + asynchronous name resolves. The name resolve will be done in a new thread, + and the supported asynch API will be the same as for ares-builds. This is + the default under (native) Windows. + + If any of the two previous are defined, CURLRES_ASYNCH is defined too. If + libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is + defined. + + The host*.c sources files are split up like this: + + hostip.c - method-independent resolver functions and utility functions + hostasyn.c - functions for asynchronous name resolves + hostsyn.c - functions for synchronous name resolves + asyn-ares.c - functions for asynchronous name resolves using c-ares + asyn-thread.c - functions for asynchronous name resolves using threads + hostip4.c - IPv4 specific functions + hostip6.c - IPv6 specific functions + + The hostip.h is the single united header file for all this. It defines the + CURLRES_* defines based on the config*.h and curl_setup.h defines. diff --git a/lib/README.httpauth b/lib/README.httpauth new file mode 100644 index 000000000..960504510 --- /dev/null +++ b/lib/README.httpauth @@ -0,0 +1,74 @@ + +1. PUT/POST without a known auth to use (possibly no auth required): + + (When explicitly set to use a multi-pass auth when doing a POST/PUT, + libcurl should immediately go the Content-Length: 0 bytes route to avoid + the first send all data phase, step 2. If told to use a single-pass auth, + goto step 3.) + + Issue the proper PUT/POST request immediately, with the correct + Content-Length and Expect: headers. + + If a 100 response is received or the wait for one times out, start sending + the request-body. + + If a 401 (or 407 when talking through a proxy) is received, then: + + If we have "more than just a little" data left to send, close the + connection. Exactly what "more than just a little" means will have to be + determined. Possibly the current transfer speed should be taken into + account as well. + + NOTE: if the size of the POST data is less than MAX_INITIAL_POST_SIZE (when + CURLOPT_POSTFIELDS is used), libcurl will send everything in one single + write() (all request-headers and request-body) and thus it will + unconditionally send the full post data here. + +2. PUT/POST with multi-pass auth but not yet completely negotiated: + + Send a PUT/POST request, we know that it will be rejected and thus we claim + Content-Length zero to avoid having to send the request-body. (This seems + to be what IE does.) + +3. PUT/POST as the last step in the auth negotiation, that is when we have + what we believe is a completed negotiation: + + Send a full and proper PUT/POST request (again) with the proper + Content-Length and a following request-body. + + NOTE: this may very well be the second (or even third) time the whole or at + least parts of the request body is sent to the server. Since the data may + be provided to libcurl with a callback, we need a way to tell the app that + the upload is to be restarted so that the callback will provide data from + the start again. This requires an API method/mechanism that libcurl + doesn't have today. See below. + +Data Rewind + + It will be troublesome for some apps to deal with a rewind like this in all + circumstances. I'm thinking for example when using 'curl' to upload data + from stdin. If libcurl ends up having to rewind the reading for a request + to succeed, of course a lack of this callback or if it returns failure, will + cause the request to fail completely. + + The new callback is set with CURLOPT_IOCTLFUNCTION (in an attempt to add a + more generic function that might be used for other IO-related controls in + the future): + + curlioerr curl_ioctl(CURL *handle, curliocmd cmd, void *clientp); + + And in the case where the read is to be rewinded, it would be called with a + cmd named CURLIOCMD_RESTARTREAD. The callback would then return CURLIOE_OK, + if things are fine, or CURLIOE_FAILRESTART if not. + +Backwards Compatibility + + The approach used until now, that issues a HEAD on the given URL to trigger + the auth negotiation could still be supported and encouraged, but it would + be up to the app to first fetch a URL with GET/HEAD to negotiate on, since + then a following PUT/POST wouldn't need to negotiate authentication and + thus avoid double-sending data. + + Optionally, we keep the current approach if some option is set + (CURLOPT_HEADBEFOREAUTH or similar), since it seems to work fairly well for + POST on most servers. diff --git a/lib/README.memoryleak b/lib/README.memoryleak new file mode 100644 index 000000000..166177794 --- /dev/null +++ b/lib/README.memoryleak @@ -0,0 +1,55 @@ + _ _ ____ _ + ___| | | | _ \| | + / __| | | | |_) | | + | (__| |_| | _ <| |___ + \___|\___/|_| \_\_____| + + How To Track Down Suspected Memory Leaks in libcurl + =================================================== + +Single-threaded + + Please note that this memory leak system is not adjusted to work in more + than one thread. If you want/need to use it in a multi-threaded app. Please + adjust accordingly. + + +Build + + Rebuild libcurl with -DCURLDEBUG (usually, rerunning configure with + --enable-debug fixes this). 'make clean' first, then 'make' so that all + files actually are rebuilt properly. It will also make sense to build + libcurl with the debug option (usually -g to the compiler) so that debugging + it will be easier if you actually do find a leak in the library. + + This will create a library that has memory debugging enabled. + +Modify Your Application + + Add a line in your application code: + + curl_memdebug("dump"); + + This will make the malloc debug system output a full trace of all resource + using functions to the given file name. Make sure you rebuild your program + and that you link with the same libcurl you built for this purpose as + described above. + +Run Your Application + + Run your program as usual. Watch the specified memory trace file grow. + + Make your program exit and use the proper libcurl cleanup functions etc. So + that all non-leaks are returned/freed properly. + +Analyze the Flow + + Use the tests/memanalyze.pl perl script to analyze the dump file: + + tests/memanalyze.pl dump + + This now outputs a report on what resources that were allocated but never + freed etc. This report is very fine for posting to the list! + + If this doesn't produce any output, no leak was detected in libcurl. Then + the leak is mostly likely to be in your code. diff --git a/lib/README.multi_socket b/lib/README.multi_socket new file mode 100644 index 000000000..d91e1d9f2 --- /dev/null +++ b/lib/README.multi_socket @@ -0,0 +1,53 @@ +Implementation of the curl_multi_socket API + + The main ideas of the new API are simply: + + 1 - The application can use whatever event system it likes as it gets info + from libcurl about what file descriptors libcurl waits for what action + on. (The previous API returns fd_sets which is very select()-centric). + + 2 - When the application discovers action on a single socket, it calls + libcurl and informs that there was action on this particular socket and + libcurl can then act on that socket/transfer only and not care about + any other transfers. (The previous API always had to scan through all + the existing transfers.) + + The idea is that curl_multi_socket_action() calls a given callback with + information about what socket to wait for what action on, and the callback + only gets called if the status of that socket has changed. + + We also added a timer callback that makes libcurl call the application when + the timeout value changes, and you set that with curl_multi_setopt() and the + CURLMOPT_TIMERFUNCTION option. To get this to work, Internally, there's an + added a struct to each easy handle in which we store an "expire time" (if + any). The structs are then "splay sorted" so that we can add and remove + times from the linked list and yet somewhat swiftly figure out both how long + time there is until the next nearest timer expires and which timer (handle) + we should take care of now. Of course, the upside of all this is that we get + a curl_multi_timeout() that should also work with old-style applications + that use curl_multi_perform(). + + We created an internal "socket to easy handles" hash table that given + a socket (file descriptor) return the easy handle that waits for action on + that socket. This hash is made using the already existing hash code + (previously only used for the DNS cache). + + To make libcurl able to report plain sockets in the socket callback, we had + to re-organize the internals of the curl_multi_fdset() etc so that the + conversion from sockets to fd_sets for that function is only done in the + last step before the data is returned. I also had to extend c-ares to get a + function that can return plain sockets, as that library too returned only + fd_sets and that is no longer good enough. The changes done to c-ares are + available in c-ares 1.3.1 and later. + + We have done a test runs with up to 9000 connections (with a single active + one). The curl_multi_socket_action() invoke then takes less than 10 + microseconds in average (using the read-only-1-byte-at-a-time hack). We are + now below the 60 microseconds "per socket action" goal (the extra 50 is the + time libevent needs). + +Documentation + + http://curl.haxx.se/libcurl/c/curl_multi_socket_action.html + http://curl.haxx.se/libcurl/c/curl_multi_timeout.html + http://curl.haxx.se/libcurl/c/curl_multi_setopt.html diff --git a/lib/README.pingpong b/lib/README.pingpong new file mode 100644 index 000000000..69ba9aadb --- /dev/null +++ b/lib/README.pingpong @@ -0,0 +1,30 @@ +Date: December 5, 2009 + +Pingpong +======== + + Pingpong is just my (Daniel's) jestful collective name on the protocols that + share a very similar kind of back-and-forth procedure with command and + responses to and from the server. FTP was previously the only protocol in + that family that libcurl supported, but when POP3, IMAP and SMTP joined the + team I moved some of the internals into a separate pingpong module to be + easier to get used by all these protocols to reduce code duplication and ease + code re-use between these protocols. + +FTP + + In 7.20.0 we converted code to use the new pingpong code from previously + having been all "native" FTP code. + +POP3 + + There's no support in the documented URL format to specify the exact mail to + get, but we support that as the path specified in the URL. + +IMAP + +SMTP + + There's no official URL syntax defined for SMTP, but we use only the generic + one and we provide two additional libcurl options to specify receivers and + sender of the actual mail. diff --git a/lib/README.pipelining b/lib/README.pipelining new file mode 100644 index 000000000..e5bf6ec33 --- /dev/null +++ b/lib/README.pipelining @@ -0,0 +1,44 @@ +HTTP Pipelining with libcurl +============================ + +Background + +Since pipelining implies that one or more requests are sent to a server before +the previous response(s) have been received, we only support it for multi +interface use. + +Considerations + +When using the multi interface, you create one easy handle for each transfer. +Bascially any number of handles can be created, added and used with the multi +interface - simultaneously. It is an interface designed to allow many +simultaneous transfers while still using a single thread. Pipelining does not +change any of these details. + +API + +We've added a new option to curl_multi_setopt() called CURLMOPT_PIPELINING +that enables "attempted pipelining" and then all easy handles used on that +handle will attempt to use an existing pipeline. + +Details + +- A pipeline is only created if a previous connection exists to the same IP + address that the new request is being made to use. + +- Pipelines are only supported for HTTP(S) as no other currently supported + protocol has features resemembling this, but we still name this feature + plain 'pipelining' to possibly one day support it for other protocols as + well. + +- HTTP Pipelining is for GET and HEAD requests only. + +- When a pipeline is in use, we must take precautions so that when used easy + handles (i.e those who still wait for a response) are removed from the multi + handle, we must deal with the outstanding response nicely. + +- Explicitly asking for pipelining handle X and handle Y won't be supported. + It isn't easy for an app to do this association. The lib should probably + still resolve the second one properly to make sure that they actually _can_ + be considered for pipelining. Also, asking for explicit pipelining on handle + X may be tricky when handle X get a closed connection. diff --git a/lib/amigaos.c b/lib/amigaos.c index e3ff85f98..34f95e9b5 100644 --- a/lib/amigaos.c +++ b/lib/amigaos.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -71,7 +71,7 @@ bool Curl_amiga_init() } #ifdef __libnix__ -ADD2EXIT(Curl_amiga_cleanup, -50); +ADD2EXIT(Curl_amiga_cleanup,-50); #endif #endif /* __AMIGA__ && ! __ixemul__ */ diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 98ecdfd71..4404b6c98 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -68,7 +68,9 @@ #include "connect.h" #include "select.h" #include "progress.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) @@ -164,7 +166,7 @@ void Curl_resolver_cleanup(void *resolver) int Curl_resolver_duphandle(void **to, void *from) { /* Clone the ares channel for the new handle */ - if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from)) + if(ARES_SUCCESS != ares_dup((ares_channel*)to,(ares_channel)from)) return CURLE_FAILED_INIT; return CURLE_OK; } @@ -186,7 +188,8 @@ void Curl_resolver_cancel(struct connectdata *conn) */ static void destroy_async_data (struct Curl_async *async) { - free(async->hostname); + if(async->hostname) + free(async->hostname); if(async->os_specific) { struct ResolverResults *res = (struct ResolverResults *)async->os_specific; @@ -385,7 +388,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, timeout_ms = 1000; waitperform(conn, timeout_ms); - Curl_resolver_is_resolved(conn, &temp_entry); + Curl_resolver_is_resolved(conn,&temp_entry); if(conn->async.done) break; @@ -533,15 +536,15 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, bufp = strdup(hostname); if(bufp) { struct ResolverResults *res = NULL; - free(conn->async.hostname); + Curl_safefree(conn->async.hostname); conn->async.hostname = bufp; conn->async.port = port; conn->async.done = FALSE; /* not done */ conn->async.status = 0; /* clear */ conn->async.dns = NULL; /* clear */ - res = calloc(sizeof(struct ResolverResults), 1); + res = calloc(sizeof(struct ResolverResults),1); if(!res) { - free(conn->async.hostname); + Curl_safefree(conn->async.hostname); conn->async.hostname = NULL; return NULL; } diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index bd47d5ad5..80b5e7851 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -69,9 +69,11 @@ #include "inet_ntop.h" #include "curl_threads.h" #include "connect.h" -#include "curl_printf.h" -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -190,12 +192,13 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd) free(tsd->mtx); } - free(tsd->hostname); + if(tsd->hostname) + free(tsd->hostname); if(tsd->res) Curl_freeaddrinfo(tsd->res); - memset(tsd, 0, sizeof(*tsd)); + memset(tsd,0,sizeof(*tsd)); } /* Initialize resolver thread synchronization data */ @@ -363,7 +366,9 @@ static void destroy_async_data (struct Curl_async *async) } async->os_specific = NULL; - free(async->hostname); + if(async->hostname) + free(async->hostname); + async->hostname = NULL; } @@ -393,7 +398,7 @@ static bool init_resolve_thread (struct connectdata *conn, if(!init_thread_sync_data(td, hostname, port, hints)) goto err_exit; - free(conn->async.hostname); + Curl_safefree(conn->async.hostname); conn->async.hostname = strdup(hostname); if(!conn->async.hostname) goto err_exit; diff --git a/lib/base64.c b/lib/base64.c index 6b87eed40..6b1eb7c9c 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,14 +23,17 @@ /* Base64 encoding/decoding */ #include "curl_setup.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "urldata.h" /* for the SessionHandle definition */ #include "warnless.h" #include "curl_base64.h" +#include "curl_memory.h" #include "non-ascii.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* include memdebug.h last */ #include "memdebug.h" /* ---- Base64 Encoding/Decoding Table --- */ @@ -149,7 +152,7 @@ CURLcode Curl_base64_decode(const char *src, for(i = 0; i < numQuantums; i++) { size_t result = decodeQuantum(pos, src); if(!result) { - free(newstr); + Curl_safefree(newstr); return CURLE_BAD_CONTENT_ENCODING; } @@ -252,7 +255,8 @@ static CURLcode base64_encode(const char *table64, *output = '\0'; *outptr = base64data; /* return pointer to new data, allocated memory */ - free(convbuf); + if(convbuf) + free(convbuf); *outlen = strlen(base64data); /* return the length of the new data */ diff --git a/lib/bundles.c b/lib/bundles.c new file mode 100644 index 000000000..aadf02656 --- /dev/null +++ b/lib/bundles.c @@ -0,0 +1,110 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se> + * Copyright (C) 2012, 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 http://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" + +#include <curl/curl.h> + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "bundles.h" +#include "sendf.h" +#include "rawstr.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void conn_llist_dtor(void *user, void *element) +{ + struct connectdata *data = element; + (void)user; + + data->bundle = NULL; +} + +CURLcode Curl_bundle_create(struct SessionHandle *data, + struct connectbundle **cb_ptr) +{ + (void)data; + DEBUGASSERT(*cb_ptr == NULL); + *cb_ptr = malloc(sizeof(struct connectbundle)); + if(!*cb_ptr) + return CURLE_OUT_OF_MEMORY; + + (*cb_ptr)->num_connections = 0; + (*cb_ptr)->server_supports_pipelining = FALSE; + + (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor); + if(!(*cb_ptr)->conn_list) { + Curl_safefree(*cb_ptr); + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} + +void Curl_bundle_destroy(struct connectbundle *cb_ptr) +{ + if(!cb_ptr) + return; + + if(cb_ptr->conn_list) { + Curl_llist_destroy(cb_ptr->conn_list, NULL); + cb_ptr->conn_list = NULL; + } + Curl_safefree(cb_ptr); +} + +/* Add a connection to a bundle */ +CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn)) + return CURLE_OUT_OF_MEMORY; + + conn->bundle = cb_ptr; + + cb_ptr->num_connections++; + return CURLE_OK; +} + +/* Remove a connection from a bundle */ +int Curl_bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = cb_ptr->conn_list->head; + while(curr) { + if(curr->ptr == conn) { + Curl_llist_remove(cb_ptr->conn_list, curr, NULL); + cb_ptr->num_connections--; + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; + } + return 0; +} diff --git a/lib/curl_des.h b/lib/bundles.h index b855db4c1..3816c4065 100644 --- a/lib/curl_des.h +++ b/lib/bundles.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_DES_H -#define HEADER_CURL_DES_H +#ifndef HEADER_CURL_BUNDLES_H +#define HEADER_CURL_BUNDLES_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se> * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,13 +22,24 @@ * ***************************************************************************/ -#include "curl_setup.h" +struct connectbundle { + bool server_supports_pipelining; /* TRUE if server supports pipelining, + set after first response */ + size_t num_connections; /* Number of connections in the bundle */ + struct curl_llist *conn_list; /* The connectdata members of the bundle */ +}; -#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL)) +CURLcode Curl_bundle_create(struct SessionHandle *data, + struct connectbundle **cb_ptr); -/* Applies odd parity to the given byte array */ -void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); +void Curl_bundle_destroy(struct connectbundle *cb_ptr); -#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */ +CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn); + +int Curl_bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn); + + +#endif /* HEADER_CURL_BUNDLES_H */ -#endif /* HEADER_CURL_DES_H */ diff --git a/lib/checksrc.pl b/lib/checksrc.pl index 8fad2cfcb..f561492a7 100755 --- a/lib/checksrc.pl +++ b/lib/checksrc.pl @@ -6,7 +6,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 2011 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -26,32 +26,13 @@ my $indent = 2; my $warnings; my $errors; -my $supressed; # whitelisted problems my $file; my $dir="."; my $wlist; -my $windows_os = $^O eq 'MSWin32' || $^O eq 'msys' || $^O eq 'cygwin'; - -my %whitelist; - -sub readwhitelist { - open(W, "<$dir/checksrc.whitelist"); - my @all=<W>; - for(@all) { - $windows_os ? $_ =~ s/\r?\n$// : chomp; - $whitelist{$_}=1; - } - close(W); -} sub checkwarn { my ($num, $col, $file, $line, $msg, $error) = @_; - if($whitelist{$line}) { - $supressed++; - return; - } - my $w=$error?"error":"warning"; if($w) { @@ -97,8 +78,6 @@ if(!$file) { exit; } -readwhitelist(); - do { if("$wlist" !~ / $file /) { my $fullname = $file; @@ -121,7 +100,7 @@ sub scanfile { my $copyright=0; while(<R>) { - $windows_os ? $_ =~ s/\r?\n$// : chomp; + chomp; my $l = $_; my $column = 0; @@ -165,49 +144,6 @@ sub scanfile { } } - # check for "return(" without space - if($l =~ /^(.*)return\(/) { - if($1 =~ / *\#/) { - # this is a #if, treat it differently - } - else { - checkwarn($line, length($1)+6, $file, $l, - "return without space before paren"); - } - } - - # check for comma without space - if($l =~ /^(.*),[^ \n]/) { - my $pref=$1; - my $ign=0; - if($pref =~ / *\#/) { - # this is a #if, treat it differently - $ign=1; - } - elsif($pref =~ /\/\*/) { - # this is a comment - $ign=1; - } - elsif($pref =~ /[\"\']/) { - $ign = 1; - # There is a quote here, figure out whether the comma is - # within a string or '' or not. - if($pref =~ /\"/) { - # withing a string - } - elsif($pref =~ /\'$/) { - # a single letter - } - else { - $ign = 0; - } - } - if(!$ign) { - checkwarn($line, length($pref)+1, $file, $l, - "comma without following space"); - } - } - # check for "} else" if($l =~ /^(.*)\} *else/) { checkwarn($line, length($1), $file, $l, "else after closing brace on same line"); @@ -217,26 +153,12 @@ sub scanfile { checkwarn($line, length($1)+1, $file, $l, "missing space after close paren"); } - # check for space before the semicolon last in a line - if($l =~ /^(.*[^ ].*) ;$/) { - checkwarn($line, length($1), $file, $l, "space before last semicolon"); - } - # scan for use of banned functions if($l =~ /^(.*\W)(sprintf|vsprintf|strcat|strncat|gets)\s*\(/) { checkwarn($line, length($1), $file, $l, "use of $2 is banned"); } - # scan for use of non-binary fopen without the macro - if($l =~ /^(.*\W)fopen\s*\([^"]*\"([^"]*)/) { - my $mode = $2; - if($mode !~ /b/) { - checkwarn($line, length($1), $file, $l, - "use of non-binary fopen without FOPEN_* macro"); - } - } - # check for open brace first on line but not first column # only alert if previous line ended with a close paren and wasn't a cpp # line diff --git a/lib/checksrc.whitelist b/lib/checksrc.whitelist deleted file mode 100644 index e261b9da1..000000000 --- a/lib/checksrc.whitelist +++ /dev/null @@ -1,10 +0,0 @@ - 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) - 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) - 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). - 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) - * no_proxy=domain1.dom,host.domain2.dom - Default values are (0,0) initialized by calloc. - file = fopen(name, "r"); /* VMS */ - return fopen(file, "r"); /* VMS */ - return fopen(file, "r", "rfm=stmlf", "ctx=stm"); - curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", diff --git a/lib/config-amigaos.h b/lib/config-amigaos.h index 04b18b744..76d887755 100644 --- a/lib/config-amigaos.h +++ b/lib/config-amigaos.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, 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 @@ -93,6 +93,7 @@ #define USE_MANUAL 1 #define USE_OPENSSL 1 +#define USE_SSLEAY 1 #define CURL_DISABLE_LDAP 1 #define OS "AmigaOS" diff --git a/lib/config-dos.h b/lib/config-dos.h index 288bd1db3..dd5b06db4 100644 --- a/lib/config-dos.h +++ b/lib/config-dos.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, 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 @@ -132,11 +132,12 @@ #define HAVE_LIBZ 1 #endif -/* USE_OPENSSL on cmd-line */ -#ifdef USE_OPENSSL +/* USE_SSLEAY on cmd-line */ +#ifdef USE_SSLEAY #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 #define HAVE_OPENSSL_ENGINE_H 1 #define OPENSSL_NO_KRB5 1 + #define USE_OPENSSL 1 #endif /* to disable LDAP */ @@ -162,6 +163,11 @@ #define HAVE_TERMIOS_H 1 #define HAVE_VARIADIC_MACROS_GCC 1 + /* Because djgpp <= 2.03 doesn't have snprintf() etc. */ + #if (DJGPP_MINOR < 4) + #define _MPRINTF_REPLACE + #endif + #elif defined(__WATCOMC__) #define HAVE_STRCASECMP 1 diff --git a/lib/config-mac.h b/lib/config-mac.h index ee7a6590c..d89c38515 100644 --- a/lib/config-mac.h +++ b/lib/config-mac.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, 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 @@ -70,6 +70,7 @@ #define HAVE_SIG_ATOMIC_T 1 #ifdef MACOS_SSL_SUPPORT +# define USE_SSLEAY 1 # define USE_OPENSSL 1 #endif diff --git a/lib/config-symbian.h b/lib/config-symbian.h index a40e3d8e0..f7eaab92d 100644 --- a/lib/config-symbian.h +++ b/lib/config-symbian.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -69,7 +69,7 @@ /* #undef CURL_EXTERN_SYMBOL */ /* Use Windows LDAP implementation */ -/* #undef USE_WIN32_LDAP */ +/* #undef CURL_LDAP_WIN */ /* your Entropy Gathering Daemon socket pathname */ /* #undef EGD_SOCKET */ @@ -808,4 +808,10 @@ #define HAVE_ZLIB_H 1 #endif +/* Enable appropriate definitions only when OpenSSL support is enabled */ +#ifdef USE_SSLEAY +/* if OpenSSL is in use */ +#define USE_OPENSSL +#endif + #endif /* HEADER_CURL_CONFIG_SYMBIAN_H */ diff --git a/lib/config-tpf.h b/lib/config-tpf.h index d6b8cc2f2..6ff701a9f 100644 --- a/lib/config-tpf.h +++ b/lib/config-tpf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -646,7 +646,7 @@ /* #undef USE_OPENSSL */ /* if SSL is enabled */ -/* #undef USE_OPENSSL */ +/* #undef USE_SSLEAY */ /* to enable SSPI support */ /* #undef USE_WINDOWS_SSPI */ diff --git a/lib/config-vxworks.h b/lib/config-vxworks.h index d889efcd8..05220b581 100644 --- a/lib/config-vxworks.h +++ b/lib/config-vxworks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -75,7 +75,7 @@ /* #undef CURL_EXTERN_SYMBOL */ /* Use Windows LDAP implementation */ -/* #undef USE_WIN32_LDAP */ +/* #undef CURL_LDAP_WIN */ /* your Entropy Gathering Daemon socket pathname */ /* #undef EGD_SOCKET */ @@ -883,6 +883,9 @@ /* if OpenSSL is in use */ #define USE_OPENSSL 1 +/* if SSL is enabled */ +#define USE_SSLEAY 1 + /* Define to 1 if you are building a Windows target without large file support. */ /* #undef USE_WIN32_LARGE_FILES */ diff --git a/lib/config-win32.h b/lib/config-win32.h index e9a371212..744e02271 100644 --- a/lib/config-win32.h +++ b/lib/config-win32.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -678,30 +678,30 @@ Vista /* ---------------------------------------------------------------- */ #if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK) -#undef USE_WIN32_LDAP +#undef CURL_LDAP_WIN #define HAVE_LDAP_SSL_H 1 #define HAVE_LDAP_URL_PARSE 1 #elif defined(CURL_HAS_OPENLDAP_LDAPSDK) -#undef USE_WIN32_LDAP +#undef CURL_LDAP_WIN #define HAVE_LDAP_URL_PARSE 1 #else #undef HAVE_LDAP_URL_PARSE -#define USE_WIN32_LDAP 1 +#define CURL_LDAP_WIN 1 #endif -#if defined(__WATCOMC__) && defined(USE_WIN32_LDAP) +#if defined(__WATCOMC__) && defined(CURL_LDAP_WIN) #if __WATCOMC__ < 1280 #define WINBERAPI __declspec(cdecl) #define WINLDAPAPI __declspec(cdecl) #endif #endif -#if defined(__POCC__) && defined(USE_WIN32_LDAP) +#if defined(__POCC__) && defined(CURL_LDAP_WIN) # define CURL_DISABLE_LDAP 1 #endif /* Define to use the Windows crypto library. */ -#if !defined(USE_OPENSSL) && !defined(USE_NSS) +#if !defined(USE_SSLEAY) && !defined(USE_NSS) #define USE_WIN32_CRYPTO #endif diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h index a723fd188..a8ab0d34e 100644 --- a/lib/config-win32ce.h +++ b/lib/config-win32ce.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, 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,7 +409,7 @@ /* LDAP SUPPORT */ /* ---------------------------------------------------------------- */ -#define USE_WIN32_LDAP 1 +#define CURL_LDAP_WIN 1 #undef HAVE_LDAP_URL_PARSE /* ---------------------------------------------------------------- */ @@ -443,6 +443,6 @@ #define ENOMEM 2 #define EAGAIN 3 -extern int stat(const char *path, struct stat *buffer); +extern int stat(const char *path,struct stat *buffer ); #endif /* HEADER_CURL_CONFIG_WIN32CE_H */ diff --git a/lib/conncache.c b/lib/conncache.c index c712ed7b9..fcfb15015 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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,134 +31,66 @@ #include "multiif.h" #include "sendf.h" #include "rawstr.h" +#include "bundles.h" #include "conncache.h" -#include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" -static void conn_llist_dtor(void *user, void *element) -{ - struct connectdata *data = element; - (void)user; - - data->bundle = NULL; -} - -static CURLcode bundle_create(struct SessionHandle *data, - struct connectbundle **cb_ptr) -{ - (void)data; - DEBUGASSERT(*cb_ptr == NULL); - *cb_ptr = malloc(sizeof(struct connectbundle)); - if(!*cb_ptr) - return CURLE_OUT_OF_MEMORY; - - (*cb_ptr)->num_connections = 0; - (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; - - (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor); - if(!(*cb_ptr)->conn_list) { - Curl_safefree(*cb_ptr); - return CURLE_OUT_OF_MEMORY; - } - return CURLE_OK; -} - -static void bundle_destroy(struct connectbundle *cb_ptr) +static void free_bundle_hash_entry(void *freethis) { - if(!cb_ptr) - return; + struct connectbundle *b = (struct connectbundle *) freethis; - if(cb_ptr->conn_list) { - Curl_llist_destroy(cb_ptr->conn_list, NULL); - cb_ptr->conn_list = NULL; - } - free(cb_ptr); + Curl_bundle_destroy(b); } -/* Add a connection to a bundle */ -static CURLcode bundle_add_conn(struct connectbundle *cb_ptr, - struct connectdata *conn) +struct conncache *Curl_conncache_init(int size) { - if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn)) - return CURLE_OUT_OF_MEMORY; - - conn->bundle = cb_ptr; + struct conncache *connc; - cb_ptr->num_connections++; - return CURLE_OK; -} + connc = calloc(1, sizeof(struct conncache)); + if(!connc) + return NULL; -/* Remove a connection from a bundle */ -static int bundle_remove_conn(struct connectbundle *cb_ptr, - struct connectdata *conn) -{ - struct curl_llist_element *curr; + connc->hash = Curl_hash_alloc(size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); - curr = cb_ptr->conn_list->head; - while(curr) { - if(curr->ptr == conn) { - Curl_llist_remove(cb_ptr->conn_list, curr, NULL); - cb_ptr->num_connections--; - conn->bundle = NULL; - return 1; /* we removed a handle */ - } - curr = curr->next; + if(!connc->hash) { + free(connc); + return NULL; } - return 0; -} -static void free_bundle_hash_entry(void *freethis) -{ - struct connectbundle *b = (struct connectbundle *) freethis; - - bundle_destroy(b); -} - -int Curl_conncache_init(struct conncache *connc, int size) -{ - return Curl_hash_init(&connc->hash, size, Curl_hash_str, - Curl_str_key_compare, free_bundle_hash_entry); + return connc; } void Curl_conncache_destroy(struct conncache *connc) { - if(connc) - Curl_hash_destroy(&connc->hash); -} - -/* returns an allocated key to find a bundle for this connection */ -static char *hashkey(struct connectdata *conn) -{ - return aprintf("%s:%d", - conn->bits.proxy?conn->proxy.name:conn->host.name, - conn->localport); + if(connc) { + Curl_hash_destroy(connc->hash); + connc->hash = NULL; + free(connc); + } } -/* Look up the bundle with all the connections to the same host this - connectdata struct is setup to use. */ -struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, - struct conncache *connc) +struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc, + char *hostname) { struct connectbundle *bundle = NULL; - if(connc) { - char *key = hashkey(conn); - if(key) { - bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); - free(key); - } - } + + if(connc) + bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1); return bundle; } static bool conncache_add_bundle(struct conncache *connc, - char *key, + char *hostname, struct connectbundle *bundle) { - void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); + void *p; + + p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle); return p?TRUE:FALSE; } @@ -172,14 +104,14 @@ static void conncache_remove_bundle(struct conncache *connc, if(!connc) return; - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { if(he->ptr == bundle) { /* The bundle is destroyed by the hash destructor function, free_bundle_hash_entry() */ - Curl_hash_delete(&connc->hash, he->key, he->key_len); + Curl_hash_delete(connc->hash, he->key, he->key_len); return; } @@ -195,31 +127,22 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectbundle *new_bundle = NULL; struct SessionHandle *data = conn->data; - bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); + bundle = Curl_conncache_find_bundle(data->state.conn_cache, + conn->host.name); if(!bundle) { - char *key; - int rc; - - result = bundle_create(data, &new_bundle); + result = Curl_bundle_create(data, &new_bundle); if(result) return result; - key = hashkey(conn); - if(!key) { - bundle_destroy(new_bundle); - return CURLE_OUT_OF_MEMORY; - } - - rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); - free(key); - if(!rc) { - bundle_destroy(new_bundle); + if(!conncache_add_bundle(data->state.conn_cache, + conn->host.name, new_bundle)) { + Curl_bundle_destroy(new_bundle); return CURLE_OUT_OF_MEMORY; } bundle = new_bundle; } - result = bundle_add_conn(bundle, conn); + result = Curl_bundle_add_conn(bundle, conn); if(result) { if(new_bundle) conncache_remove_bundle(data->state.conn_cache, new_bundle); @@ -244,7 +167,7 @@ void Curl_conncache_remove_conn(struct conncache *connc, /* The bundle pointer can be NULL, since this function can be called due to a failed connection attempt, before being added to a bundle */ if(bundle) { - bundle_remove_conn(bundle, conn); + Curl_bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) { conncache_remove_bundle(connc, bundle); } @@ -276,7 +199,7 @@ void Curl_conncache_foreach(struct conncache *connc, if(!connc) return; - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { @@ -307,7 +230,7 @@ Curl_conncache_find_first_connection(struct conncache *connc) struct curl_hash_element *he; struct connectbundle *bundle; - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { diff --git a/lib/conncache.h b/lib/conncache.h index 59181bf3d..d793f2482 100644 --- a/lib/conncache.h +++ b/lib/conncache.h @@ -7,7 +7,6 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se> * * This software is licensed as described in the file COPYING, which @@ -24,30 +23,18 @@ ***************************************************************************/ struct conncache { - struct curl_hash hash; + struct curl_hash *hash; size_t num_connections; long next_connection_id; struct timeval last_cleanup; }; -#define BUNDLE_NO_MULTIUSE -1 -#define BUNDLE_UNKNOWN 0 /* initial value */ -#define BUNDLE_PIPELINING 1 -#define BUNDLE_MULTIPLEX 2 - -struct connectbundle { - int multiuse; /* supports multi-use */ - size_t num_connections; /* Number of connections in the bundle */ - struct curl_llist *conn_list; /* The connectdata members of the bundle */ -}; - -int Curl_conncache_init(struct conncache *, int size); +struct conncache *Curl_conncache_init(int size); void Curl_conncache_destroy(struct conncache *connc); -/* return the correct bundle, to a host or a proxy */ -struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, - struct conncache *connc); +struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc, + char *hostname); CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectdata *conn); diff --git a/lib/connect.c b/lib/connect.c index 18ac32c32..5a60d14ab 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -56,12 +56,15 @@ #include <inet.h> #endif -#include "curl_printf.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "urldata.h" #include "sendf.h" #include "if2ip.h" #include "strerror.h" #include "connect.h" +#include "curl_memory.h" #include "select.h" #include "url.h" /* for Curl_safefree() */ #include "multiif.h" @@ -74,8 +77,7 @@ #include "conncache.h" #include "multihandle.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #ifdef __SYMBIAN32__ @@ -540,7 +542,6 @@ static CURLcode trynextip(struct connectdata *conn, int sockindex, int tempindex) { - const int other = tempindex ^ 1; CURLcode result = CURLE_COULDNT_CONNECT; /* First clean up after the failed socket. @@ -559,21 +560,20 @@ static CURLcode trynextip(struct connectdata *conn, family = conn->tempaddr[tempindex]->ai_family; ai = conn->tempaddr[tempindex]->ai_next; } -#ifdef ENABLE_IPV6 else if(conn->tempaddr[0]) { /* happy eyeballs - try the other protocol family */ int firstfamily = conn->tempaddr[0]->ai_family; +#ifdef ENABLE_IPV6 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET; +#else + family = firstfamily; +#endif ai = conn->tempaddr[0]->ai_next; } -#endif while(ai) { - if(conn->tempaddr[other]) { - /* we can safely skip addresses of the other protocol family */ - while(ai && ai->ai_family != family) - ai = ai->ai_next; - } + while(ai && ai->ai_family != family) + ai = ai->ai_next; if(ai) { result = singleipconnect(conn, ai, &conn->tempsock[tempindex]); @@ -749,7 +749,6 @@ CURLcode Curl_is_connected(struct connectdata *conn, } for(i=0; i<2; i++) { - const int other = i ^ 1; if(conn->tempsock[i] == CURL_SOCKET_BAD) continue; @@ -779,6 +778,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, else if(rc == CURL_CSELECT_OUT) { if(verifyconnect(conn->tempsock[i], &error)) { /* we are connected with TCP, awesome! */ + int other = i ^ 1; /* use this socket from now on */ conn->sock[sockindex] = conn->tempsock[i]; @@ -820,7 +820,6 @@ CURLcode Curl_is_connected(struct connectdata *conn, data->state.os_errno = error; SET_SOCKERRNO(error); if(conn->tempaddr[i]) { - CURLcode status; char ipaddress[MAX_IPADR_LEN]; Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); infof(data, "connect to %s port %ld failed: %s\n", @@ -829,11 +828,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? allow : allow / 2; - status = trynextip(conn, sockindex, i); - if(status != CURLE_COULDNT_CONNECT - || conn->tempsock[other] == CURL_SOCKET_BAD) - /* the last attempt failed and no other sockets remain open */ - result = status; + result = trynextip(conn, sockindex, i); } } } @@ -883,7 +878,7 @@ static void tcpnodelay(struct connectdata *conn, infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, SOCKERRNO)); else - infof(data, "TCP_NODELAY set\n"); + infof(data,"TCP_NODELAY set\n"); #else (void)conn; (void)sockfd; @@ -949,21 +944,16 @@ void Curl_sndbufset(curl_socket_t sockfd) detectOsState = DETECT_OS_VISTA_OR_LATER; } #else - ULONGLONG cm; + ULONGLONG majorVersionMask; OSVERSIONINFOEX osver; memset(&osver, 0, sizeof(osver)); osver.dwOSVersionInfoSize = sizeof(osver); osver.dwMajorVersion = majorVersion; + majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, + VER_GREATER_EQUAL); - cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); - - if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), - cm)) + if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask)) detectOsState = DETECT_OS_VISTA_OR_LATER; else detectOsState = DETECT_OS_PREVISTA; @@ -1026,12 +1016,8 @@ static CURLcode singleipconnect(struct connectdata *conn, } infof(data, " Trying %s...\n", ipaddress); -#ifdef ENABLE_IPV6 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && - addr.socktype == SOCK_STREAM; -#else - is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; -#endif + addr.socktype == SOCK_STREAM; if(is_tcp && data->set.tcp_nodelay) tcpnodelay(conn, sockfd); @@ -1057,11 +1043,7 @@ static CURLcode singleipconnect(struct connectdata *conn, } /* possibly bind the local end to an IP, interface or port */ - if(addr.family == AF_INET -#ifdef ENABLE_IPV6 - || addr.family == AF_INET6 -#endif - ) { + if(addr.family == AF_INET || addr.family == AF_INET6) { result = bindlocal(conn, sockfd, addr.family, Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); if(result) { @@ -1116,7 +1098,7 @@ static CURLcode singleipconnect(struct connectdata *conn, default: /* unknown error, fallthrough and try another address! */ infof(data, "Immediate connect fail for %s: %s\n", - ipaddress, Curl_strerror(conn, error)); + ipaddress, Curl_strerror(conn,error)); data->state.os_errno = error; /* connect failed */ @@ -1171,11 +1153,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ conn->tempaddr[0] = conn->tempaddr[0]->ai_next; } - if(conn->tempsock[0] == CURL_SOCKET_BAD) { - if(!result) - result = CURLE_COULDNT_CONNECT; + if(conn->tempsock[0] == CURL_SOCKET_BAD) return result; - } data->info.numconnects++; /* to track the number of connections made */ @@ -1210,20 +1189,15 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, DEBUGASSERT(data); - /* this works for an easy handle: - * - that has been used for curl_easy_perform() - * - that is associated with a multi handle, and whose connection - * was detached with CURLOPT_CONNECT_ONLY - */ - if(data->state.lastconnect && (data->multi_easy || data->multi)) { + /* this only works for an easy handle that has been used for + curl_easy_perform()! */ + if(data->state.lastconnect && data->multi_easy) { struct connectdata *c = data->state.lastconnect; struct connfind find; find.tofind = data->state.lastconnect; find.found = FALSE; - Curl_conncache_foreach(data->multi_easy? - &data->multi_easy->conn_cache: - &data->multi->conn_cache, &find, conn_is_conn); + Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn); if(!find.found) { data->state.lastconnect = NULL; @@ -1274,10 +1248,8 @@ int Curl_closesocket(struct connectdata *conn, accept, then we MUST NOT call the callback but clear the accepted status */ conn->sock_accepted[SECONDARYSOCKET] = FALSE; - else { - Curl_multi_closed(conn, sock); + else return conn->fclosesocket(conn->closesocket_client, sock); - } } if(conn) @@ -1372,12 +1344,11 @@ void Curl_conncontrol(struct connectdata *conn, bool closeit, #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) reason; #endif - if(closeit != conn->bits.close) { - infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", - reason); - conn->bits.close = closeit; /* the only place in the source code that - should assign this bit */ - } + infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", + reason); + + conn->bits.close = closeit; /* the only place in the source code that should + assign this bit */ } #endif diff --git a/lib/cookie.c b/lib/cookie.c index 22730cff4..0b9c8d337 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -84,33 +84,44 @@ Example set of cookies: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) -#include "curl_printf.h" +#define _MPRINTF_REPLACE +#include <curl/mprintf.h> + #include "urldata.h" #include "cookie.h" #include "strequal.h" #include "strtok.h" #include "sendf.h" #include "slist.h" +#include "curl_memory.h" #include "share.h" #include "strtoofft.h" #include "rawstr.h" #include "curl_memrchr.h" #include "inet_pton.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" static void freecookie(struct Cookie *co) { - free(co->expirestr); - free(co->domain); - free(co->path); - free(co->spath); - free(co->name); - free(co->value); - free(co->maxage); - free(co->version); + if(co->expirestr) + free(co->expirestr); + if(co->domain) + free(co->domain); + if(co->path) + free(co->path); + if(co->spath) + free(co->spath); + if(co->name) + free(co->name); + if(co->value) + free(co->value); + if(co->maxage) + free(co->maxage); + if(co->version) + free(co->version); + free(co); } @@ -225,14 +236,11 @@ static char *sanitize_cookie_path(const char *cookie_path) return NULL; /* some stupid site sends path attribute with '"'. */ - len = strlen(new_path); if(new_path[0] == '\"') { - memmove((void *)new_path, (const void *)(new_path + 1), len); - len--; + memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path)); } - if(len && (new_path[len - 1] == '\"')) { - new_path[len - 1] = 0x0; - len--; + if(new_path[strlen(new_path) - 1] == '\"') { + new_path[strlen(new_path) - 1] = 0x0; } /* RFC6265 5.2.4 The Path Attribute */ @@ -244,7 +252,8 @@ static char *sanitize_cookie_path(const char *cookie_path) } /* convert /hoge/ to /hoge */ - if(len && new_path[len - 1] == '/') { + len = strlen(new_path); + if(1 < len && new_path[len - 1] == '/') { new_path[len - 1] = 0x0; } @@ -289,7 +298,8 @@ void Curl_cookie_loadfiles(struct SessionHandle *data) */ static void strstore(char **str, const char *newstr) { - free(*str); + if(*str) + free(*str); *str = strdup(newstr); } @@ -409,7 +419,7 @@ Curl_cookie_add(struct SessionHandle *data, do { /* we have a <what>=<this> pair or a stand-alone word here */ name[0]=what[0]=0; /* init the buffers */ - if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =] =%" + if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =]=%" MAX_COOKIE_LINE_TXT "[^;\r\n]", name, what)) { /* Use strstore() below to properly deal with received cookie @@ -824,13 +834,21 @@ Curl_cookie_add(struct SessionHandle *data, /* then free all the old pointers */ free(clist->name); - free(clist->value); - free(clist->domain); - free(clist->path); - free(clist->spath); - free(clist->expirestr); - free(clist->version); - free(clist->maxage); + if(clist->value) + free(clist->value); + if(clist->domain) + free(clist->domain); + if(clist->path) + free(clist->path); + if(clist->spath) + free(clist->spath); + if(clist->expirestr) + free(clist->expirestr); + + if(clist->version) + free(clist->version); + if(clist->maxage) + free(clist->maxage); *clist = *co; /* then store all the new data */ @@ -914,7 +932,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, fp = NULL; } else - fp = file?fopen(file, FOPEN_READTEXT):NULL; + fp = file?fopen(file, "r"):NULL; c->newsession = newsession; /* new session? */ @@ -951,7 +969,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, return c; fail: - free(line); + Curl_safefree(line); if(!inc) /* Only clean up if we allocated it here, as the original could still be in * use by a share handle */ @@ -1198,7 +1216,8 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies) void Curl_cookie_cleanup(struct CookieInfo *c) { if(c) { - free(c->filename); + if(c->filename) + free(c->filename); Curl_cookie_freelist(c->cookies, TRUE); free(c); /* free the base struct as well */ } @@ -1262,7 +1281,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) use_stdout=TRUE; } else { - out = fopen(dumphere, FOPEN_WRITETEXT); + out = fopen(dumphere, "w"); if(!out) return 1; /* failure */ } @@ -1274,10 +1293,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) "# http://curl.haxx.se/docs/http-cookies.html\n" "# This file was generated by libcurl! Edit at your own risk.\n\n", out); + co = c->cookies; - for(co = c->cookies; co; co = co->next) { - if(!co->domain) - continue; + while(co) { format_ptr = get_netscape_format(co); if(format_ptr == NULL) { fprintf(out, "#\n# Fatal libcurl error\n"); @@ -1287,6 +1305,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) } fprintf(out, "%s\n", format_ptr); free(format_ptr); + co=co->next; } } @@ -1307,9 +1326,10 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data) (data->cookies->numcookies == 0)) return NULL; - for(c = data->cookies->cookies; c; c = c->next) { - if(!c->domain) - continue; + c = data->cookies->cookies; + + while(c) { + /* fill the list with _all_ the cookies we know */ line = get_netscape_format(c); if(!line) { curl_slist_free_all(list); @@ -1322,6 +1342,7 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data) return NULL; } list = beg; + c = c->next; } return list; diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 6627a6b96..1e359d5c7 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -50,12 +50,15 @@ #include "curl_addrinfo.h" #include "inet_pton.h" #include "warnless.h" -#include "curl_printf.h" -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" + /* * Curl_freeaddrinfo() * @@ -80,8 +83,13 @@ Curl_freeaddrinfo(Curl_addrinfo *cahead) Curl_addrinfo *ca; for(ca = cahead; ca != NULL; ca = canext) { - free(ca->ai_addr); - free(ca->ai_canonname); + + if(ca->ai_addr) + free(ca->ai_addr); + + if(ca->ai_canonname) + free(ca->ai_canonname); + canext = ca->ai_next; free(ca); diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 5376aa7e1..87be9c717 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -53,7 +53,7 @@ #endif /* Use Windows LDAP implementation */ -#cmakedefine USE_WIN32_LDAP 1 +#cmakedefine CURL_LDAP_WIN 1 /* when not building a shared library */ #cmakedefine CURL_STATICLIB 1 @@ -909,6 +909,9 @@ /* if OpenSSL is in use */ #cmakedefine USE_OPENSSL 1 +/* if SSL is enabled */ +#cmakedefine USE_SSLEAY 1 + /* if Unix domain sockets are enabled */ #cmakedefine USE_UNIX_SOCKETS diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in index feb582ecd..1318afcca 100644 --- a/lib/curl_config.h.in +++ b/lib/curl_config.h.in @@ -69,6 +69,9 @@ /* Definition to make a library symbol externally visible. */ #undef CURL_EXTERN_SYMBOL +/* Use Windows LDAP implementation */ +#undef CURL_LDAP_WIN + /* your Entropy Gathering Daemon socket pathname */ #undef EGD_SOCKET @@ -120,9 +123,6 @@ /* Define to 1 if bool is an available type. */ #undef HAVE_BOOL_T -/* Define to 1 if using BoringSSL. */ -#undef HAVE_BORINGSSL - /* Define to 1 if you have the clock_gettime function and monotonic timer. */ #undef HAVE_CLOCK_GETTIME_MONOTONIC @@ -144,12 +144,6 @@ /* Define to 1 if you have the <cyassl/error-ssl.h> header file. */ #undef HAVE_CYASSL_ERROR_SSL_H -/* Define to 1 if you have the <cyassl/options.h> header file. */ -#undef HAVE_CYASSL_OPTIONS_H - -/* Define to 1 if you have the `DES_set_odd_parity' function. */ -#undef HAVE_DES_SET_ODD_PARITY - /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H @@ -394,9 +388,6 @@ /* Define to 1 if you have the `resolve' library (-lresolve). */ #undef HAVE_LIBRESOLVE -/* Define to 1 if using libressl. */ -#undef HAVE_LIBRESSL - /* Define to 1 if you have the <librtmp/rtmp.h> header file. */ #undef HAVE_LIBRTMP_RTMP_H @@ -479,9 +470,6 @@ /* Define to 1 if you have the <openssl/rsa.h> header file. */ #undef HAVE_OPENSSL_RSA_H -/* if you have the function SRP_Calc_client_key */ -#undef HAVE_OPENSSL_SRP - /* Define to 1 if you have the <openssl/ssl.h> header file. */ #undef HAVE_OPENSSL_SSL_H @@ -590,6 +578,9 @@ /* Define to 1 if you have the <socket.h> header file. */ #undef HAVE_SOCKET_H +/* if you have the function SRP_Calc_client_key */ +#undef HAVE_SSLEAY_SRP + /* Define to 1 if you have the `SSLv2_client_method' function. */ #undef HAVE_SSLV2_CLIENT_METHOD @@ -954,6 +945,9 @@ /* to enable Windows native SSL/TLS support */ #undef USE_SCHANNEL +/* if SSL is enabled */ +#undef USE_SSLEAY + /* if you want POSIX threaded DNS lookup */ #undef USE_THREADS_POSIX @@ -970,9 +964,6 @@ */ #undef USE_WIN32_LARGE_FILES -/* Use Windows LDAP implementation */ -#undef USE_WIN32_LDAP - /* Define to 1 if you are building a Windows target without large file support. */ #undef USE_WIN32_SMALL_FILES @@ -980,6 +971,9 @@ /* to enable SSPI support */ #undef USE_WINDOWS_SSPI +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +#undef USE_YASSLEMUL + /* Version number of package */ #undef VERSION diff --git a/lib/curl_des.c b/lib/curl_des.c deleted file mode 100644 index 42c1df956..000000000 --- a/lib/curl_des.c +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "curl_setup.h" - -#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL)) - -#include "curl_des.h" - -/* - * Curl_des_set_odd_parity() - * - * This is used to apply odd parity to the given byte array. It is typically - * used by when a cryptography engines doesn't have it's own version. - * - * The function is a port of the Java based oddParity() function over at: - * - * http://davenport.sourceforge.net/ntlm.html - * - * Parameters: - * - * bytes [in/out] - The data whose parity bits are to be adjusted for - * odd parity. - * len [out] - The length of the data. - */ -void Curl_des_set_odd_parity(unsigned char *bytes, size_t len) -{ - size_t i; - - for(i = 0; i < len; i++) { - unsigned char b = bytes[i]; - - bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ - (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ - (b >> 1)) & 0x01) == 0; - - if(needs_parity) - bytes[i] |= 0x01; - else - bytes[i] &= 0xfe; - } -} - -#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */ diff --git a/lib/curl_endian.c b/lib/curl_endian.c index bcd66ed84..14a28834d 100644 --- a/lib/curl_endian.c +++ b/lib/curl_endian.c @@ -62,7 +62,6 @@ unsigned int Curl_read32_le(unsigned char *buf) ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); } -#if (CURL_SIZEOF_CURL_OFF_T > 4) /* * Curl_read64_le() * @@ -98,8 +97,6 @@ unsigned __int64 Curl_read64_le(unsigned char *buf) } #endif -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ - /* * Curl_read16_be() * @@ -138,7 +135,6 @@ unsigned int Curl_read32_be(unsigned char *buf) ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); } -#if (CURL_SIZEOF_CURL_OFF_T > 4) /* * Curl_read64_be() * @@ -174,8 +170,6 @@ unsigned __int64 Curl_read64_be(unsigned char *buf) } #endif -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ - /* * Curl_write16_le() * @@ -233,4 +227,4 @@ void Curl_write64_le(const __int64 value, unsigned char *buffer) Curl_write32_le((int)value, buffer); Curl_write32_le((int)(value >> 32), buffer + 4); } -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ +#endif diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c index 1e53918d8..63f67b9aa 100644 --- a/lib/curl_fnmatch.c +++ b/lib/curl_fnmatch.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2011, 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,8 +23,11 @@ #include "curl_setup.h" #include "curl_fnmatch.h" -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index 9baece5ad..2cd14fff0 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,9 +27,9 @@ #include "curl_gssapi.h" #include "sendf.h" -static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; +static const char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes }; -static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; +static const char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes }; OM_uint32 Curl_gss_init_sec_context( diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h index 19aab64e6..35e4b2484 100644 --- a/lib/curl_gssapi.h +++ b/lib/curl_gssapi.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -59,17 +59,6 @@ OM_uint32 Curl_gss_init_sec_context( void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status, const char *prefix); -/* Provide some definitions missing in old headers */ -#ifdef HAVE_OLD_GSSMIT -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#define NCOMPAT 1 -#endif - -/* Define our privacy and integrity protection values */ -#define GSSAUTH_P_NONE 1 -#define GSSAUTH_P_INTEGRITY 2 -#define GSSAUTH_P_PRIVACY 4 - #endif /* HAVE_GSSAPI */ #endif /* HEADER_CURL_GSSAPI_H */ diff --git a/lib/curl_memory.h b/lib/curl_memory.h index bc744ccd8..e3cdc721c 100644 --- a/lib/curl_memory.h +++ b/lib/curl_memory.h @@ -28,9 +28,6 @@ * File curl_memory.h must be included by _all_ *.c source files * that use memory related functions strdup, malloc, calloc, realloc * or free, and given source file is used to build libcurl library. - * It should be included immediately before memdebug.h as the last files - * included to avoid undesired interaction with other memory function - * headers in dependent libraries. * * There is nearly no exception to above rule. All libcurl source * files in 'lib' subdirectory as well as those living deep inside diff --git a/lib/curl_memrchr.c b/lib/curl_memrchr.c index 6722c6a20..a71c2bb4a 100644 --- a/lib/curl_memrchr.c +++ b/lib/curl_memrchr.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2011, 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 @@ -21,9 +21,13 @@ ***************************************************************************/ #include "curl_setup.h" + #include "curl_memrchr.h" -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c index 403d00537..6e657228c 100644 --- a/lib/curl_multibyte.c +++ b/lib/curl_multibyte.c @@ -23,15 +23,18 @@ #include "curl_setup.h" #if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ - defined(USE_WIN32_LDAP)) && defined(UNICODE)) + defined(CURL_LDAP_WIN)) && defined(UNICODE)) /* * MultiByte conversions using Windows kernel32 library. */ #include "curl_multibyte.h" -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -47,8 +50,7 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) if(str_w) { if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, str_w_len) == 0) { - free(str_w); - return NULL; + Curl_safefree(str_w); } } } @@ -69,8 +71,7 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) if(str_utf8) { if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, NULL, FALSE) == 0) { - free(str_utf8); - return NULL; + Curl_safefree(str_utf8); } } } @@ -79,4 +80,4 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8; } -#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || CURL_LDAP_WIN) && UNICODE) */ diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h index dc7ed4c39..d0247557c 100644 --- a/lib/curl_multibyte.h +++ b/lib/curl_multibyte.h @@ -24,7 +24,7 @@ #include "curl_setup.h" #if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ - defined(USE_WIN32_LDAP)) && defined(UNICODE)) + defined(CURL_LDAP_WIN)) && defined(UNICODE)) /* * MultiByte conversions using Windows kernel32 library. @@ -33,11 +33,11 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); -#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || CURL_LDAP_WIN) && UNICODE) */ #if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \ - defined(USE_WIN32_LDAP) + defined(CURL_LDAP_WIN) /* * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() @@ -87,6 +87,6 @@ typedef union { #endif /* UNICODE */ -#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ +#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || CURL_LDAP_WIN */ #endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/lib/curl_ntlm.c b/lib/curl_ntlm.c index f9ddf506d..c77f055d4 100644 --- a/lib/curl_ntlm.c +++ b/lib/curl_ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -41,7 +41,10 @@ #include "curl_ntlm_wb.h" #include "curl_sasl.h" #include "url.h" -#include "curl_printf.h" +#include "curl_memory.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #if defined(USE_NSS) #include "vtls/nssg.h" @@ -49,8 +52,7 @@ #include "curl_sspi.h" #endif -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #if DEBUG_ME @@ -84,11 +86,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */ } else { - if(ntlm->state == NTLMSTATE_LAST) { - infof(conn->data, "NTLM auth restarted\n"); - Curl_http_ntlm_cleanup(conn); - } - else if(ntlm->state == NTLMSTATE_TYPE3) { + if(ntlm->state == NTLMSTATE_TYPE3) { infof(conn->data, "NTLM handshake rejected\n"); Curl_http_ntlm_cleanup(conn); ntlm->state = NTLMSTATE_NONE; @@ -177,7 +175,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) return result; if(base64) { - free(*allocuserpwd); + Curl_safefree(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "", base64); @@ -197,7 +195,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) return result; if(base64) { - free(*allocuserpwd); + Curl_safefree(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "", base64); @@ -215,9 +213,6 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) case NTLMSTATE_TYPE3: /* connection is already authenticated, * don't send a header in future requests */ - ntlm->state = NTLMSTATE_LAST; - - case NTLMSTATE_LAST: Curl_safefree(*allocuserpwd); authp->done = TRUE; break; diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 2e5b573fd..2aaea4db8 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -33,7 +33,7 @@ #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY # ifdef USE_OPENSSL # include <openssl/des.h> @@ -101,16 +101,17 @@ #include "urldata.h" #include "non-ascii.h" #include "rawstr.h" +#include "curl_memory.h" #include "curl_ntlm_core.h" #include "curl_md5.h" #include "curl_hmac.h" #include "warnless.h" #include "curl_endian.h" -#include "curl_des.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" #define NTLM_HMAC_MD5_LEN (16) @@ -132,7 +133,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key) key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); } -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY /* * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The * key schedule ks is also set. @@ -142,17 +143,8 @@ static void setup_des_key(const unsigned char *key_56, { DES_cblock key; - /* Expand the 56-bit key to 64-bits */ extend_key_56_to_64(key_56, (char *) key); - - /* Set the key parity to odd */ -#if defined(HAVE_BORINGSSL) - Curl_des_set_odd_parity((unsigned char *) &key, sizeof(key)); -#else DES_set_odd_parity(&key); -#endif - - /* Set the key */ DES_set_key(&key, ks); } @@ -162,15 +154,8 @@ static void setup_des_key(const unsigned char *key_56, struct des_ctx *des) { char key[8]; - - /* Expand the 56-bit key to 64-bits */ extend_key_56_to_64(key_56, key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); - - /* Set the key */ - des_set_key(des, (const uint8_t *) key); + des_set_key(des, (const uint8_t*)key); } #elif defined(USE_GNUTLS) @@ -182,15 +167,8 @@ static void setup_des_key(const unsigned char *key_56, gcry_cipher_hd_t *des) { char key[8]; - - /* Expand the 56-bit key to 64-bits */ extend_key_56_to_64(key_56, key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); - - /* Set the key */ - gcry_cipher_setkey(*des, key, sizeof(key)); + gcry_cipher_setkey(*des, key, 8); } #elif defined(USE_NSS) @@ -218,21 +196,16 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, if(!slot) return FALSE; - /* Expand the 56-bit key to 64-bits */ + /* expand the 56 bit key to 64 bit and wrap by NSS */ extend_key_56_to_64(key_56, key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); - - /* Import the key */ key_item.data = (unsigned char *)key; - key_item.len = sizeof(key); + key_item.len = /* hard-wired */ 8; symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if(!symkey) goto fail; - /* Create the DES encryption context */ + /* create DES encryption context */ param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); if(!param) goto fail; @@ -240,7 +213,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, if(!ctx) goto fail; - /* Perform the encryption */ + /* perform the encryption */ if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, (unsigned char *)in, /* inbuflen */ 8) && SECSuccess == PK11_Finalize(ctx)) @@ -267,17 +240,10 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, size_t out_len; CCCryptorStatus err; - /* Expand the 56-bit key to 64-bits */ extend_key_56_to_64(key_56, key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); - - /* Perform the encryption */ err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key, kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out, 8 /* outbuflen */, &out_len); - return err == kCCSuccess; } @@ -289,19 +255,10 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, char key[8]; _CIPHER_Control_T ctl; - /* Setup the cipher control structure */ ctl.Func_ID = ENCRYPT_ONLY; - ctl.Data_Len = sizeof(key); - - /* Expand the 56-bit key to 64-bits */ + ctl.Data_Len = 8; extend_key_56_to_64(key_56, ctl.Crypto_Key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); - - /* Perform the encryption */ _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); - return TRUE; } @@ -324,19 +281,13 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, CRYPT_VERIFYCONTEXT)) return FALSE; - /* Setup the key blob structure */ memset(&blob, 0, sizeof(blob)); + extend_key_56_to_64(key_56, blob.key); blob.hdr.bType = PLAINTEXTKEYBLOB; blob.hdr.bVersion = 2; blob.hdr.aiKeyAlg = CALG_DES; blob.len = sizeof(blob.key); - /* Expand the 56-bit key to 64-bits */ - extend_key_56_to_64(key_56, blob.key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); - /* Import the key */ if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { CryptReleaseContext(hprov, 0); @@ -366,7 +317,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, const unsigned char *plaintext, unsigned char *results) { -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY DES_key_schedule ks; setup_des_key(keys, DESKEY(ks)); @@ -441,7 +392,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, { /* Create LanManager hashed password. */ -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY DES_key_schedule ks; setup_des_key(pw, DESKEY(ks)); @@ -508,7 +459,6 @@ static void ascii_uppercase_to_unicode_le(unsigned char *dest, /* * Set up nt hashed passwords - * @unittest: 1600 */ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, const char *password, @@ -532,7 +482,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, { /* Create NT hashed password. */ -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY MD4_CTX MD4pw; MD4_Init(&MD4pw); MD4_Update(&MD4pw, pw, 2 * len); @@ -618,7 +568,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), ntlmv2hash); - free(identity); + Curl_safefree(identity); return result; } @@ -705,7 +655,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, NTLMv2_BLOB_LEN + 8, hmac_output); if(result) { - free(ptr); + Curl_safefree(ptr); + return result; } diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h index 3a763592a..c1689666c 100644 --- a/lib/curl_ntlm_core.h +++ b/lib/curl_ntlm_core.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,7 @@ #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY # if !defined(OPENSSL_VERSION_NUMBER) && \ !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H) # error "curl_ntlm_core.h shall not be included before OpenSSL headers." diff --git a/lib/curl_ntlm_msgs.c b/lib/curl_ntlm_msgs.c index 7f07decb8..865954d3b 100644 --- a/lib/curl_ntlm_msgs.c +++ b/lib/curl_ntlm_msgs.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -41,6 +41,7 @@ #include "curl_gethostname.h" #include "curl_multibyte.h" #include "warnless.h" +#include "curl_memory.h" #include "vtls/vtls.h" @@ -52,10 +53,11 @@ #include "curl_ntlm_msgs.h" #include "curl_sasl.h" #include "curl_endian.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* "NTLMSSP" signature is always in ASCII regardless of the platform */ @@ -591,11 +593,11 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, memcpy(tmp, &ntlm->nonce[0], 8); memcpy(tmp + 8, entropy, 8); - result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); - if(!result) - /* We shall only use the first 8 bytes of md5sum, but the des code in - Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ - result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); + + /* We shall only use the first 8 bytes of md5sum, but the des + code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) return result; @@ -758,7 +760,7 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); }); - free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ + Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ #endif diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index b2a5fb343..5e2d79cb4 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -51,10 +51,12 @@ #include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" -#include "curl_printf.h" - -/* The last #include files should be: */ #include "curl_memory.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" #if DEBUG_ME @@ -105,9 +107,9 @@ void Curl_ntlm_wb_cleanup(struct connectdata *conn) conn->ntlm_auth_hlpr_pid = 0; } - free(conn->challenge_header); + Curl_safefree(conn->challenge_header); conn->challenge_header = NULL; - free(conn->response_header); + Curl_safefree(conn->response_header); conn->response_header = NULL; } @@ -244,13 +246,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose(sockfds[1]); conn->ntlm_auth_hlpr_socket = sockfds[0]; conn->ntlm_auth_hlpr_pid = child_pid; - free(domain); - free(ntlm_auth_alloc); + Curl_safefree(domain); + Curl_safefree(ntlm_auth_alloc); return CURLE_OK; done: - free(domain); - free(ntlm_auth_alloc); + Curl_safefree(domain); + Curl_safefree(ntlm_auth_alloc); return CURLE_REMOTE_ACCESS_DENIED; } @@ -306,7 +308,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, if(state == NTLMSTATE_TYPE1 && len_out == 3 && buf[0] == 'P' && buf[1] == 'W') - goto done; + return CURLE_REMOTE_ACCESS_DENIED; /* invalid response */ if(len_out < 4) goto done; @@ -389,12 +391,12 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(res) return res; - free(*allocuserpwd); + Curl_safefree(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: %s\r\n", proxy ? "Proxy-" : "", conn->response_header); DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); - free(conn->response_header); + Curl_safefree(conn->response_header); conn->response_header = NULL; break; case NTLMSTATE_TYPE2: @@ -407,7 +409,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(res) return res; - free(*allocuserpwd); + Curl_safefree(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: %s\r\n", proxy ? "Proxy-" : "", conn->response_header); @@ -419,8 +421,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, case NTLMSTATE_TYPE3: /* connection is already authenticated, * don't send a header in future requests */ - free(*allocuserpwd); - *allocuserpwd=NULL; + if(*allocuserpwd) { + free(*allocuserpwd); + *allocuserpwd=NULL; + } authp->done = TRUE; break; } diff --git a/lib/curl_printf.h b/lib/curl_printf.h deleted file mode 100644 index 086923f1d..000000000 --- a/lib/curl_printf.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef HEADER_CURL_PRINTF_H -#define HEADER_CURL_PRINTF_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 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 http://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. - * - ***************************************************************************/ - -/* - * This header should be included by ALL code in libcurl that uses any - * *rintf() functions. - */ - -#include <curl/mprintf.h> - -# undef printf -# undef fprintf -# undef snprintf -# undef vprintf -# undef vfprintf -# undef vsnprintf -# undef aprintf -# undef vaprintf -# define printf curl_mprintf -# define fprintf curl_mfprintf -# define snprintf curl_msnprintf -# define vprintf curl_mvprintf -# define vfprintf curl_mvfprintf -# define vsnprintf 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/lib/curl_rtmp.c b/lib/curl_rtmp.c index 293897288..d1d79c38f 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com> * * This software is licensed as described in the file COPYING, which @@ -32,6 +32,10 @@ #include "warnless.h" #include <curl/curl.h> #include <librtmp/rtmp.h> + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -197,7 +201,7 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn) static CURLcode rtmp_connect(struct connectdata *conn, bool *done) { RTMP *r = conn->proto.generic; - SET_RCVTIMEO(tv, 10); + SET_RCVTIMEO(tv,10); r->m_sb.sb_socket = conn->sock[FIRSTSOCKET]; diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index 68646bc1a..b944aa2df 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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 @@ -39,33 +39,16 @@ #include "curl_hmac.h" #include "curl_sasl.h" #include "warnless.h" +#include "curl_memory.h" #include "strtok.h" -#include "strequal.h" #include "rawstr.h" -#include "sendf.h" #include "non-ascii.h" /* included for Curl_convert_... prototypes */ -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> -/* Supported mechanisms */ -const struct { - const char *name; /* Name */ - size_t len; /* Name length */ - unsigned int bit; /* Flag bit */ -} mechtable[] = { - { "LOGIN", 5, SASL_MECH_LOGIN }, - { "PLAIN", 5, SASL_MECH_PLAIN }, - { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 }, - { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 }, - { "GSSAPI", 6, SASL_MECH_GSSAPI }, - { "EXTERNAL", 8, SASL_MECH_EXTERNAL }, - { "NTLM", 4, SASL_MECH_NTLM }, - { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, - { ZERO_NULL, 0, 0 } -}; +/* The last #include file should be: */ +#include "memdebug.h" #if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI) #define DIGEST_QOP_VALUE_AUTH (1 << 0) @@ -76,6 +59,9 @@ const struct { #define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int" #define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf" +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + /* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. It converts digest text to ASCII so the MD5 will be correct for what ultimately goes over the network. @@ -87,16 +73,13 @@ const struct { return result; \ } -#endif - -#if !defined(CURL_DISABLE_CRYPTO_AUTH) /* - * Returns 0 on success and then the buffers are filled in fine. + * Return 0 on success and then the buffers are filled in fine. * * Non-zero means failure to parse. */ -int Curl_sasl_digest_get_pair(const char *str, char *value, char *content, - const char **endptr) +static int sasl_digest_get_pair(const char *str, char *value, char *content, + const char **endptr) { int c; bool starts_with_quote = FALSE; @@ -157,9 +140,7 @@ int Curl_sasl_digest_get_pair(const char *str, char *value, char *content, return 0; /* all is fine! */ } -#endif -#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI) /* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ static void sasl_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ unsigned char *dest) /* 33 bytes */ @@ -253,7 +234,7 @@ static CURLcode sasl_digest_get_qop_values(const char *options, int *value) token = strtok_r(NULL, ",", &tok_buf); } - free(tmp); + Curl_safefree(tmp); return CURLE_OK; } @@ -267,7 +248,7 @@ static CURLcode sasl_digest_get_qop_values(const char *options, int *value) * * Parameters: * - * service [in] - The service type such as www, smtp, pop or imap. + * serivce [in] - The service type such as www, smtp, pop or imap. * host [in] - The host name or realm. * * Returns a pointer to the newly allocated SPN. @@ -280,7 +261,7 @@ char *Curl_sasl_build_spn(const char *service, const char *host) #endif /* - * sasl_create_plain_message() + * Curl_sasl_create_plain_message() * * This is used to generate an already encoded PLAIN message ready * for sending to the recipient. @@ -296,10 +277,10 @@ char *Curl_sasl_build_spn(const char *service, const char *host) * * Returns CURLE_OK on success. */ -static CURLcode sasl_create_plain_message(struct SessionHandle *data, - const char *userp, - const char *passwdp, - char **outptr, size_t *outlen) +CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) { CURLcode result; char *plainauth; @@ -326,12 +307,12 @@ static CURLcode sasl_create_plain_message(struct SessionHandle *data, /* Base64 encode the reply */ result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, outlen); - free(plainauth); + Curl_safefree(plainauth); return result; } /* - * sasl_create_login_message() + * Curl_sasl_create_login_message() * * This is used to generate an already encoded LOGIN message containing the * user name or password ready for sending to the recipient. @@ -346,9 +327,9 @@ static CURLcode sasl_create_plain_message(struct SessionHandle *data, * * Returns CURLE_OK on success. */ -static CURLcode sasl_create_login_message(struct SessionHandle *data, - const char *valuep, char **outptr, - size_t *outlen) +CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, + const char *valuep, char **outptr, + size_t *outlen) { size_t vlen = strlen(valuep); @@ -368,33 +349,9 @@ static CURLcode sasl_create_login_message(struct SessionHandle *data, return Curl_base64_encode(data, valuep, vlen, outptr, outlen); } -/* - * sasl_create_external_message() - * - * This is used to generate an already encoded EXTERNAL message containing - * the user name ready for sending to the recipient. - * - * Parameters: - * - * data [in] - The session handle. - * user [in] - The user name. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. - * - * Returns CURLE_OK on success. - */ -static CURLcode sasl_create_external_message(struct SessionHandle *data, - const char *user, char **outptr, - size_t *outlen) -{ - /* This is the same formatting as the login message. */ - return sasl_create_login_message(data, user, outptr, outlen); -} - #ifndef CURL_DISABLE_CRYPTO_AUTH /* - * sasl_decode_cram_md5_message() + * Curl_sasl_decode_cram_md5_message() * * This is used to decode an already encoded CRAM-MD5 challenge message. * @@ -407,8 +364,8 @@ static CURLcode sasl_create_external_message(struct SessionHandle *data, * * Returns CURLE_OK on success. */ -static CURLcode sasl_decode_cram_md5_message(const char *chlg64, char **outptr, - size_t *outlen) +CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen) { CURLcode result = CURLE_OK; size_t chlg64len = strlen(chlg64); @@ -424,7 +381,7 @@ static CURLcode sasl_decode_cram_md5_message(const char *chlg64, char **outptr, } /* - * sasl_create_cram_md5_message() + * Curl_sasl_create_cram_md5_message() * * This is used to generate an already encoded CRAM-MD5 response message ready * for sending to the recipient. @@ -441,11 +398,11 @@ static CURLcode sasl_decode_cram_md5_message(const char *chlg64, char **outptr, * * Returns CURLE_OK on success. */ -static CURLcode sasl_create_cram_md5_message(struct SessionHandle *data, - const char *chlg, - const char *userp, - const char *passwdp, - char **outptr, size_t *outlen) +CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) { CURLcode result = CURLE_OK; size_t chlglen = 0; @@ -483,7 +440,7 @@ static CURLcode sasl_create_cram_md5_message(struct SessionHandle *data, /* Base64 encode the response */ result = Curl_base64_encode(data, response, 0, outptr, outlen); - free(response); + Curl_safefree(response); return result; } @@ -533,7 +490,7 @@ static CURLcode sasl_decode_digest_md5_message(const char *chlg64, /* Retrieve nonce string from the challenge */ if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) { - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } @@ -545,17 +502,17 @@ static CURLcode sasl_decode_digest_md5_message(const char *chlg64, /* Retrieve algorithm string from the challenge */ if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) { - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } /* Retrieve qop-options string from the challenge */ if(!sasl_digest_get_key_value((char *)chlg, "qop=\"", qop, qlen, '\"')) { - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } - free(chlg); + Curl_safefree(chlg); return CURLE_OK; } @@ -677,7 +634,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, /* Calculate H(A2) */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) { - free(spn); + Curl_safefree(spn); return CURLE_OUT_OF_MEMORY; } @@ -695,7 +652,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, /* Now calculate the response hash */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) { - free(spn); + Curl_safefree(spn); return CURLE_OUT_OF_MEMORY; } @@ -728,14 +685,14 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, "qop=%s", userp, realm, nonce, cnonce, nonceCount, spn, resp_hash_hex, qop); - free(spn); + Curl_safefree(spn); if(!response) return CURLE_OUT_OF_MEMORY; /* Base64 encode the response */ result = Curl_base64_encode(data, response, 0, outptr, outlen); - free(response); + Curl_safefree(response); return result; } @@ -778,7 +735,7 @@ CURLcode Curl_sasl_decode_digest_http_message(const char *chlg, chlg++; /* Extract a value=content pair */ - if(!Curl_sasl_digest_get_pair(chlg, value, content, &chlg)) { + if(!sasl_digest_get_pair(chlg, value, content, &chlg)) { if(Curl_raw_equal(value, "nonce")) { digest->nonce = strdup(content); if(!digest->nonce) @@ -949,7 +906,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ Curl_md5it(md5buf, md5this); - free(md5this); + Curl_safefree(md5this); sasl_digest_md5_to_ascii(md5buf, ha1); if(digest->algo == CURLDIGESTALGO_MD5SESS) { @@ -960,7 +917,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */ Curl_md5it(md5buf, (unsigned char *)tmp); - free(tmp); + Curl_safefree(tmp); sasl_digest_md5_to_ascii(md5buf, ha1); } @@ -984,7 +941,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, TODO: replace md5 of empty string with entity-body for PUT/POST */ unsigned char *md5this2 = (unsigned char *) aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e"); - free(md5this); + Curl_safefree(md5this); md5this = md5this2; } @@ -993,7 +950,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ Curl_md5it(md5buf, md5this); - free(md5this); + Curl_safefree(md5this); sasl_digest_md5_to_ascii(md5buf, ha2); if(digest->qop) { @@ -1017,7 +974,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ Curl_md5it(md5buf, md5this); - free(md5this); + Curl_safefree(md5this); sasl_digest_md5_to_ascii(md5buf, request_digest); /* for test case 64 (snooped from a Mozilla 1.3a request) @@ -1072,7 +1029,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, uripath, request_digest); } - free(userp_quoted); + Curl_safefree(userp_quoted); if(!response) return CURLE_OUT_OF_MEMORY; @@ -1153,7 +1110,7 @@ void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm) #endif /* USE_NTLM && !USE_WINDOWS_SSPI*/ /* - * sasl_create_xoauth2_message() + * Curl_sasl_create_xoauth2_message() * * This is used to generate an already encoded OAuth 2.0 message ready for * sending to the recipient. @@ -1169,10 +1126,10 @@ void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm) * * Returns CURLE_OK on success. */ -static CURLcode sasl_create_xoauth2_message(struct SessionHandle *data, - const char *user, - const char *bearer, - char **outptr, size_t *outlen) +CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen) { CURLcode result = CURLE_OK; char *xoauth = NULL; @@ -1185,7 +1142,7 @@ static CURLcode sasl_create_xoauth2_message(struct SessionHandle *data, /* Base64 encode the reply */ result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); - free(xoauth); + Curl_safefree(xoauth); return result; } @@ -1223,447 +1180,3 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) (void)authused; #endif } - -/* - * Curl_sasl_decode_mech() - * - * Convert a SASL mechanism name into a token. - * - * Parameters: - * - * ptr [in] - The mechanism string. - * maxlen [in] - Maximum mechanism string length. - * len [out] - If not NULL, effective name length. - * - * Returns the SASL mechanism token or 0 if no match. - */ -unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) -{ - unsigned int i; - char c; - - for(i = 0; mechtable[i].name; i++) { - if(maxlen >= mechtable[i].len && - !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { - if(len) - *len = mechtable[i].len; - - if(maxlen == mechtable[i].len) - return mechtable[i].bit; - - c = ptr[mechtable[i].len]; - if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_') - return mechtable[i].bit; - } - } - - return 0; -} - -/* - * Curl_sasl_parse_url_auth_option() - * - * Parse the URL login options. - */ -CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, - const char *value, size_t len) -{ - CURLcode result = CURLE_OK; - unsigned int mechbit; - size_t mechlen; - - if(!len) - return CURLE_URL_MALFORMAT; - - if(sasl->resetprefs) { - sasl->resetprefs = FALSE; - sasl->prefmech = SASL_AUTH_NONE; - } - - if(strnequal(value, "*", len)) - sasl->prefmech = SASL_AUTH_DEFAULT; - else if((mechbit = Curl_sasl_decode_mech(value, len, &mechlen)) && - mechlen == len) - sasl->prefmech |= mechbit; - else - result = CURLE_URL_MALFORMAT; - - return result; -} - -/* - * Curl_sasl_init() - * - * Initializes the SASL structure. - */ -void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) -{ - sasl->params = params; /* Set protocol dependent parameters */ - sasl->state = SASL_STOP; /* Not yet running */ - sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ - sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */ - sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */ - sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ - sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ - sasl->force_ir = FALSE; /* Respect external option */ -} - -/* - * state() - * - * This is the ONLY way to change SASL state! - */ -static void state(struct SASL *sasl, struct connectdata *conn, - saslstate newstate) -{ -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const names[]={ - "STOP", - "PLAIN", - "LOGIN", - "LOGIN_PASSWD", - "EXTERNAL", - "CRAMMD5", - "DIGESTMD5", - "DIGESTMD5_RESP", - "NTLM", - "NTLM_TYPE2MSG", - "GSSAPI", - "GSSAPI_TOKEN", - "GSSAPI_NO_DATA", - "XOAUTH2", - "CANCEL", - "FINAL", - /* LAST */ - }; - - if(sasl->state != newstate) - infof(conn->data, "SASL %p state change from %s to %s\n", - (void *)sasl, names[sasl->state], names[newstate]); -#else - (void) conn; -#endif - - sasl->state = newstate; -} - -/* - * Curl_sasl_can_authenticate() - * - * Check if we have enough auth data and capabilities to authenticate. - */ -bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn) -{ - /* Have credentials been provided? */ - if(conn->bits.user_passwd) - return TRUE; - - /* EXTERNAL can authenticate without a user name and/or password */ - if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL) - return TRUE; - - return FALSE; -} - -/* - * Curl_sasl_start() - * - * Calculate the required login details for SASL authentication. - */ -CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, - bool force_ir, saslprogress *progress) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - unsigned int enabledmechs; - const char *mech = NULL; - char *resp = NULL; - size_t len = 0; - saslstate state1 = SASL_STOP; - saslstate state2 = SASL_FINAL; - - sasl->force_ir = force_ir; /* Latch for future use */ - sasl->authused = 0; /* No mechanism used yet */ - enabledmechs = sasl->authmechs & sasl->prefmech; - *progress = SASL_IDLE; - - /* Calculate the supported authentication mechanism, by decreasing order of - security, as well as the initial response where appropriate */ - if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { - mech = SASL_MECH_STRING_EXTERNAL; - state1 = SASL_EXTERNAL; - sasl->authused = SASL_MECH_EXTERNAL; - - if(force_ir || data->set.sasl_ir) - result = sasl_create_external_message(data, conn->user, &resp, &len); - } - else if(conn->bits.user_passwd) { -#if defined(USE_KERBEROS5) - if(enabledmechs & SASL_MECH_GSSAPI) { - sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */ - mech = SASL_MECH_STRING_GSSAPI; - state1 = SASL_GSSAPI; - state2 = SASL_GSSAPI_TOKEN; - sasl->authused = SASL_MECH_GSSAPI; - - if(force_ir || data->set.sasl_ir) - result = Curl_sasl_create_gssapi_user_message(data, conn->user, - conn->passwd, - sasl->params->service, - sasl->mutual_auth, - NULL, &conn->krb5, - &resp, &len); - } - else -#endif -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(enabledmechs & SASL_MECH_DIGEST_MD5) { - mech = SASL_MECH_STRING_DIGEST_MD5; - state1 = SASL_DIGESTMD5; - sasl->authused = SASL_MECH_DIGEST_MD5; - } - else if(enabledmechs & SASL_MECH_CRAM_MD5) { - mech = SASL_MECH_STRING_CRAM_MD5; - state1 = SASL_CRAMMD5; - sasl->authused = SASL_MECH_CRAM_MD5; - } - else -#endif -#ifdef USE_NTLM - if(enabledmechs & SASL_MECH_NTLM) { - mech = SASL_MECH_STRING_NTLM; - state1 = SASL_NTLM; - state2 = SASL_NTLM_TYPE2MSG; - sasl->authused = SASL_MECH_NTLM; - - if(force_ir || data->set.sasl_ir) - result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, - &conn->ntlm, &resp, &len); - } - else -#endif - if((enabledmechs & SASL_MECH_XOAUTH2) || conn->xoauth2_bearer) { - mech = SASL_MECH_STRING_XOAUTH2; - state1 = SASL_XOAUTH2; - sasl->authused = SASL_MECH_XOAUTH2; - - if(force_ir || data->set.sasl_ir) - result = sasl_create_xoauth2_message(data, conn->user, - conn->xoauth2_bearer, - &resp, &len); - } - else if(enabledmechs & SASL_MECH_LOGIN) { - mech = SASL_MECH_STRING_LOGIN; - state1 = SASL_LOGIN; - state2 = SASL_LOGIN_PASSWD; - sasl->authused = SASL_MECH_LOGIN; - - if(force_ir || data->set.sasl_ir) - result = sasl_create_login_message(data, conn->user, &resp, &len); - } - else if(enabledmechs & SASL_MECH_PLAIN) { - mech = SASL_MECH_STRING_PLAIN; - state1 = SASL_PLAIN; - sasl->authused = SASL_MECH_PLAIN; - - if(force_ir || data->set.sasl_ir) - result = sasl_create_plain_message(data, conn->user, conn->passwd, - &resp, &len); - } - } - - if(!result) { - if(resp && sasl->params->maxirlen && - strlen(mech) + len > sasl->params->maxirlen) { - free(resp); - resp = NULL; - } - - if(mech) { - result = sasl->params->sendauth(conn, mech, resp); - if(!result) { - *progress = SASL_INPROGRESS; - state(sasl, conn, resp? state2: state1); - } - } - } - - free(resp); - - return result; -} - -/* - * Curl_sasl_continue() - * - * Continue the authentication. - */ -CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, - int code, saslprogress *progress) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - saslstate newstate = SASL_FINAL; - char *resp = NULL; -#if !defined(CURL_DISABLE_CRYPTO_AUTH) - char *serverdata; - char *chlg = NULL; - size_t chlglen = 0; -#endif - size_t len = 0; - - *progress = SASL_INPROGRESS; - - if(sasl->state == SASL_FINAL) { - if(code != sasl->params->finalcode) - result = CURLE_LOGIN_DENIED; - *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); - return result; - } - - if(sasl->state != SASL_CANCEL && code != sasl->params->contcode) { - *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); - return CURLE_LOGIN_DENIED; - } - - switch(sasl->state) { - case SASL_STOP: - *progress = SASL_DONE; - return result; - case SASL_PLAIN: - result = sasl_create_plain_message(data, conn->user, conn->passwd, &resp, - &len); - break; - case SASL_LOGIN: - result = sasl_create_login_message(data, conn->user, &resp, &len); - newstate = SASL_LOGIN_PASSWD; - break; - case SASL_LOGIN_PASSWD: - result = sasl_create_login_message(data, conn->passwd, &resp, &len); - break; - case SASL_EXTERNAL: - result = sasl_create_external_message(data, conn->user, &resp, &len); - break; - -#ifndef CURL_DISABLE_CRYPTO_AUTH - case SASL_CRAMMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = sasl_decode_cram_md5_message(serverdata, &chlg, &chlglen); - if(!result) - result = sasl_create_cram_md5_message(data, chlg, conn->user, - conn->passwd, &resp, &len); - free(chlg); - break; - case SASL_DIGESTMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_sasl_create_digest_md5_message(data, serverdata, - conn->user, conn->passwd, - sasl->params->service, - &resp, &len); - newstate = SASL_DIGESTMD5_RESP; - break; - case SASL_DIGESTMD5_RESP: - if(!(resp = strdup(""))) - result = CURLE_OUT_OF_MEMORY; - break; -#endif - -#ifdef USE_NTLM - case SASL_NTLM: - /* Create the type-1 message */ - result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, - &conn->ntlm, &resp, &len); - newstate = SASL_NTLM_TYPE2MSG; - break; - case SASL_NTLM_TYPE2MSG: - /* Decode the type-2 message */ - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_sasl_decode_ntlm_type2_message(data, serverdata, - &conn->ntlm); - if(!result) - result = Curl_sasl_create_ntlm_type3_message(data, conn->user, - conn->passwd, &conn->ntlm, - &resp, &len); - break; -#endif - -#if defined(USE_KERBEROS5) - case SASL_GSSAPI: - result = Curl_sasl_create_gssapi_user_message(data, conn->user, - conn->passwd, - sasl->params->service, - sasl->mutual_auth, NULL, - &conn->krb5, - &resp, &len); - newstate = SASL_GSSAPI_TOKEN; - break; - case SASL_GSSAPI_TOKEN: - sasl->params->getmessage(data->state.buffer, &serverdata); - if(sasl->mutual_auth) { - /* Decode the user token challenge and create the optional response - message */ - result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL, - sasl->mutual_auth, - serverdata, &conn->krb5, - &resp, &len); - newstate = SASL_GSSAPI_NO_DATA; - } - else - /* Decode the security challenge and create the response message */ - result = Curl_sasl_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); - break; - case SASL_GSSAPI_NO_DATA: - sasl->params->getmessage(data->state.buffer, &serverdata); - /* Decode the security challenge and create the response message */ - result = Curl_sasl_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); - break; -#endif - - case SASL_XOAUTH2: - /* Create the authorisation message */ - result = sasl_create_xoauth2_message(data, conn->user, - conn->xoauth2_bearer, &resp, &len); - break; - case SASL_CANCEL: - /* Remove the offending mechanism from the supported list */ - sasl->authmechs ^= sasl->authused; - - /* Start an alternative SASL authentication */ - result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); - newstate = sasl->state; /* Use state from Curl_sasl_start() */ - break; - default: - failf(data, "Unsupported SASL authentication mechanism"); - result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ - break; - } - - switch(result) { - case CURLE_BAD_CONTENT_ENCODING: - /* Cancel dialog */ - result = sasl->params->sendcont(conn, "*"); - newstate = SASL_CANCEL; - break; - case CURLE_OK: - if(resp) - result = sasl->params->sendcont(conn, resp); - break; - default: - newstate = SASL_STOP; /* Stop on error */ - *progress = SASL_DONE; - break; - } - - free(resp); - - state(sasl, conn, newstate); - - return result; -} diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h index 117d60e32..41ef859a2 100644 --- a/lib/curl_sasl.h +++ b/lib/curl_sasl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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 @@ -39,6 +39,10 @@ struct ntlmdata; struct kerberos5data; #endif +/* Authentication mechanism values */ +#define SASL_AUTH_NONE 0 +#define SASL_AUTH_ANY ~0U + /* Authentication mechanism flags */ #define SASL_MECH_LOGIN (1 << 0) #define SASL_MECH_PLAIN (1 << 1) @@ -49,12 +53,6 @@ struct kerberos5data; #define SASL_MECH_NTLM (1 << 6) #define SASL_MECH_XOAUTH2 (1 << 7) -/* Authentication mechanism values */ -#define SASL_AUTH_NONE 0 -#define SASL_AUTH_ANY ~0U -#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & \ - ~(SASL_MECH_EXTERNAL | SASL_MECH_XOAUTH2)) - /* Authentication mechanism strings */ #define SASL_MECH_STRING_LOGIN "LOGIN" #define SASL_MECH_STRING_PLAIN "PLAIN" @@ -65,70 +63,11 @@ struct kerberos5data; #define SASL_MECH_STRING_NTLM "NTLM" #define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" -#if !defined(CURL_DISABLE_CRYPTO_AUTH) -#define DIGEST_MAX_VALUE_LENGTH 256 -#define DIGEST_MAX_CONTENT_LENGTH 1024 -#endif - enum { CURLDIGESTALGO_MD5, CURLDIGESTALGO_MD5SESS }; -/* SASL machine states */ -typedef enum { - SASL_STOP, - SASL_PLAIN, - SASL_LOGIN, - SASL_LOGIN_PASSWD, - SASL_EXTERNAL, - SASL_CRAMMD5, - SASL_DIGESTMD5, - SASL_DIGESTMD5_RESP, - SASL_NTLM, - SASL_NTLM_TYPE2MSG, - SASL_GSSAPI, - SASL_GSSAPI_TOKEN, - SASL_GSSAPI_NO_DATA, - SASL_XOAUTH2, - SASL_CANCEL, - SASL_FINAL -} saslstate; - -/* Progress indicator */ -typedef enum { - SASL_IDLE, - SASL_INPROGRESS, - SASL_DONE -} saslprogress; - -/* Protocol dependent SASL parameters */ -struct SASLproto { - const char *service; /* The service name */ - int contcode; /* Code to receive when continuation is expected */ - int finalcode; /* Code to receive upon authentication success */ - size_t maxirlen; /* Maximum initial response length */ - CURLcode (*sendauth)(struct connectdata *conn, - const char *mech, const char *ir); - /* Send authentication command */ - CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); - /* Send authentication continuation */ - void (*getmessage)(char *buffer, char **outptr); - /* Get SASL response message */ -}; - -/* Per-connection parameters */ -struct SASL { - const struct SASLproto *params; /* Protocol dependent parameters */ - saslstate state; /* Current machine state */ - unsigned int authmechs; /* Accepted authentication mechanisms */ - unsigned int prefmech; /* Preferred authentication mechanism */ - unsigned int authused; /* Auth mechanism used for the connection */ - bool resetprefs; /* For URL auth option parsing. */ - bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ - bool force_ir; /* Protocol always supports initial response */ -}; - /* This is used to test whether the line starts with the given mechanism */ #define sasl_mech_equal(line, wordlen, mech) \ (wordlen == (sizeof(mech) - 1) / sizeof(char) && \ @@ -141,15 +80,29 @@ char *Curl_sasl_build_spn(const char *service, const char *instance); TCHAR *Curl_sasl_build_spn(const char *service, const char *instance); #endif -/* This is used to extract the realm from a challenge message */ -int Curl_sasl_digest_get_pair(const char *str, char *value, char *content, - const char **endptr); +/* This is used to generate a base64 encoded PLAIN authentication message */ +CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); -#if defined(HAVE_GSSAPI) -char *Curl_sasl_build_gssapi_spn(const char *service, const char *host); -#endif +/* This is used to generate a base64 encoded LOGIN authentication message + containing either the user name or password details */ +CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, + const char *valuep, char **outptr, + size_t *outlen); #ifndef CURL_DISABLE_CRYPTO_AUTH +/* This is used to decode a base64 encoded CRAM-MD5 challange message */ +CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen); + +/* This is used to generate a base64 encoded CRAM-MD5 response message */ +CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, + const char *chlg, + const char *user, + const char *passwdp, + char **outptr, size_t *outlen); /* This is used to generate a base64 encoded DIGEST-MD5 response message */ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, @@ -225,30 +178,15 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5); #endif /* USE_KERBEROS5 */ +/* This is used to generate a base64 encoded XOAUTH2 authentication message + containing the user name and bearer token */ +CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen); + /* This is used to cleanup any libraries or curl modules used by the sasl functions */ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); -/* Convert a mechanism name to a token */ -unsigned int Curl_sasl_decode_mech(const char *ptr, - size_t maxlen, size_t *len); - -/* Parse the URL login options */ -CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, - const char *value, size_t len); - -/* Initializes an SASL structure */ -void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); - -/* Check if we have enough auth data and capabilities to authenticate */ -bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); - -/* Calculate the required login details for SASL authentication */ -CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, - bool force_ir, saslprogress *progress); - -/* Continue an SASL authentication */ -CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, - int code, saslprogress *progress); - #endif /* HEADER_CURL_SASL_H */ diff --git a/lib/curl_sasl_gssapi.c b/lib/curl_sasl_gssapi.c index 3c6f3ce32..6dda0e907 100644 --- a/lib/curl_sasl_gssapi.c +++ b/lib/curl_sasl_gssapi.c @@ -5,8 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2015, Steve Holme, <steve_holme@hotmail.com>. - * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2014, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,17 +26,28 @@ #if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5) +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif + +#define GSSAUTH_P_NONE 1 +#define GSSAUTH_P_INTEGRITY 2 +#define GSSAUTH_P_PRIVACY 4 + #include <curl/curl.h> #include "curl_sasl.h" #include "urldata.h" #include "curl_base64.h" #include "curl_gssapi.h" +#include "curl_memory.h" #include "sendf.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -52,7 +62,7 @@ * * Returns a pointer to the newly allocated SPN. */ -char *Curl_sasl_build_gssapi_spn(const char *service, const char *host) +static char *Curl_sasl_build_gssapi_spn(const char *service, const char *host) { /* Generate and return our SPN */ return aprintf("%s@%s", service, host); @@ -116,16 +126,12 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data, /* Import the SPN */ gss_major_status = gss_import_name(&gss_minor_status, &spn_token, - GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn); + gss_nt_service_name, &krb5->spn); if(GSS_ERROR(gss_major_status)) { Curl_gss_log_error(data, gss_minor_status, "gss_import_name() failed: "); - free(spn); - return CURLE_OUT_OF_MEMORY; } - - free(spn); } else { /* Decode the base-64 encoded challenge message */ @@ -158,7 +164,7 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data, mutual_auth, NULL); - free(input_token.value); + Curl_safefree(input_token.value); if(GSS_ERROR(gss_major_status)) { if(output_token.value) @@ -244,7 +250,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, Curl_gss_log_error(data, gss_minor_status, "gss_inquire_context() failed: "); - free(chlg); + Curl_safefree(chlg); return CURLE_OUT_OF_MEMORY; } @@ -255,7 +261,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, if(GSS_ERROR(gss_major_status)) { Curl_gss_log_error(data, gss_minor_status, "gss_display_name() failed: "); - free(chlg); + Curl_safefree(chlg); return CURLE_OUT_OF_MEMORY; } @@ -271,7 +277,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, Curl_gss_log_error(data, gss_minor_status, "gss_unwrap() failed: "); gss_release_buffer(&gss_status, &username_token); - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } @@ -281,7 +287,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, infof(data, "GSSAPI handshake failure (invalid security data)\n"); gss_release_buffer(&gss_status, &username_token); - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } @@ -289,7 +295,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, output_token.value, 4); gss_release_buffer(&gss_status, &output_token); - free(chlg); + Curl_safefree(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; @@ -344,7 +350,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, if(GSS_ERROR(gss_major_status)) { Curl_gss_log_error(data, gss_minor_status, "gss_wrap() failed: "); - free(message); + Curl_safefree(message); return CURLE_OUT_OF_MEMORY; } @@ -357,7 +363,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, gss_release_buffer(&gss_status, &output_token); /* Free the message buffer */ - free(message); + Curl_safefree(message); return result; } diff --git a/lib/curl_sasl_sspi.c b/lib/curl_sasl_sspi.c index b149530ff..0509b7555 100644 --- a/lib/curl_sasl_sspi.c +++ b/lib/curl_sasl_sspi.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2014, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2014, 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 @@ -36,14 +36,15 @@ #include "urldata.h" #include "curl_base64.h" #include "warnless.h" +#include "curl_memory.h" #include "curl_multibyte.h" #include "sendf.h" #include "strdup.h" -#include "curl_printf.h" -#include "rawstr.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -79,7 +80,7 @@ TCHAR *Curl_sasl_build_spn(const char *service, const char *host) /* Allocate our TCHAR based SPN */ tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn); if(!tchar_spn) { - free(utf8_spn); + Curl_safefree(utf8_spn); return NULL; } @@ -155,7 +156,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), &SecurityPackage); if(status != SEC_E_OK) { - free(input_token); + Curl_safefree(input_token); return CURLE_NOT_BUILT_IN; } @@ -168,7 +169,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, /* Allocate our response buffer */ output_token = malloc(token_max); if(!output_token) { - free(input_token); + Curl_safefree(input_token); return CURLE_OUT_OF_MEMORY; } @@ -176,8 +177,8 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, /* Generate our SPN */ spn = Curl_sasl_build_spn(service, data->easy_conn->host.name); if(!spn) { - free(output_token); - free(input_token); + Curl_safefree(output_token); + Curl_safefree(input_token); return CURLE_OUT_OF_MEMORY; } @@ -186,9 +187,9 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, /* Populate our identity structure */ result = Curl_create_sspi_identity(userp, passwdp, &identity); if(result) { - free(spn); - free(output_token); - free(input_token); + Curl_safefree(spn); + Curl_safefree(output_token); + Curl_safefree(input_token); return result; } @@ -209,9 +210,9 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, if(status != SEC_E_OK) { Curl_sspi_free_identity(p_identity); - free(spn); - free(output_token); - free(input_token); + Curl_safefree(spn); + Curl_safefree(output_token); + Curl_safefree(input_token); return CURLE_LOGIN_DENIED; } @@ -244,9 +245,9 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { s_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); - free(spn); - free(output_token); - free(input_token); + Curl_safefree(spn); + Curl_safefree(output_token); + Curl_safefree(input_token); return CURLE_RECV_ERROR; } @@ -263,86 +264,18 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, Curl_sspi_free_identity(p_identity); /* Free the SPN */ - free(spn); + Curl_safefree(spn); /* Free the response buffer */ - free(output_token); + Curl_safefree(output_token); /* Free the decoded challenge message */ - free(input_token); + Curl_safefree(input_token); return result; } /* -* Curl_override_sspi_http_realm() -* -* This is used to populate the domain in a SSPI identity structure -* The realm is extracted from the challenge message and used as the -* domain if it is not already explicitly set. -* -* Parameters: -* -* chlg [in] - The challenge message. -* identity [in/out] - The identity structure. -* -* Returns CURLE_OK on success. -*/ -CURLcode Curl_override_sspi_http_realm(const char *chlg, - SEC_WINNT_AUTH_IDENTITY *identity) -{ - xcharp_u domain, dup_domain; - - /* If domain is blank or unset, check challenge message for realm */ - if(!identity->Domain || !identity->DomainLength) { - for(;;) { - char value[DIGEST_MAX_VALUE_LENGTH]; - char content[DIGEST_MAX_CONTENT_LENGTH]; - - /* Pass all additional spaces here */ - while(*chlg && ISSPACE(*chlg)) - chlg++; - - /* Extract a value=content pair */ - if(!Curl_sasl_digest_get_pair(chlg, value, content, &chlg)) { - if(Curl_raw_equal(value, "realm")) { - - /* Setup identity's domain and length */ - domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)content); - if(!domain.tchar_ptr) - return CURLE_OUT_OF_MEMORY; - dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr); - if(!dup_domain.tchar_ptr) { - Curl_unicodefree(domain.tchar_ptr); - return CURLE_OUT_OF_MEMORY; - } - identity->Domain = dup_domain.tbyte_ptr; - identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr)); - dup_domain.tchar_ptr = NULL; - - Curl_unicodefree(domain.tchar_ptr); - } - else { - /* unknown specifier, ignore it! */ - } - } - else - break; /* we're done here */ - - /* Pass all additional spaces here */ - while(*chlg && ISSPACE(*chlg)) - chlg++; - - /* Allow the list to be comma-separated */ - if(',' == *chlg) - chlg++; - } - } - - return CURLE_OK; -} - -/* * Curl_sasl_decode_digest_http_message() * * This is used to decode a HTTP DIGEST challenge message into the seperate @@ -443,11 +376,6 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, if(Curl_create_sspi_identity(userp, passwdp, &identity)) return CURLE_OUT_OF_MEMORY; - /* Populate our identity domain */ - if(Curl_override_sspi_http_realm((const char*)digest->input_token, - &identity)) - return CURLE_OUT_OF_MEMORY; - /* Allow proper cleanup of the identity structure */ p_identity = &identity; } @@ -462,7 +390,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, p_identity, NULL, NULL, &credentials, &expiry); if(status != SEC_E_OK) { - free(output_token); + Curl_safefree(output_token); return CURLE_LOGIN_DENIED; } @@ -502,7 +430,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { s_pSecFn->FreeCredentialsHandle(&credentials); - free(output_token); + Curl_safefree(output_token); return CURLE_OUT_OF_MEMORY; } @@ -512,7 +440,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, s_pSecFn->DeleteSecurityContext(&context); s_pSecFn->FreeCredentialsHandle(&credentials); - free(output_token); + Curl_safefree(output_token); return CURLE_OUT_OF_MEMORY; } @@ -533,7 +461,7 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, Curl_sspi_free_identity(p_identity); /* Free the response buffer */ - free(output_token); + Curl_safefree(output_token); return CURLE_OK; } @@ -984,7 +912,7 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data, &expiry); if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { - free(chlg); + Curl_safefree(chlg); return CURLE_RECV_ERROR; } @@ -1002,7 +930,7 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data, } /* Free the decoded challenge */ - free(chlg); + Curl_safefree(chlg); return result; } @@ -1073,7 +1001,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, SECPKG_ATTR_SIZES, &sizes); if(status != SEC_E_OK) { - free(chlg); + Curl_safefree(chlg); return CURLE_OUT_OF_MEMORY; } @@ -1083,7 +1011,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, SECPKG_CRED_ATTR_NAMES, &names); if(status != SEC_E_OK) { - free(chlg); + Curl_safefree(chlg); return CURLE_RECV_ERROR; } @@ -1104,7 +1032,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, if(status != SEC_E_OK) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } @@ -1113,7 +1041,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, if(input_buf[1].cbBuffer != 4) { infof(data, "GSSAPI handshake failure (invalid security data)\n"); - free(chlg); + Curl_safefree(chlg); return CURLE_BAD_CONTENT_ENCODING; } @@ -1121,7 +1049,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, input_buf[1].pvBuffer, 4); s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); - free(chlg); + Curl_safefree(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; @@ -1148,7 +1076,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, /* Convert the user name to UTF8 when operating with Unicode */ user_name = Curl_convert_tchar_to_UTF8(names.sUserName); if(!user_name) { - free(trailer); + Curl_safefree(trailer); return CURLE_OUT_OF_MEMORY; } @@ -1157,7 +1085,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, messagelen = sizeof(outdata) + strlen(user_name) + 1; message = malloc(messagelen); if(!message) { - free(trailer); + Curl_safefree(trailer); Curl_unicodefree(user_name); return CURLE_OUT_OF_MEMORY; @@ -1176,8 +1104,8 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, /* Allocate the padding */ padding = malloc(sizes.cbBlockSize); if(!padding) { - free(message); - free(trailer); + Curl_safefree(message); + Curl_safefree(trailer); return CURLE_OUT_OF_MEMORY; } @@ -1200,9 +1128,9 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT, &wrap_desc, 0); if(status != SEC_E_OK) { - free(padding); - free(message); - free(trailer); + Curl_safefree(padding); + Curl_safefree(message); + Curl_safefree(trailer); return CURLE_OUT_OF_MEMORY; } @@ -1212,9 +1140,9 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, wrap_buf[2].cbBuffer; appdata = malloc(appdatalen); if(!appdata) { - free(padding); - free(message); - free(trailer); + Curl_safefree(padding); + Curl_safefree(message); + Curl_safefree(trailer); return CURLE_OUT_OF_MEMORY; } @@ -1231,10 +1159,10 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, outlen); /* Free all of our local buffers */ - free(appdata); - free(padding); - free(message); - free(trailer); + Curl_safefree(appdata); + Curl_safefree(padding); + Curl_safefree(message); + Curl_safefree(trailer); return result; } diff --git a/lib/curl_setup.h b/lib/curl_setup.h index ab0c13940..b046b77d3 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -190,9 +190,6 @@ # ifndef CURL_DISABLE_GOPHER # define CURL_DISABLE_GOPHER # endif -# ifndef CURL_DISABLE_SMB -# define CURL_DISABLE_SMB -# endif #endif /* @@ -604,7 +601,7 @@ int netware_init(void); #define LIBIDN_REQUIRED_VERSION "0.4.1" -#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ +#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \ defined(USE_POLARSSL) || defined(USE_AXTLS) || \ defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ defined(USE_DARWINSSL) || defined(USE_GSKIT) @@ -625,17 +622,12 @@ int netware_init(void); /* Single point where USE_NTLM definition might be defined */ #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) -#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ +#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) - -#ifdef HAVE_BORINGSSL /* BoringSSL is not NTLM capable */ -#undef USE_NTLM -#else #define USE_NTLM #endif #endif -#endif /* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */ #if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE) @@ -707,24 +699,4 @@ int netware_init(void); #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif -/* In Windows the default file mode is text but an application can override it. -Therefore we specify it explicitly. https://github.com/bagder/curl/pull/258 -*/ -#if defined(WIN32) || defined(MSDOS) -#define FOPEN_READTEXT "rt" -#define FOPEN_WRITETEXT "wt" -#elif defined(__CYGWIN__) -/* Cygwin has specific behavior we need to address when WIN32 is not defined. -https://cygwin.com/cygwin-ug-net/using-textbinary.html -For write we want our output to have line endings of LF and be compatible with -other Cygwin utilities. For read we want to handle input that may have line -endings either CRLF or LF so 't' is appropriate. -*/ -#define FOPEN_READTEXT "rt" -#define FOPEN_WRITETEXT "w" -#else -#define FOPEN_READTEXT "r" -#define FOPEN_WRITETEXT "w" -#endif - #endif /* HEADER_CURL_SETUP_H */ diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c index 070424dd1..f09d28827 100644 --- a/lib/curl_sspi.c +++ b/lib/curl_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, 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 @@ -25,12 +25,17 @@ #ifdef USE_WINDOWS_SSPI #include <curl/curl.h> + #include "curl_sspi.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +#include "curl_memory.h" #include "curl_multibyte.h" #include "warnless.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" /* We use our own typedef here since some headers might lack these */ @@ -93,25 +98,20 @@ CURLcode Curl_sspi_global_init(void) osver.dwPlatformId == platformId) securityDll = TRUE; #else - ULONGLONG cm; + ULONGLONG majorVersionMask; + ULONGLONG platformIdMask; OSVERSIONINFOEX osver; memset(&osver, 0, sizeof(osver)); osver.dwOSVersionInfoSize = sizeof(osver); osver.dwMajorVersion = majorVersion; osver.dwPlatformId = platformId; - - cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); + majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + platformIdMask = VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL); /* Verify the major version number == 4 and platform id == WIN_NT */ - if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR | - VER_PLATFORMID), - cm)) + if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask) && + VerifyVersionInfo(&osver, VER_PLATFORMID, platformIdMask)) securityDll = TRUE; #endif @@ -224,7 +224,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, Curl_unicodefree(useranddomain.tchar_ptr); - /* Setup the identity's password and length */ + /* Setup ntlm identity's password and length */ passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); if(!passwd.tchar_ptr) return CURLE_OUT_OF_MEMORY; diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h index 8655715e2..7fa308c5a 100644 --- a/lib/curl_sspi.h +++ b/lib/curl_sspi.h @@ -43,10 +43,6 @@ CURLcode Curl_sspi_global_init(void); void Curl_sspi_global_cleanup(void); -/* This is used to populate the domain in a SSPI identity structure */ -CURLcode Curl_override_sspi_http_realm(const char *chlg, - SEC_WINNT_AUTH_IDENTITY *identity); - /* This is used to generate an SSPI identity structure */ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, SEC_WINNT_AUTH_IDENTITY *identity); diff --git a/lib/curl_threads.c b/lib/curl_threads.c index f9b812ea0..5b7013914 100644 --- a/lib/curl_threads.c +++ b/lib/curl_threads.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -33,6 +33,10 @@ #endif #include "curl_threads.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -73,8 +77,8 @@ curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg) return t; err: - free(t); - free(ac); + Curl_safefree(t); + Curl_safefree(ac); return curl_thread_t_null; } diff --git a/lib/curlx.h b/lib/curlx.h index 979e7d7a1..9dc90a004 100644 --- a/lib/curlx.h +++ b/lib/curlx.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -90,7 +90,8 @@ #ifdef ENABLE_CURLX_PRINTF /* If this define is set, we define all "standard" printf() functions to use the curlx_* version instead. It makes the source code transparent and - easier to understand/patch. Undefine them first. */ + easier to understand/patch. Undefine them first in case _MPRINTF_REPLACE + is set. */ # undef printf # undef fprintf # undef sprintf diff --git a/lib/dict.c b/lib/dict.c index 06d76992e..86ddfb9e2 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -57,6 +57,10 @@ #include "strequal.h" #include "dict.h" #include "rawstr.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -97,7 +101,7 @@ static char *unescape_word(struct SessionHandle *data, const char *inputbuff) char *dictp; char *ptr; int len; - char ch; + char byte; int olen=0; newp = curl_easy_unescape(data, inputbuff, 0, &len); @@ -109,13 +113,13 @@ static char *unescape_word(struct SessionHandle *data, const char *inputbuff) /* According to RFC2229 section 2.2, these letters need to be escaped with \[letter] */ for(ptr = newp; - (ch = *ptr) != 0; + (byte = *ptr) != 0; ptr++) { - if((ch <= 32) || (ch == 127) || - (ch == '\'') || (ch == '\"') || (ch == '\\')) { + if((byte <= 32) || (byte == 127) || + (byte == '\'') || (byte == '\"') || (byte == '\\')) { dictp[olen++] = '\\'; } - dictp[olen++] = ch; + dictp[olen++] = byte; } dictp[olen]=0; } diff --git a/lib/easy.c b/lib/easy.c index 316acb1d1..619312b79 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -60,6 +60,7 @@ #include "hostip.h" #include "share.h" #include "strdup.h" +#include "curl_memory.h" #include "progress.h" #include "easyif.h" #include "select.h" @@ -74,10 +75,11 @@ #include "multiif.h" #include "sigpipe.h" #include "ssh.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* win32_cleanup() is for win32 socket cleanup functionality, the opposite diff --git a/lib/escape.c b/lib/escape.c index 24abb930b..9923e64cf 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,14 +27,16 @@ #include <curl/curl.h> +#include "curl_memory.h" #include "urldata.h" #include "warnless.h" #include "non-ascii.h" #include "escape.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* Portable character check (remember EBCDIC). Do not use isalnum() because @@ -227,5 +229,6 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length, the library's memory system */ void curl_free(void *p) { - free(p); + if(p) + free(p); } diff --git a/lib/file.c b/lib/file.c index 175b10731..dd2c56498 100644 --- a/lib/file.c +++ b/lib/file.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -59,12 +59,14 @@ #include "getinfo.h" #include "transfer.h" #include "url.h" +#include "curl_memory.h" #include "parsedate.h" /* for the week day and month names */ #include "warnless.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" #if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \ @@ -315,6 +317,8 @@ static CURLcode file_upload(struct connectdata *conn) * Since FILE: doesn't do the full init, we need to provide some extra * assignments here. */ + conn->fread_func = data->set.fread_func; + conn->fread_in = data->set.in; conn->data->req.upload_fromhere = buf; if(!dir) diff --git a/lib/fileinfo.c b/lib/fileinfo.c index 0904937aa..8c8ee981a 100644 --- a/lib/fileinfo.c +++ b/lib/fileinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010-2011, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,6 +24,10 @@ #include "strdup.h" #include "fileinfo.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/firefox-db2pem.sh b/lib/firefox-db2pem.sh index 3f5fe75ff..14ac57606 100644 --- a/lib/firefox-db2pem.sh +++ b/lib/firefox-db2pem.sh @@ -6,7 +6,7 @@ # * | (__| |_| | _ <| |___ # * \___|\___/|_| \_\_____| # * -# * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. +# * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. # * # * This software is licensed as described in the file COPYING, which # * you should have received as part of this distribution. The terms @@ -24,7 +24,7 @@ # It extracts all ca certs it finds in the local Firefox database and converts # them all into PEM format. # -db=`ls -1d $HOME/.mozilla/firefox/*default*` +db=`ls -1d $HOME/.mozilla/firefox/*default` out=$1 if test -z "$out"; then diff --git a/lib/formdata.c b/lib/formdata.c index 9e8ce4ea0..73d3b6d72 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,12 +34,14 @@ #include "formdata.h" #include "vtls/vtls.h" #include "strequal.h" +#include "curl_memory.h" #include "sendf.h" #include "strdup.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" #ifndef HAVE_BASENAME @@ -415,7 +417,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, else { form = AddFormInfo(fname, NULL, current_form); if(!form) { - free(fname); + Curl_safefree(fname); return_value = CURL_FORMADD_MEMORY; } else { @@ -504,7 +506,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, else { form = AddFormInfo(NULL, type, current_form); if(!form) { - free(type); + Curl_safefree(type); return_value = CURL_FORMADD_MEMORY; } else { @@ -711,7 +713,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, now by the httppost linked list */ while(first_form) { FormInfo *ptr = first_form->more; - free(first_form); + Curl_safefree(first_form); first_form = ptr; } @@ -756,7 +758,7 @@ curl_off_t VmsRealFileSize(const char * name, int ret_stat; FILE * file; - file = fopen(name, "r"); /* VMS */ + file = fopen(name, "r"); if(file == NULL) return 0; @@ -969,16 +971,19 @@ void curl_formfree(struct curl_httppost *form) next=form->next; /* the following form line */ /* recurse to sub-contents */ - curl_formfree(form->more); + if(form->more) + curl_formfree(form->more); - if(!(form->flags & HTTPPOST_PTRNAME)) + if(!(form->flags & HTTPPOST_PTRNAME) && form->name) free(form->name); /* free the name */ if(!(form->flags & - (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) - ) + (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) && + form->contents) free(form->contents); /* free the contents */ - free(form->contenttype); /* free the content type */ - free(form->showfilename); /* free the faked file name */ + if(form->contenttype) + free(form->contenttype); /* free the content type */ + if(form->showfilename) + free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ } while((form = next) != NULL); /* continue */ @@ -1068,7 +1073,7 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file, /* filename need be escaped */ filename_escaped = malloc(strlen(filename)*2+1); if(!filename_escaped) { - free(filebasename); + Curl_safefree(filebasename); return CURLE_OUT_OF_MEMORY; } p0 = filename_escaped; @@ -1084,8 +1089,8 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file, result = AddFormDataf(form, size, "; filename=\"%s\"", filename); - free(filename_escaped); - free(filebasename); + Curl_safefree(filename_escaped); + Curl_safefree(filebasename); return result; } @@ -1135,7 +1140,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data, boundary); if(result) { - free(boundary); + Curl_safefree(boundary); return result; } /* we DO NOT include that line in the total size of the POST, since it'll be @@ -1178,7 +1183,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data, /* If used, this is a link to more file names, we must then do the magic to include several files with the same field name */ - free(fileboundary); + Curl_safefree(fileboundary); fileboundary = formboundary(data); if(!fileboundary) { result = CURLE_OUT_OF_MEMORY; @@ -1331,15 +1336,15 @@ CURLcode Curl_getformdata(struct SessionHandle *data, if(result) { Curl_formclean(&firstform); - free(fileboundary); - free(boundary); + Curl_safefree(fileboundary); + Curl_safefree(boundary); return result; } *sizep = size; - free(fileboundary); - free(boundary); + Curl_safefree(fileboundary); + Curl_safefree(boundary); *finalform = firstform; @@ -1385,7 +1390,7 @@ static FILE * vmsfopenread(const char *file, const char *mode) { case FAB$C_VAR: case FAB$C_VFC: case FAB$C_STMCR: - return fopen(file, "r"); /* VMS */ + return fopen(file, "r"); break; default: return fopen(file, "r", "rfm=stmlf", "ctx=stm"); @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -77,7 +77,9 @@ #include "warnless.h" #include "http_proxy.h" #include "non-ascii.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -283,17 +285,19 @@ static void freedirs(struct ftp_conn *ftpc) int i; if(ftpc->dirs) { for(i=0; i < ftpc->dirdepth; i++) { - free(ftpc->dirs[i]); - ftpc->dirs[i]=NULL; + if(ftpc->dirs[i]) { + free(ftpc->dirs[i]); + ftpc->dirs[i]=NULL; + } } free(ftpc->dirs); ftpc->dirs = NULL; ftpc->dirdepth = 0; } - Curl_safefree(ftpc->file); - - /* no longer of any use */ - Curl_safefree(ftpc->newhost); + if(ftpc->file) { + free(ftpc->file); + ftpc->file = NULL; + } } /* Returns non-zero if the given string contains CR (\r) or LF (\n), @@ -1101,7 +1105,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", Curl_strerror(conn, SOCKERRNO) ); - free(addr); + Curl_safefree(addr); return CURLE_FTP_PORT_FAILED; } switch(sa->sa_family) { @@ -1133,11 +1137,11 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(res == NULL) { failf(data, "failed to resolve the address provided to PORT: %s", host); - free(addr); + Curl_safefree(addr); return CURLE_FTP_PORT_FAILED; } - free(addr); + Curl_safefree(addr); host = NULL; /* step 2, create a socket for the requested address */ @@ -1491,13 +1495,13 @@ static CURLcode ftp_state_list(struct connectdata *conn) The other ftp_filemethods will CWD into dir/dir/ first and then just do LIST (in that case: nothing to do here) */ - char *cmd, *lstArg, *slashPos; + char *cmd,*lstArg,*slashPos; lstArg = NULL; if((data->set.ftp_filemethod == FTPFILE_NOCWD) && data->state.path && data->state.path[0] && - strchr(data->state.path, '/')) { + strchr(data->state.path,'/')) { lstArg = strdup(data->state.path); if(!lstArg) @@ -1507,7 +1511,7 @@ static CURLcode ftp_state_list(struct connectdata *conn) if(lstArg[strlen(lstArg) - 1] != '/') { /* chop off the file part if format is dir/dir/file */ - slashPos = strrchr(lstArg, '/'); + slashPos = strrchr(lstArg,'/'); if(slashPos) *(slashPos+1) = '\0'; } @@ -1521,13 +1525,16 @@ static CURLcode ftp_state_list(struct connectdata *conn) lstArg? lstArg: "" ); if(!cmd) { - free(lstArg); + if(lstArg) + free(lstArg); return CURLE_OUT_OF_MEMORY; } result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); - free(lstArg); + if(lstArg) + free(lstArg); + free(cmd); if(result) @@ -1670,8 +1677,8 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, BUFSIZE : curlx_sotouz(data->state.resume_from - passed); size_t actuallyread = - data->set.fread_func(data->state.buffer, 1, readthisamountnow, - data->set.in); + conn->fread_func(data->state.buffer, 1, readthisamountnow, + conn->fread_in); passed += actuallyread; if((actuallyread == 0) || (actuallyread > readthisamountnow)) { @@ -1808,13 +1815,6 @@ static CURLcode ftp_state_quote(struct connectdata *conn, static CURLcode ftp_epsv_disable(struct connectdata *conn) { CURLcode result = CURLE_OK; - - if(conn->bits.ipv6) { - /* We can't disable EPSV when doing IPv6, so this is instead a fail */ - failf(conn->data, "Failed EPSV attempt, exiting\n"); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); /* disable it for next transfer */ conn->bits.ftp_use_epsv = FALSE; @@ -1887,7 +1887,7 @@ static CURLcode proxy_magic(struct connectdata *conn, memset(&http_proxy, 0, sizeof(http_proxy)); data->req.protop = &http_proxy; - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); data->req.protop = ftp_save; @@ -1906,22 +1906,6 @@ static CURLcode proxy_magic(struct connectdata *conn, return result; } -static char *control_address(struct connectdata *conn) -{ - /* Returns the control connection IP address. - If a proxy tunnel is used, returns the original host name instead, because - the effective control connection address is the proxy address, - not the ftp host. */ - if(conn->bits.tunnel_proxy || - conn->proxytype == CURLPROXY_SOCKS5 || - conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || - conn->proxytype == CURLPROXY_SOCKS4 || - conn->proxytype == CURLPROXY_SOCKS4A) - return conn->host.name; - - return conn->ip_addr_str; -} - static CURLcode ftp_state_pasv_resp(struct connectdata *conn, int ftpcode) { @@ -1933,9 +1917,6 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, unsigned short connectport; /* the local port connect() should use! */ char *str=&data->state.buffer[4]; /* start on the first letter */ - /* if we come here again, make sure the former name is cleared */ - Curl_safefree(ftpc->newhost); - if((ftpc->count1 == 0) && (ftpcode == 229)) { /* positive EPSV response */ @@ -1944,12 +1925,12 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, unsigned int num; char separator[4]; ptr++; - if(5 == sscanf(ptr, "%c%c%c%u%c", - &separator[0], - &separator[1], - &separator[2], - &num, - &separator[3])) { + if(5 == sscanf(ptr, "%c%c%c%u%c", + &separator[0], + &separator[1], + &separator[2], + &num, + &separator[3])) { const char sep1 = separator[0]; int i; @@ -1967,9 +1948,19 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, } if(ptr) { ftpc->newport = (unsigned short)(num & 0xffff); - ftpc->newhost = strdup(control_address(conn)); - if(!ftpc->newhost) - return CURLE_OUT_OF_MEMORY; + + if(conn->bits.tunnel_proxy || + conn->proxytype == CURLPROXY_SOCKS5 || + conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || + conn->proxytype == CURLPROXY_SOCKS4 || + conn->proxytype == CURLPROXY_SOCKS4A) + /* proxy tunnel -> use other host info because ip_addr_str is the + proxy address not the ftp host */ + snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", + conn->host.name); + else + /* use the same IP we are already connected to */ + snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str); } } else @@ -1997,8 +1988,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, */ while(*str) { if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d", - &ip[0], &ip[1], &ip[2], &ip[3], - &port[0], &port[1])) + &ip[0], &ip[1], &ip[2], &ip[3], + &port[0], &port[1])) break; str++; } @@ -2010,19 +2001,26 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, /* we got OK from server */ if(data->set.ftp_skip_ip) { - /* told to ignore the remotely given IP but instead use the host we used + /* told to ignore the remotely given IP but instead use the one we used for the control connection */ - infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n", + infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n", ip[0], ip[1], ip[2], ip[3], - conn->host.name); - ftpc->newhost = strdup(control_address(conn)); + conn->ip_addr_str); + if(conn->bits.tunnel_proxy || + conn->proxytype == CURLPROXY_SOCKS5 || + conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || + conn->proxytype == CURLPROXY_SOCKS4 || + conn->proxytype == CURLPROXY_SOCKS4A) + /* proxy tunnel -> use other host info because ip_addr_str is the + proxy address not the ftp host */ + snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name); + else + snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", + conn->ip_addr_str); } else - ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - - if(!ftpc->newhost) - return CURLE_OUT_OF_MEMORY; - + snprintf(ftpc->newhost, sizeof(ftpc->newhost), + "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); } else if(ftpc->count1 == 0) { @@ -2073,8 +2071,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; result = Curl_connecthost(conn, addr); + Curl_resolv_unlock(data, addr); /* we're done using this address */ + if(result) { - Curl_resolv_unlock(data, addr); /* we're done using this address */ if(ftpc->count1 == 0 && ftpcode == 229) return ftp_epsv_disable(conn); @@ -2090,9 +2089,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, if(data->set.verbose) /* this just dumps information about this second connection */ - ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport); - Curl_resolv_unlock(data, addr); /* we're done using this address */ conn->bits.do_more = TRUE; state(conn, FTP_STOP); /* this phase is completed */ @@ -2107,9 +2105,7 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn, ftpport fcmd = (ftpport)ftpc->count1; CURLcode result = CURLE_OK; - /* The FTP spec tells a positive response should have code 200. - Be more permissive here to tolerate deviant servers. */ - if(ftpcode / 100 != 2) { + if(ftpcode != 200) { /* the command failed */ if(EPRT == fcmd) { @@ -3273,7 +3269,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, } /* now store a copy of the directory we are in */ - free(ftpc->prevpath); + if(ftpc->prevpath) + free(ftpc->prevpath); if(data->set.wildcardmatch) { if(data->set.chunk_end && ftpc->file) { @@ -3322,7 +3319,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, /* shut down the socket to inform the server we're done */ #ifdef _WIN32_WCE - shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ + shutdown(conn->sock[SECONDARYSOCKET],2); /* SD_BOTH */ #endif if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { @@ -3645,7 +3642,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port aren't used so we blank their arguments. TODO: make this nicer */ - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); return result; } @@ -3819,7 +3816,7 @@ static void wc_data_dtor(void *ptr) struct ftp_wc_tmpdata *tmp = ptr; if(tmp) Curl_ftp_parselist_data_free(&tmp->parser); - free(tmp); + Curl_safefree(tmp); } static CURLcode init_wc_data(struct connectdata *conn) @@ -3873,7 +3870,7 @@ static CURLcode init_wc_data(struct connectdata *conn) ftp_tmp->parser = Curl_ftp_parselist_data_alloc(); if(!ftp_tmp->parser) { Curl_safefree(wildcard->pattern); - free(ftp_tmp); + Curl_safefree(ftp_tmp); return CURLE_OUT_OF_MEMORY; } @@ -4099,7 +4096,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, result = Curl_convert_to_network(conn->data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ if(result) - return result; + return(result); for(;;) { #ifdef HAVE_GSSAPI @@ -4198,10 +4195,14 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) } freedirs(ftpc); - free(ftpc->prevpath); - ftpc->prevpath = NULL; - free(ftpc->server_os); - ftpc->server_os = NULL; + if(ftpc->prevpath) { + free(ftpc->prevpath); + ftpc->prevpath = NULL; + } + if(ftpc->server_os) { + free(ftpc->server_os); + ftpc->server_os = NULL; + } Curl_pp_disconnect(pp); @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, 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 @@ -147,10 +147,11 @@ struct ftp_conn { curl_off_t known_filesize; /* file size is different from -1, if wildcard LIST parsing was done and wc_statemach set it */ - /* newhost is the (allocated) IP addr or host name to connect the data - connection to */ - char *newhost; /* this is the pair to connect the DATA... */ - unsigned short newport; /* connection to */ + /* newhost must be able to hold a full IP-style address in ASCII, which + in the IPv6 case means 5*8-1 = 39 letters */ +#define NEWHOST_BUFSIZE 48 + char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */ + unsigned short newport; /* connection to */ }; diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 17e0a66f8..9aacad914 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,6 +49,10 @@ #include "ftp.h" #include "ftplistparser.h" #include "curl_fnmatch.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -187,7 +191,8 @@ struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data) { - free(*pl_data); + if(*pl_data) + free(*pl_data); *pl_data = NULL; } diff --git a/lib/getinfo.c b/lib/getinfo.c index 910f520ed..0ffdd74a0 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,12 +27,12 @@ #include "urldata.h" #include "getinfo.h" +#include "curl_memory.h" #include "vtls/vtls.h" #include "connect.h" /* Curl_getconnectinfo() */ #include "progress.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* Make this the last #include */ #include "memdebug.h" /* @@ -58,7 +58,8 @@ CURLcode Curl_initinfo(struct SessionHandle *data) info->filetime = -1; /* -1 is an illegal time and thus means unknown */ info->timecond = FALSE; - free(info->contenttype); + if(info->contenttype) + free(info->contenttype); info->contenttype = NULL; info->header_size = 0; @@ -305,7 +306,7 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info, break; /* no SSL session found */ /* Return the TLS session information from the relevant backend */ -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY internals = conn->ssl[sockindex].ctx; #endif #ifdef USE_GNUTLS diff --git a/lib/gopher.c b/lib/gopher.c index 954cad8e0..f3fd06533 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -36,6 +36,10 @@ #include "select.h" #include "url.h" #include "warnless.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -120,7 +124,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) if(!result) { /* Which may not have written it all! */ result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); if(result) { - free(sel_org); + Curl_safefree(sel_org); return result; } k -= amount; @@ -130,7 +134,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) } else { failf(data, "Failed sending Gopher request"); - free(sel_org); + Curl_safefree(sel_org); return result; } /* Don't busyloop. The entire loop thing is a work-around as it causes a @@ -145,7 +149,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100); } - free(sel_org); + Curl_safefree(sel_org); /* We can use Curl_sendf to send the terminal \r\n relatively safely and save allocing another string/doing another _write loop. */ diff --git a/lib/hash.c b/lib/hash.c index c46760ae1..4a12e1a7b 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,6 +24,10 @@ #include "hash.h" #include "llist.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -89,6 +93,32 @@ Curl_hash_init(struct curl_hash *h, } } +struct curl_hash * +Curl_hash_alloc(int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor) +{ + struct curl_hash *h; + + if(!slots || !hfunc || !comparator ||!dtor) { + return NULL; /* failure */ + } + + h = malloc(sizeof(struct curl_hash)); + if(h) { + if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) { + /* failure */ + free(h); + h = NULL; + } + } + + return h; +} + + + static struct curl_hash_element * mk_hash_element(const void *key, size_t key_len, const void *p) { @@ -212,11 +242,8 @@ Curl_hash_apply(curl_hash *h, void *user, } #endif -/* Destroys all the entries in the given hash and resets its attributes, - * prepping the given hash for [static|dynamic] deallocation. - */ void -Curl_hash_destroy(struct curl_hash *h) +Curl_hash_clean(struct curl_hash *h) { int i; @@ -230,17 +257,6 @@ Curl_hash_destroy(struct curl_hash *h) h->slots = 0; } -/* Removes all the entries in the given hash. - * - * @unittest: 1602 - */ -void -Curl_hash_clean(struct curl_hash *h) -{ - Curl_hash_clean_with_criterium(h, NULL, NULL); -} - -/* Cleans all entries that pass the comp function criteria. */ void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, int (*comp)(void *, void *)) @@ -260,7 +276,7 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, struct curl_hash_element *he = le->ptr; lnext = le->next; /* ask the callback function if we shall remove this entry or not */ - if(comp == NULL || comp(user, he->ptr)) { + if(comp(user, he->ptr)) { Curl_llist_remove(list, le, (void *) h); --h->size; /* one less entry in the hash now */ } @@ -269,6 +285,17 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, } } +void +Curl_hash_destroy(struct curl_hash *h) +{ + if(!h) + return; + + Curl_hash_clean(h); + + free(h); +} + size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) { const char* key_str = (const char *) key; @@ -283,11 +310,16 @@ size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) return (h % slots_num); } -size_t Curl_str_key_compare(void *k1, size_t key1_len, - void *k2, size_t key2_len) +size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len) { - if((key1_len == key2_len) && !memcmp(k1, k2, key1_len)) + char *key1 = (char *)k1; + char *key2 = (char *)k2; + + if(key1_len == key2_len && + *key1 == *key2 && + memcmp(key1, key2, key1_len) == 0) { return 1; + } return 0; } diff --git a/lib/hash.h b/lib/hash.h index b13a236bb..aa935d4eb 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2007, 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 @@ -74,16 +74,22 @@ int Curl_hash_init(struct curl_hash *h, comp_function comparator, curl_hash_dtor dtor); +struct curl_hash *Curl_hash_alloc(int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len); void Curl_hash_apply(struct curl_hash *h, void *user, void (*cb)(void *user, void *ptr)); int Curl_hash_count(struct curl_hash *h); -void Curl_hash_destroy(struct curl_hash *h); void Curl_hash_clean(struct curl_hash *h); void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, int (*comp)(void *, void *)); +void Curl_hash_destroy(struct curl_hash *h); + size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num); size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len); diff --git a/lib/hmac.c b/lib/hmac.c index 0d2d5f45d..dace82037 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,6 +27,10 @@ #ifndef CURL_DISABLE_CRYPTO_AUTH #include "curl_hmac.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/hostasyn.c b/lib/hostasyn.c index 17b8be072..3cf800430 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,6 +47,10 @@ #include "share.h" #include "strerror.h" #include "url.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -119,21 +123,21 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, CURLcode Curl_async_resolved(struct connectdata *conn, bool *protocol_done) { - CURLcode result; + CURLcode code; if(conn->async.dns) { conn->dns_entry = conn->async.dns; conn->async.dns = NULL; } - result = Curl_setup_conn(conn, protocol_done); + code = Curl_setup_conn(conn, protocol_done); - if(result) + if(code) /* We're not allowed to return failure with memory left allocated in the connectdata struct, free those here */ Curl_disconnect(conn, FALSE); /* close the connection */ - return result; + return code; } /* diff --git a/lib/hostcheck.c b/lib/hostcheck.c index 62a26e4f2..21af8fa1c 100644 --- a/lib/hostcheck.c +++ b/lib/hostcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,7 +22,7 @@ #include "curl_setup.h" -#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT) +#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_GSKIT) /* these backends use functions from this file */ #ifdef HAVE_NETINET_IN_H @@ -144,4 +144,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) return res; } -#endif /* OPENSSL or AXTLS or GSKIT */ +#endif /* SSLEAY or AXTLS or GSKIT */ diff --git a/lib/hostip.c b/lib/hostip.c index 82f3897f9..2ea0ab648 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -56,7 +56,10 @@ #include "url.h" #include "inet_ntop.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -137,7 +140,11 @@ struct curl_hash *Curl_global_host_cache_init(void) void Curl_global_host_cache_dtor(void) { if(host_cache_initialized) { - Curl_hash_destroy(&hostname_cache); + /* first make sure that any custom "CURLOPT_RESOLVE" names are + cleared off */ + Curl_hostcache_clean(NULL, &hostname_cache); + /* then free the remaining hash completely */ + Curl_hash_clean(&hostname_cache); host_cache_initialized = 0; } } @@ -230,8 +237,7 @@ hostcache_timestamp_remove(void *datap, void *hc) (struct hostcache_prune_data *) datap; struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; - return (0 != c->timestamp) - && (data->now - c->timestamp >= data->cache_timeout); + return !c->inuse && (data->now - c->timestamp >= data->cache_timeout); } /* @@ -277,54 +283,40 @@ void Curl_hostcache_prune(struct SessionHandle *data) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); } -#ifdef HAVE_SIGSETJMP -/* Beware this is a global and unique instance. This is used to store the - return address that we can jump back to from inside a signal handler. This - is not thread-safe stuff. */ -sigjmp_buf curl_jmpenv; -#endif - -/* lookup address, returns entry if found and not stale */ -static struct Curl_dns_entry * -fetch_addr(struct connectdata *conn, - const char *hostname, - int port) +/* + * Check if the entry should be pruned. Assumes a locked cache. + */ +static int +remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns) { - char *entry_id = NULL; - struct Curl_dns_entry *dns = NULL; - size_t entry_len; - struct SessionHandle *data = conn->data; + struct hostcache_prune_data user; - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return dns; + if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache || + dns->inuse) + /* cache forever means never prune, and NULL hostcache means we can't do + it, if it still is in use then we leave it */ + return 0; - entry_len = strlen(entry_id); + time(&user.now); + user.cache_timeout = data->set.dns_cache_timeout; - /* See if its already in our dns cache */ - dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); - - if(dns && (data->set.dns_cache_timeout != -1)) { - /* See whether the returned entry is stale. Done before we release lock */ - struct hostcache_prune_data user; + if(!hostcache_timestamp_remove(&user,dns) ) + return 0; - time(&user.now); - user.cache_timeout = data->set.dns_cache_timeout; + Curl_hash_clean_with_criterium(data->dns.hostcache, + (void *) &user, + hostcache_timestamp_remove); - if(hostcache_timestamp_remove(&user, dns)) { - infof(data, "Hostname in DNS cache was stale, zapped\n"); - dns = NULL; /* the memory deallocation is being handled by the hash */ - Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); - } - } + return 1; +} - /* free the allocated entry_id again */ - free(entry_id); - return dns; -} +#ifdef HAVE_SIGSETJMP +/* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ +sigjmp_buf curl_jmpenv; +#endif /* * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. @@ -336,27 +328,38 @@ fetch_addr(struct connectdata *conn, * lookups for the same hostname requested by different handles. * * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. - * - * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after - * use, or we'll leak memory! */ struct Curl_dns_entry * Curl_fetch_addr(struct connectdata *conn, const char *hostname, int port) { - struct SessionHandle *data = conn->data; + char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; + size_t entry_len; + struct SessionHandle *data = conn->data; + int stale; - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + /* Create an entry id, based upon the hostname and port */ + entry_id = create_hostcache_id(hostname, port); + /* If we can't create the entry id, fail */ + if(!entry_id) + return dns; - dns = fetch_addr(conn, hostname, port); + entry_len = strlen(entry_id); - if(dns) dns->inuse++; /* we use it! */ + /* See if its already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + /* free the allocated entry_id again */ + free(entry_id); + + /* See whether the returned entry is stale. Done before we release lock */ + stale = remove_entry_if_stale(data, dns); + if(stale) { + infof(data, "Hostname in DNS cache was stale, zapped\n"); + dns = NULL; /* the memory deallocation is being handled by the hash */ + } return dns; } @@ -395,11 +398,11 @@ Curl_cache_addr(struct SessionHandle *data, return NULL; } - dns->inuse = 1; /* the cache has the first reference */ + dns->inuse = 0; /* init to not used */ dns->addr = addr; /* this is the address(es) */ time(&dns->timestamp); if(dns->timestamp == 0) - dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */ + dns->timestamp = 1; /* zero indicates that entry isn't in hash table */ /* Store the resolved data in our DNS cache. */ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1, @@ -455,7 +458,7 @@ int Curl_resolv(struct connectdata *conn, if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - dns = fetch_addr(conn, hostname, port); + dns = Curl_fetch_addr(conn, hostname, port); if(dns) { infof(data, "Hostname %s was found in DNS cache\n", hostname); @@ -607,6 +610,32 @@ int Curl_resolv_timeout(struct connectdata *conn, we want to wait less than one second we must bail out already now. */ return CURLRESOLV_TIMEDOUT; + /************************************************************* + * Set signal handler to catch SIGALRM + * Store the old value to be able to set it back later! + *************************************************************/ +#ifdef HAVE_SIGACTION + sigaction(SIGALRM, NULL, &sigact); + keep_sigact = sigact; + keep_copysig = TRUE; /* yes, we have a copy */ + sigact.sa_handler = alarmfunc; +#ifdef SA_RESTART + /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ + sigact.sa_flags &= ~SA_RESTART; +#endif + /* now set the new struct */ + sigaction(SIGALRM, &sigact, NULL); +#else /* HAVE_SIGACTION */ + /* no sigaction(), revert to the much lamer signal() */ +#ifdef HAVE_SIGNAL + keep_sigact = signal(SIGALRM, alarmfunc); +#endif +#endif /* HAVE_SIGACTION */ + + /* alarm() makes a signal get sent when the timeout fires off, and that + will abort system calls */ + prev_alarm = alarm(curlx_sltoui(timeout/1000L)); + /* This allows us to time-out from the name resolver, as the timeout will generate a signal and we will siglongjmp() from that here. This technique has problems (see alarmfunc). @@ -619,33 +648,6 @@ int Curl_resolv_timeout(struct connectdata *conn, rc = CURLRESOLV_ERROR; goto clean_up; } - else { - /************************************************************* - * Set signal handler to catch SIGALRM - * Store the old value to be able to set it back later! - *************************************************************/ -#ifdef HAVE_SIGACTION - sigaction(SIGALRM, NULL, &sigact); - keep_sigact = sigact; - keep_copysig = TRUE; /* yes, we have a copy */ - sigact.sa_handler = alarmfunc; -#ifdef SA_RESTART - /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ - sigact.sa_flags &= ~SA_RESTART; -#endif - /* now set the new struct */ - sigaction(SIGALRM, &sigact, NULL); -#else /* HAVE_SIGACTION */ - /* no sigaction(), revert to the much lamer signal() */ -#ifdef HAVE_SIGNAL - keep_sigact = signal(SIGALRM, alarmfunc); -#endif -#endif /* HAVE_SIGACTION */ - - /* alarm() makes a signal get sent when the timeout fires off, and that - will abort system calls */ - prev_alarm = alarm(curlx_sltoui(timeout/1000L)); - } #else #ifndef CURLRES_ASYNCH @@ -717,37 +719,54 @@ clean_up: */ void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) { + DEBUGASSERT(dns && (dns->inuse>0)); + if(data && data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - freednsentry(dns); + dns->inuse--; + /* only free if nobody is using AND it is not in hostcache (timestamp == + 0) */ + if(dns->inuse == 0 && dns->timestamp == 0) { + Curl_freeaddrinfo(dns->addr); + free(dns); + } if(data && data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); } /* - * File-internal: release cache dns entry reference, free if inuse drops to 0 + * File-internal: free a cache dns entry. */ static void freednsentry(void *freethis) { - struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis; - DEBUGASSERT(dns && (dns->inuse>0)); + struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis; - dns->inuse--; - if(dns->inuse == 0) { - Curl_freeaddrinfo(dns->addr); - free(dns); + /* mark the entry as not in hostcache */ + p->timestamp = 0; + if(p->inuse == 0) { + Curl_freeaddrinfo(p->addr); + free(p); } } /* - * Curl_mk_dnscache() inits a new DNS cache and returns success/failure. + * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it. */ -int Curl_mk_dnscache(struct curl_hash *hash) +struct curl_hash *Curl_mk_dnscache(void) { - return Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare, - freednsentry); + return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry); +} + +static int hostcache_inuse(void *data, void *hc) +{ + struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; + + if(c->inuse == 1) + Curl_resolv_unlock(data, c); + + return 1; /* free all entries */ } /* @@ -760,13 +779,11 @@ int Curl_mk_dnscache(struct curl_hash *hash) void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash) { - if(data && data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - Curl_hash_clean(hash); - - if(data && data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + /* Entries added to the hostcache with the CURLOPT_RESOLVE function are + * still present in the cache with the inuse counter set to 1. Detect them + * and cleanup! + */ + Curl_hash_clean_with_criterium(hash, data, hostcache_inuse); } @@ -781,52 +798,18 @@ CURLcode Curl_loadhostpairs(struct SessionHandle *data) if(!hostp->data) continue; if(hostp->data[0] == '-') { - char *entry_id; - size_t entry_len; - - if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { - infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", - hostp->data); - continue; - } - - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) { - return CURLE_OUT_OF_MEMORY; - } - - entry_len = strlen(entry_id); - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - /* delete entry, ignore if it didn't exist */ - Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - /* free the allocated entry_id again */ - free(entry_id); + /* TODO: mark an entry for removal */ } - else { + else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, + address)) { struct Curl_dns_entry *dns; Curl_addrinfo *addr; char *entry_id; size_t entry_len; - if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, - address)) { - infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", - hostp->data); - continue; - } - addr = Curl_str2addr(address, port); if(!addr) { - infof(data, "Address in '%s' found illegal!\n", hostp->data); + infof(data, "Resolve %s found illegal!\n", hostp->data); continue; } @@ -849,16 +832,9 @@ CURLcode Curl_loadhostpairs(struct SessionHandle *data) /* free the allocated entry_id again */ free(entry_id); - if(!dns) { + if(!dns) /* if not in the cache already, put this host in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); - if(dns) { - dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ - /* release the returned reference; the cache itself will keep the - * entry alive: */ - dns->inuse--; - } - } else /* this is a duplicate, free it again */ Curl_freeaddrinfo(addr); diff --git a/lib/hostip.h b/lib/hostip.h index d5b44bc9e..e1e880eab 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -65,10 +65,11 @@ void Curl_global_host_cache_dtor(void); struct Curl_dns_entry { Curl_addrinfo *addr; - /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + /* timestamp == 0 -- entry not in hostcache + timestamp != 0 -- entry is in hostcache */ time_t timestamp; - /* use-counter, use Curl_resolv_unlock to release reference */ - long inuse; + long inuse; /* use-counter, make very sure you decrease this + when you're done using the address you received */ }; /* @@ -124,8 +125,8 @@ void Curl_resolv_unlock(struct SessionHandle *data, /* for debugging purposes only: */ void Curl_scan_cache_used(void *user, void *ptr); -/* init a new dns cache and return success */ -int Curl_mk_dnscache(struct curl_hash *hash); +/* make a new dns cache and return the handle */ +struct curl_hash *Curl_mk_dnscache(void); /* prune old entries from the DNS cache */ void Curl_hostcache_prune(struct SessionHandle *data); @@ -174,9 +175,6 @@ const char *Curl_printable_address(const Curl_addrinfo *ip, * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. * * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. - * - * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after - * use, or we'll leak memory! */ struct Curl_dns_entry * Curl_fetch_addr(struct connectdata *conn, diff --git a/lib/hostip4.c b/lib/hostip4.c index 37b036911..3a05d1077 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -48,7 +48,10 @@ #include "strerror.h" #include "url.h" #include "inet_pton.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/hostip6.c b/lib/hostip6.c index 6ab131a8c..bb723912a 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,7 +49,10 @@ #include "url.h" #include "inet_pton.h" #include "connect.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/hostsyn.c b/lib/hostsyn.c index fb1de35ce..4ad3c63da 100644 --- a/lib/hostsyn.c +++ b/lib/hostsyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,6 +47,10 @@ #include "share.h" #include "strerror.h" #include "url.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/http.c b/lib/http.c index 9817d72af..ee0a9a481 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -63,6 +63,7 @@ #include "share.h" #include "hostip.h" #include "http.h" +#include "curl_memory.h" #include "select.h" #include "parsedate.h" /* for the week day and month names */ #include "strtoofft.h" @@ -72,14 +73,15 @@ #include "http_proxy.h" #include "warnless.h" #include "non-ascii.h" -#include "conncache.h" +#include "bundles.h" #include "pipeline.h" #include "http2.h" #include "connect.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -153,18 +155,12 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn) { /* allocate the HTTP-specific struct for the SessionHandle, only to survive during this request */ - struct HTTP *http; DEBUGASSERT(conn->data->req.protop == NULL); - http = calloc(1, sizeof(struct HTTP)); - if(!http) + conn->data->req.protop = calloc(1, sizeof(struct HTTP)); + if(!conn->data->req.protop) return CURLE_OUT_OF_MEMORY; - conn->data->req.protop = http; - - Curl_http2_setup_conn(conn); - Curl_http2_setup_req(conn->data); - return CURLE_OK; } @@ -307,7 +303,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) if(!authorization) return CURLE_REMOTE_ACCESS_DENIED; - free(*userp); + Curl_safefree(*userp); *userp = aprintf("%sAuthorization: Basic %s\r\n", proxy?"Proxy-":"", authorization); @@ -351,6 +347,82 @@ static bool pickoneauth(struct auth *pick) return picked; } +/* whether to complete request (for authentication) in current connection */ +static bool complete_request(struct connectdata *conn, + curl_off_t remaining_bytes) +{ +#if defined(USE_NTLM) || defined(USE_SPNEGO) + struct SessionHandle *data = conn->data; + bool have_ntlm_or_negotiate = FALSE; + bool auth_started = FALSE; + + /* don't reset connection when we're in NTLM or Negotiate authentication; + * those authenticate the connection - creating a new connection breaks the + * authentication. + */ + +#if defined(USE_NTLM) + /* proxy NTLM authentication */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_WB)) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (conn->proxyntlm.state != NTLMSTATE_NONE); + } + + /* normal NTLM authentication */ + if((data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (conn->ntlm.state != NTLMSTATE_NONE); + } +#endif + +#if defined(USE_SPNEGO) + /* proxy Negotiate authentication */ + if(data->state.authproxy.picked == CURLAUTH_NEGOTIATE) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (data->state.proxyneg.state != GSS_AUTHNONE); + } + + /* normal Negotiate authentication */ + if(data->state.authhost.picked == CURLAUTH_NEGOTIATE) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (data->state.negotiate.state != GSS_AUTHNONE); + } +#endif + + if(have_ntlm_or_negotiate) { + if(remaining_bytes < 2000 || auth_started) { + /* NTLM/Negotiation has started *OR* there is just a little (<2K) + * data left to send, keep on sending. + */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return TRUE; + } + + infof(data, "NTLM/Negotiate send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + remaining_bytes); + } +#else + /* unused parameters: */ + (void)conn; + (void)remaining_bytes; +#endif + + return FALSE; +} + /* * Curl_http_perhapsrewind() * @@ -409,8 +481,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) /* figure out how much data we are expected to send */ switch(data->set.httpreq) { case HTTPREQ_POST: - if(data->state.infilesize != -1) - expectsend = data->state.infilesize; + if(data->set.postfieldsize != -1) + expectsend = data->set.postfieldsize; else if(data->set.postfields) expectsend = (curl_off_t)strlen(data->set.postfields); break; @@ -429,36 +501,12 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) conn->bits.rewindaftersend = FALSE; /* default */ if((expectsend == -1) || (expectsend > bytessent)) { -#if defined(USE_NTLM) - /* There is still data left to send */ - if((data->state.authproxy.picked == CURLAUTH_NTLM) || - (data->state.authhost.picked == CURLAUTH_NTLM) || - (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || - (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { - if(((expectsend - bytessent) < 2000) || - (conn->ntlm.state != NTLMSTATE_NONE) || - (conn->proxyntlm.state != NTLMSTATE_NONE)) { - /* The NTLM-negotiation has started *OR* there is just a little (<2K) - data left to send, keep on sending. */ - - /* rewind data when completely done sending! */ - if(!conn->bits.authneg) { - conn->bits.rewindaftersend = TRUE; - infof(data, "Rewind stream after send\n"); - } + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; - return CURLE_OK; - } - - if(conn->bits.close) - /* this is already marked to get closed */ - return CURLE_OK; - - infof(data, "NTLM send, close instead of sending %" - CURL_FORMAT_CURL_OFF_T " bytes\n", - (curl_off_t)(expectsend - bytessent)); - } -#endif + if(complete_request(conn, (curl_off_t)(expectsend - bytessent))) + return CURLE_OK; /* This is not NTLM or many bytes left to send: close */ connclose(conn, "Mid-auth HTTP and much data left to send"); @@ -469,7 +517,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) } if(bytessent) - /* we rewind now at once since if we already sent something */ + /* we rewind now at once since we already sent something */ return Curl_readrewind(conn); return CURLE_OK; @@ -685,7 +733,7 @@ Curl_http_output_auth(struct connectdata *conn, if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || conn->bits.user_passwd) - /* continue please */; + /* continue please */ ; else { authhost->done = TRUE; authproxy->done = TRUE; @@ -786,13 +834,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, while(*auth) { #ifdef USE_SPNEGO if(checkprefix("Negotiate", auth)) { + int neg; *availp |= CURLAUTH_NEGOTIATE; authp->avail |= CURLAUTH_NEGOTIATE; if(authp->picked == CURLAUTH_NEGOTIATE) { if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) { - CURLcode result = Curl_input_negotiate(conn, proxy, auth); - if(!result) { + neg = Curl_input_negotiate(conn, proxy, auth); + if(neg == 0) { DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->change.url); if(!data->req.newurl) @@ -1001,8 +1050,8 @@ static size_t readmoredata(char *buffer, /* move backup data into focus and continue on that */ http->postdata = http->backup.postdata; http->postsize = http->backup.postsize; - conn->data->set.fread_func = http->backup.fread_func; - conn->data->set.in = http->backup.fread_in; + conn->fread_func = http->backup.fread_func; + conn->fread_in = http->backup.fread_in; http->sending++; /* move one step up */ @@ -1033,16 +1082,6 @@ Curl_send_buffer *Curl_add_buffer_init(void) } /* - * Curl_add_buffer_free() frees all associated resources. - */ -void Curl_add_buffer_free(Curl_send_buffer *buff) -{ - if(buff) /* deal with NULL input */ - free(buff->buffer); - free(buff); -} - -/* * Curl_add_buffer_send() sends a header buffer and frees all associated * memory. Body data may be appended to the header data if desired. * @@ -1088,7 +1127,9 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, /* Curl_convert_to_network calls failf if unsuccessful */ if(result) { /* conversion failed, free memory and return to the caller */ - Curl_add_buffer_free(in); + if(in->buffer) + free(in->buffer); + free(in); return result; } @@ -1157,14 +1198,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, ptr = in->buffer + amount; /* backup the currently set pointers */ - http->backup.fread_func = conn->data->set.fread_func; - http->backup.fread_in = conn->data->set.in; + http->backup.fread_func = conn->fread_func; + http->backup.fread_in = conn->fread_in; http->backup.postdata = http->postdata; http->backup.postsize = http->postsize; /* set the new pointers for the request-sending */ - conn->data->set.fread_func = (curl_read_callback)readmoredata; - conn->data->set.in = (void *)conn; + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; http->postdata = ptr; http->postsize = (curl_off_t)size; @@ -1187,10 +1228,12 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, */ return CURLE_SEND_ERROR; else - Curl_pipeline_leave_write(conn); + conn->writechannel_inuse = FALSE; } } - Curl_add_buffer_free(in); + if(in->buffer) + free(in->buffer); + free(in); return result; } @@ -1213,7 +1256,8 @@ CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) return result; } /* If we failed, we cleanup the whole buffer and return error */ - free(in->buffer); + if(in->buffer) + free(in->buffer); free(in); return CURLE_OUT_OF_MEMORY; } @@ -1393,7 +1437,7 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) } #endif -#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) /* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only. It should be made to query the generic SSL layer instead. */ @@ -1432,7 +1476,7 @@ static int https_getsock(struct connectdata *conn, return GETSOCK_BLANK; } #endif /* USE_SSL */ -#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */ +#endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */ /* * Curl_http_done() gets called from Curl_done() after a single HTTP request @@ -1443,26 +1487,19 @@ CURLcode Curl_http_done(struct connectdata *conn, CURLcode status, bool premature) { struct SessionHandle *data = conn->data; - struct HTTP *http = data->req.protop; -#ifdef USE_NGHTTP2 - struct http_conn *httpc = &conn->proto.httpc; -#endif + struct HTTP *http =data->req.protop; Curl_unencode_cleanup(conn); #ifdef USE_SPNEGO if(data->state.proxyneg.state == GSS_AUTHSENT || - data->state.negotiate.state == GSS_AUTHSENT) { - /* add forbid re-use if http-code != 401/407 as a WA only needed for - * 401/407 that signal auth failure (empty) otherwise state will be RECV - * with current code */ - if((data->req.httpcode != 401) && (data->req.httpcode != 407)) - connclose(conn, "Negotiate transfer completed"); + data->state.negotiate.state == GSS_AUTHSENT) Curl_cleanup_negotiate(data); - } #endif /* set the proper values (possibly modified on POST) */ + conn->fread_func = data->set.fread_func; /* restore */ + conn->fread_in = data->set.in; /* restore */ conn->seek_func = data->set.seek_func; /* restore */ conn->seek_client = data->set.seek_client; /* restore */ @@ -1470,26 +1507,12 @@ CURLcode Curl_http_done(struct connectdata *conn, return CURLE_OK; if(http->send_buffer) { - Curl_add_buffer_free(http->send_buffer); - http->send_buffer = NULL; /* clear the pointer */ - } + Curl_send_buffer *buff = http->send_buffer; -#ifdef USE_NGHTTP2 - if(http->header_recvbuf) { - DEBUGF(infof(data, "free header_recvbuf!!\n")); - Curl_add_buffer_free(http->header_recvbuf); - http->header_recvbuf = NULL; /* clear the pointer */ - for(; http->push_headers_used > 0; --http->push_headers_used) { - free(http->push_headers[http->push_headers_used - 1]); - } - free(http->push_headers); - http->push_headers = NULL; - } - if(http->stream_id) { - nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0); - http->stream_id = 0; + free(buff->buffer); + free(buff); + http->send_buffer = NULL; /* clear the pointer */ } -#endif if(HTTPREQ_POST_FORM == data->set.httpreq) { data->req.bytecount = http->readbytecount + http->writebytecount; @@ -1553,11 +1576,10 @@ static CURLcode expect100(struct SessionHandle *data, const char *ptr; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if(use_http_1_1plus(data, conn) && - (conn->httpversion != 20)) { - /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an - Expect: 100-continue to the headers which actually speeds up post - operations (as there is one packet coming back from the web server) */ + if(use_http_1_1plus(data, conn)) { + /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: + 100-continue to the headers which actually speeds up post operations + (as there is one packet coming back from the web server) */ ptr = Curl_checkheaders(conn, "Expect:"); if(ptr) { data->state.expect100header = @@ -1776,8 +1798,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->httpversion < 20) { /* unless the connection is re-used and already http2 */ switch(conn->negnpn) { - case CURL_HTTP_VERSION_2_0: - conn->httpversion = 20; /* we know we're on HTTP/2 now */ + case NPN_HTTP2: result = Curl_http2_init(conn); if(result) return result; @@ -1790,7 +1811,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; break; - case CURL_HTTP_VERSION_1_1: + case NPN_HTTP1_1: /* continue with HTTP/1.1 when explicitly requested */ break; default: @@ -1808,8 +1829,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) http = data->req.protop; if(!data->state.this_is_a_follow) { - /* Free to avoid leaking memory on multiple requests*/ - free(data->state.first_host); + /* this is not a followed location, get the original host name */ + if(data->state.first_host) + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); data->state.first_host = strdup(conn->host.name); if(!data->state.first_host) @@ -1853,7 +1876,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ - if(Curl_checkheaders(conn, "User-Agent:")) { + if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) { free(conn->allocptr.uagent); conn->allocptr.uagent=NULL; } @@ -1996,14 +2019,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } #endif - if(strcmp("Host:", ptr)) { - conn->allocptr.host = aprintf("%s\r\n", ptr); - if(!conn->allocptr.host) - return CURLE_OUT_OF_MEMORY; - } - else - /* when clearing the header */ - conn->allocptr.host = NULL; + conn->allocptr.host = NULL; } else { /* When building Host: headers, we must put the host name within @@ -2198,7 +2214,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && !Curl_checkheaders(conn, "Range:")) { /* if a line like this was already allocated, free the previous one */ - free(conn->allocptr.rangeline); + if(conn->allocptr.rangeline) + free(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->state.range); } @@ -2206,7 +2223,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) !Curl_checkheaders(conn, "Content-Range:")) { /* if a line like this was already allocated, free the previous one */ - free(conn->allocptr.rangeline); + if(conn->allocptr.rangeline) + free(conn->allocptr.rangeline); if(data->set.set_resume_from < 0) { /* Upload resume was asked for, but we don't know the size of the @@ -2270,11 +2288,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_add_bufferf(req_buffer, "%s" /* ftp typecode (;type=x) */ " HTTP/%s\r\n" /* HTTP version */ - "%s" /* host */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ "%s" /* user agent */ + "%s" /* host */ "%s" /* accept */ "%s" /* TE: */ "%s" /* accept-encoding */ @@ -2284,7 +2302,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ftp_typecode, httpstring, - (conn->allocptr.host?conn->allocptr.host:""), conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", conn->allocptr.userpwd?conn->allocptr.userpwd:"", @@ -2294,6 +2311,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? conn->allocptr.uagent:"", + (conn->allocptr.host?conn->allocptr.host:""), http->p_accept?http->p_accept:"", conn->allocptr.te?conn->allocptr.te:"", (data->set.str[STRING_ENCODING] && @@ -2309,12 +2327,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) te ); - /* clear userpwd to avoid re-using credentials from re-used connections */ - Curl_safefree(conn->allocptr.userpwd); + /* + * Free userpwd for Negotiate/NTLM. Cannot reuse as it is associated with + * the connection and shouldn't be repeated over it either. + */ + switch (data->state.authhost.picked) { + case CURLAUTH_NEGOTIATE: + case CURLAUTH_NTLM: + case CURLAUTH_NTLM_WB: + Curl_safefree(conn->allocptr.userpwd); + break; + } /* - * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated - * with the connection and shouldn't be repeated over it either. + * Same for proxyuserpwd */ switch (data->state.authproxy.picked) { case CURLAUTH_NEGOTIATE: @@ -2434,14 +2460,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Get the currently set callback function pointer and store that in the form struct since we might want the actual user-provided callback later - on. The data->set.fread_func pointer itself will be changed for the + on. The conn->fread_func pointer itself will be changed for the multipart case to the function that returns a multipart formatted stream. */ - http->form.fread_func = data->set.fread_func; + http->form.fread_func = conn->fread_func; /* Set the read function to read from the generated form data */ - data->set.fread_func = (curl_read_callback)Curl_FormReader; - data->set.in = &http->form; + conn->fread_func = (curl_read_callback)Curl_FormReader; + conn->fread_in = &http->form; http->sending = HTTPSEND_BODY; @@ -2561,8 +2587,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) postsize = 0; else { /* figure out the size of the postfields */ - postsize = (data->state.infilesize != -1)? - data->state.infilesize: + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); } @@ -2659,8 +2685,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) http->sending = HTTPSEND_BODY; - data->set.fread_func = (curl_read_callback)readmoredata; - data->set.in = (void *)conn; + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); @@ -2685,7 +2711,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - else if(data->state.infilesize) { + else if(data->set.postfieldsize) { /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, postsize?postsize:-1); @@ -3076,19 +3102,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } - /* At this point we have some idea about the fate of the connection. - If we are closing the connection it may result auth failure. */ -#if defined(USE_NTLM) - if(conn->bits.close && - (((data->req.httpcode == 401) && - (conn->ntlm.state == NTLMSTATE_TYPE2)) || - ((data->req.httpcode == 407) && - (conn->proxyntlm.state == NTLMSTATE_TYPE2)))) { - infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); - data->state.authproblem = TRUE; - } -#endif - /* * When all the headers have been parsed, see if we should give * up and return an error. @@ -3366,23 +3379,28 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } else if(conn->httpversion == 20 || (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { - DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); - - /* HTTP/2 cannot blacklist multiplexing since it is a core - functionality of the protocol */ - conn->bundle->multiuse = BUNDLE_MULTIPLEX; + /* Don't enable pipelining for HTTP/2 or upgraded connection. For + HTTP/2, we do not support multiplexing. In general, requests + cannot be pipelined in upgraded connection, since it is now + different protocol. */ + DEBUGF(infof(data, + "HTTP 2 or upgraded connection do not support " + "pipelining for now\n")); } else if(conn->httpversion >= 11 && !conn->bits.close) { + struct connectbundle *cb_ptr; + /* If HTTP version is >= 1.1 and connection is persistent server supports pipelining. */ DEBUGF(infof(data, "HTTP 1.1 or later with persistent connection, " "pipelining supported\n")); /* Activate pipelining if needed */ - if(conn->bundle) { + cb_ptr = conn->bundle; + if(cb_ptr) { if(!Curl_pipeline_site_blacklisted(data, conn)) - conn->bundle->multiuse = BUNDLE_PIPELINING; + cb_ptr->server_supports_pipelining = TRUE; } } @@ -3461,17 +3479,14 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } else if(checkprefix("Server:", k->p)) { - if(conn->httpversion < 20) { - /* only do this for non-h2 servers */ - char *server_name = Curl_copy_header_value(k->p); - - /* Turn off pipelining if the server version is blacklisted */ - if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) { - if(Curl_pipeline_server_blacklisted(data, server_name)) - conn->bundle->multiuse = BUNDLE_NO_MULTIUSE; - } - free(server_name); + char *server_name = Curl_copy_header_value(k->p); + + /* Turn off pipelining if the server version is blacklisted */ + if(conn->bundle && conn->bundle->server_supports_pipelining) { + if(Curl_pipeline_server_blacklisted(data, server_name)) + conn->bundle->server_supports_pipelining = FALSE; } + Curl_safefree(server_name); } else if((conn->httpversion == 10) && conn->bits.httpproxy && @@ -3568,6 +3583,14 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, k->auto_decoding = GZIP; start += 6; } + else if(checkprefix("compress", start)) { + k->auto_decoding = COMPRESS; + start += 8; + } + else if(checkprefix("x-compress", start)) { + k->auto_decoding = COMPRESS; + start += 10; + } else /* unknown! */ break; @@ -3600,6 +3623,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, else if(checkprefix("gzip", start) || checkprefix("x-gzip", start)) k->auto_decoding = GZIP; + else if(checkprefix("compress", start) + || checkprefix("x-compress", start)) + k->auto_decoding = COMPRESS; } else if(checkprefix("Content-Range:", k->p)) { /* Content-Range: bytes [num]- @@ -3665,7 +3691,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, result = Curl_http_input_auth(conn, proxy, auth); - free(auth); + Curl_safefree(auth); if(result) return result; diff --git a/lib/http.h b/lib/http.h index fe4f39bc6..907755a8a 100644 --- a/lib/http.h +++ b/lib/http.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -60,7 +60,6 @@ struct Curl_send_buffer { typedef struct Curl_send_buffer Curl_send_buffer; Curl_send_buffer *Curl_add_buffer_init(void); -void Curl_add_buffer_free(Curl_send_buffer *buff); CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...); CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size); CURLcode Curl_add_buffer_send(Curl_send_buffer *in, @@ -153,69 +152,42 @@ struct HTTP { void *send_buffer; /* used if the request couldn't be sent in one chunk, points to an allocated send_buffer struct */ - -#ifdef USE_NGHTTP2 - /*********** for HTTP/2 we store stream-local data here *************/ - int32_t stream_id; /* stream we are interested in */ - - bool bodystarted; - /* We store non-final and final response headers here, per-stream */ - Curl_send_buffer *header_recvbuf; - size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into - upper layer */ - int status_code; /* HTTP status code */ - const uint8_t *pausedata; /* pointer to data received in on_data_chunk */ - size_t pauselen; /* the number of bytes left in data */ - bool closed; /* TRUE on HTTP2 stream close */ - uint32_t error_code; /* HTTP/2 error code */ - - char *mem; /* points to a buffer in memory to store received data */ - size_t len; /* size of the buffer 'mem' points to */ - size_t memlen; /* size of data copied to mem */ - - const uint8_t *upload_mem; /* points to a buffer to read from */ - size_t upload_len; /* size of the buffer 'upload_mem' points to */ - curl_off_t upload_left; /* number of bytes left to upload */ - - char **push_headers; /* allocated array */ - size_t push_headers_used; /* number of entries filled in */ - size_t push_headers_alloc; /* number of entries allocated */ -#endif }; typedef int (*sending)(void); /* Curl_send */ typedef int (*recving)(void); /* Curl_recv */ -#ifdef USE_NGHTTP2 -/* h2 settings for this connection */ -struct h2settings { - uint32_t max_concurrent_streams; - bool enable_push; -}; -#endif - - struct http_conn { #ifdef USE_NGHTTP2 #define H2_BINSETTINGS_LEN 80 nghttp2_session *h2; uint8_t binsettings[H2_BINSETTINGS_LEN]; size_t binlen; /* length of the binsettings data */ + char *mem; /* points to a buffer in memory to store */ + size_t len; /* size of the buffer 'mem' points to */ + bool bodystarted; sending send_underlying; /* underlying send Curl_send callback */ recving recv_underlying; /* underlying recv Curl_recv callback */ + bool closed; /* TRUE on HTTP2 stream close */ + Curl_send_buffer *header_recvbuf; /* store response headers. We + store non-final and final + response headers into it. */ + size_t nread_header_recvbuf; /* number of bytes in header_recvbuf + fed into upper layer */ + int32_t stream_id; /* stream we are interested in */ + const uint8_t *data; /* pointer to data chunk, received in + on_data_chunk */ + size_t datalen; /* the number of bytes left in data */ char *inbuf; /* buffer to receive data from underlying socket */ - size_t inbuflen; /* number of bytes filled in inbuf */ - size_t nread_inbuf; /* number of bytes read from in inbuf */ /* We need separate buffer for transmission and reception because we may call nghttp2_session_send() after the nghttp2_session_mem_recv() but mem buffer is still not full. In this case, we wrongly sends the content of mem buffer if we share them for both cases. */ - int32_t pause_stream_id; /* stream ID which paused - nghttp2_session_mem_recv */ - - /* this is a hash of all individual streams (SessionHandle structs) */ - struct h2settings settings; + const uint8_t *upload_mem; /* points to a buffer to read from */ + size_t upload_len; /* size of the buffer 'upload_mem' points to */ + size_t upload_left; /* number of bytes left to upload */ + int status_code; /* HTTP status code */ #else int unused; /* prevent a compiler warning */ #endif diff --git a/lib/http2.c b/lib/http2.c index 0024add8a..dac9ab4a1 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,24 +23,22 @@ #include "curl_setup.h" #ifdef USE_NGHTTP2 -#include "curl_printf.h" +#define _MPRINTF_REPLACE +#include <curl/mprintf.h> + #include <nghttp2/nghttp2.h> #include "urldata.h" #include "http2.h" #include "http.h" #include "sendf.h" #include "curl_base64.h" +#include "curl_memory.h" #include "rawstr.h" #include "multiif.h" -#include "conncache.h" -#include "url.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* include memdebug.h last */ #include "memdebug.h" -#define MIN(x,y) ((x)<(y)?(x):(y)) - #if (NGHTTP2_VERSION_NUM < 0x000600) #error too old nghttp2 version, upgrade! #endif @@ -52,7 +50,7 @@ static int http2_perform_getsock(const struct connectdata *conn, sockets */ int numsocks) { - const struct http_conn *c = &conn->proto.httpc; + const struct http_conn *httpc = &conn->proto.httpc; int bitmap = GETSOCK_BLANK; (void)numsocks; @@ -60,10 +58,10 @@ static int http2_perform_getsock(const struct connectdata *conn, because of renegotiation. */ sock[0] = conn->sock[FIRSTSOCKET]; - if(nghttp2_session_want_read(c->h2)) + if(nghttp2_session_want_read(httpc->h2)) bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); - if(nghttp2_session_want_write(c->h2)) + if(nghttp2_session_want_write(httpc->h2)) bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); return bitmap; @@ -80,52 +78,21 @@ static int http2_getsock(struct connectdata *conn, static CURLcode http2_disconnect(struct connectdata *conn, bool dead_connection) { - struct HTTP *http = conn->data->req.protop; - struct http_conn *c = &conn->proto.httpc; + struct http_conn *httpc = &conn->proto.httpc; (void)dead_connection; - DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + infof(conn->data, "HTTP/2 DISCONNECT starts now\n"); - nghttp2_session_del(c->h2); - Curl_safefree(c->inbuf); + nghttp2_session_del(httpc->h2); - if(http) { - Curl_add_buffer_free(http->header_recvbuf); - http->header_recvbuf = NULL; /* clear the pointer */ - for(; http->push_headers_used > 0; --http->push_headers_used) { - free(http->push_headers[http->push_headers_used - 1]); - } - free(http->push_headers); - http->push_headers = NULL; - } + Curl_safefree(httpc->header_recvbuf->buffer); + Curl_safefree(httpc->header_recvbuf); - DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); + Curl_safefree(httpc->inbuf); - return CURLE_OK; -} + infof(conn->data, "HTTP/2 DISCONNECT done\n"); -/* called from Curl_http_setup_conn */ -void Curl_http2_setup_req(struct SessionHandle *data) -{ - struct HTTP *http = data->req.protop; - - http->nread_header_recvbuf = 0; - http->bodystarted = FALSE; - http->status_code = -1; - http->pausedata = NULL; - http->pauselen = 0; - http->error_code = NGHTTP2_NO_ERROR; - http->closed = FALSE; - http->mem = data->state.buffer; - http->len = BUFSIZE; - http->memlen = 0; -} - -/* called from Curl_http_setup_conn */ -void Curl_http2_setup_conn(struct connectdata *conn) -{ - conn->proto.httpc.settings.max_concurrent_streams = - DEFAULT_MAX_CONCURRENT_STREAMS; + return CURLE_OK; } /* @@ -137,7 +104,7 @@ const struct Curl_handler Curl_handler_http2 = { "HTTP2", /* scheme */ ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ - Curl_http_done, /* done */ + ZERO_NULL, /* done */ ZERO_NULL, /* do_more */ ZERO_NULL, /* connect_it */ ZERO_NULL, /* connecting */ @@ -157,7 +124,7 @@ const struct Curl_handler Curl_handler_http2_ssl = { "HTTP2", /* scheme */ ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ - Curl_http_done, /* done */ + ZERO_NULL, /* done */ ZERO_NULL, /* do_more */ ZERO_NULL, /* connect_it */ ZERO_NULL, /* connecting */ @@ -193,15 +160,15 @@ static ssize_t send_callback(nghttp2_session *h2, void *userp) { struct connectdata *conn = (struct connectdata *)userp; - struct http_conn *c = &conn->proto.httpc; + struct http_conn *httpc = &conn->proto.httpc; ssize_t written; CURLcode result = CURLE_OK; (void)h2; (void)flags; - written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET, - data, length, &result); + written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET, + data, length, &result); if(result == CURLE_AGAIN) { return NGHTTP2_ERR_WOULDBLOCK; @@ -218,205 +185,25 @@ static ssize_t send_callback(nghttp2_session *h2, return written; } - -/* We pass a pointer to this struct in the push callback, but the contents of - the struct are hidden from the user. */ -struct curl_pushheaders { - struct SessionHandle *data; - const nghttp2_push_promise *frame; -}; - -/* - * push header access function. Only to be used from within the push callback - */ -char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) -{ - /* Verify that we got a good easy handle in the push header struct, mostly to - detect rubbish input fast(er). */ - if(!h || !GOOD_EASY_HANDLE(h->data)) - return NULL; - else { - struct HTTP *stream = h->data->req.protop; - if(num < stream->push_headers_used) - return stream->push_headers[num]; - } - return NULL; -} - -/* - * push header access function. Only to be used from within the push callback - */ -char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) -{ - /* Verify that we got a good easy handle in the push header struct, - mostly to detect rubbish input fast(er). Also empty header name - is just a rubbish too. We have to allow ":" at the beginning of - the header, but header == ":" must be rejected. If we have ':' in - the middle of header, it could be matched in middle of the value, - this is because we do prefix match.*/ - if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] || - Curl_raw_equal(header, ":") || strchr(header + 1, ':')) - return NULL; - else { - struct HTTP *stream = h->data->req.protop; - size_t len = strlen(header); - size_t i; - for(i=0; i<stream->push_headers_used; i++) { - if(!strncmp(header, stream->push_headers[i], len)) { - /* sub-match, make sure that it us followed by a colon */ - if(stream->push_headers[i][len] != ':') - continue; - return &stream->push_headers[i][len+1]; - } - } - } - return NULL; -} - -static CURL *duphandle(struct SessionHandle *data) -{ - struct SessionHandle *second = curl_easy_duphandle(data); - if(second) { - /* setup the request struct */ - struct HTTP *http = calloc(1, sizeof(struct HTTP)); - if(!http) { - (void)Curl_close(second); - second = NULL; - } - else { - second->req.protop = http; - http->header_recvbuf = Curl_add_buffer_init(); - if(!http->header_recvbuf) { - free(http); - (void)Curl_close(second); - second = NULL; - } - else - Curl_http2_setup_req(second); - } - } - return second; -} - - -static int push_promise(struct SessionHandle *data, - struct connectdata *conn, - const nghttp2_push_promise *frame) -{ - int rv; - DEBUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", - frame->promised_stream_id)); - if(data->multi->push_cb) { - struct HTTP *stream; - struct curl_pushheaders heads; - CURLMcode rc; - struct http_conn *httpc; - size_t i; - /* clone the parent */ - CURL *newhandle = duphandle(data); - if(!newhandle) { - infof(data, "failed to duplicate handle\n"); - rv = 1; /* FAIL HARD */ - goto fail; - } - - heads.data = data; - heads.frame = frame; - /* ask the application */ - DEBUGF(infof(data, "Got PUSH_PROMISE, ask application!\n")); - - stream = data->req.protop; - if(!stream) { - failf(data, "Internal NULL stream!\n"); - rv = 1; - goto fail; - } - - rv = data->multi->push_cb(data, newhandle, - stream->push_headers_used, &heads, - data->multi->push_userp); - - /* free the headers again */ - for(i=0; i<stream->push_headers_used; i++) - free(stream->push_headers[i]); - free(stream->push_headers); - stream->push_headers = NULL; - - if(rv) { - /* denied, kill off the new handle again */ - (void)Curl_close(newhandle); - goto fail; - } - - /* approved, add to the multi handle and immediately switch to PERFORM - state with the given connection !*/ - rc = Curl_multi_add_perform(data->multi, newhandle, conn); - if(rc) { - infof(data, "failed to add handle to multi\n"); - Curl_close(newhandle); - rv = 1; - goto fail; - } - - httpc = &conn->proto.httpc; - nghttp2_session_set_stream_user_data(httpc->h2, - frame->promised_stream_id, newhandle); - } - else { - DEBUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); - rv = 1; - } - fail: - return rv; -} - static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { - struct connectdata *conn = NULL; - struct http_conn *httpc = NULL; - struct SessionHandle *data_s = NULL; - struct HTTP *stream = NULL; - static int lastStream = -1; + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; int rv; size_t left, ncopy; - int32_t stream_id = frame->hd.stream_id; - - (void)userp; - - if(!stream_id) { - /* stream ID zero is for connection-oriented stuff */ - return 0; - } - data_s = nghttp2_session_get_stream_user_data(session, - frame->hd.stream_id); - if(lastStream != frame->hd.stream_id) { - lastStream = frame->hd.stream_id; - } - if(!data_s) { - DEBUGF(infof(conn->data, - "No SessionHandle associated with stream: %x\n", - stream_id)); - return 0; - } - - stream = data_s->req.protop; - if(!stream) - return NGHTTP2_ERR_CALLBACK_FAILURE; - DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n", - frame->hd.type, stream_id)); - - conn = data_s->easy_conn; - assert(conn); - assert(conn->data == data_s); - httpc = &conn->proto.httpc; + (void)session; + (void)frame; + infof(conn->data, "on_frame_recv() was called with header %x\n", + frame->hd.type); switch(frame->hd.type) { case NGHTTP2_DATA: - /* If body started on this stream, then receiving DATA is illegal. */ - if(!stream->bodystarted) { + /* If body started, then receiving DATA is illegal. */ + if(!c->bodystarted) { rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - stream_id, NGHTTP2_PROTOCOL_ERROR); + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); if(nghttp2_is_fatal(rv)) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -427,96 +214,74 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(frame->headers.cat == NGHTTP2_HCAT_REQUEST) break; - if(stream->bodystarted) { - /* Only valid HEADERS after body started is trailer HEADERS. We - ignores trailer HEADERS for now. nghttp2 guarantees that it - has END_STREAM flag set. */ + if(c->bodystarted) { + /* Only valid HEADERS after body started is trailer header, + which is not fully supported in this code. If HEADERS is not + trailer, then it is a PROTOCOL_ERROR. */ + if((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } break; } - /* nghttp2 guarantees that :status is received, and we store it to - stream->status_code */ - DEBUGASSERT(stream->status_code != -1); + if(c->status_code == -1) { + /* No :status header field means PROTOCOL_ERROR. */ + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); - /* Only final status code signals the end of header */ - if(stream->status_code / 100 != 1) { - stream->bodystarted = TRUE; - stream->status_code = -1; + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + break; } - Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); + /* Only final status code signals the end of header */ + if(c->status_code / 100 != 1) { + c->bodystarted = TRUE; + } - left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf; - ncopy = MIN(stream->len, left); + c->status_code = -1; - memcpy(&stream->mem[stream->memlen], - stream->header_recvbuf->buffer + stream->nread_header_recvbuf, - ncopy); - stream->nread_header_recvbuf += ncopy; + Curl_add_buffer(c->header_recvbuf, "\r\n", 2); - DEBUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n", - ncopy, stream_id, stream->mem)); + left = c->header_recvbuf->size_used - c->nread_header_recvbuf; + ncopy = c->len < left ? c->len : left; - stream->len -= ncopy; - stream->memlen += ncopy; + memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy); + c->nread_header_recvbuf += ncopy; - data_s->state.drain++; - Curl_expire(data_s, 1); + c->mem += ncopy; + c->len -= ncopy; break; case NGHTTP2_PUSH_PROMISE: - rv = push_promise(data_s, conn, &frame->push_promise); - if(rv) { /* deny! */ - rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - frame->push_promise.promised_stream_id, - NGHTTP2_CANCEL); - if(nghttp2_is_fatal(rv)) { - return rv; - } + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_CANCEL); + if(nghttp2_is_fatal(rv)) { + return rv; } break; - case NGHTTP2_SETTINGS: - { - uint32_t max_conn = httpc->settings.max_concurrent_streams; - DEBUGF(infof(conn->data, "Got SETTINGS for stream %u!\n", stream_id)); - httpc->settings.max_concurrent_streams = - nghttp2_session_get_remote_settings( - session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); - httpc->settings.enable_push = - nghttp2_session_get_remote_settings( - session, NGHTTP2_SETTINGS_ENABLE_PUSH); - DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n", - httpc->settings.max_concurrent_streams)); - DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n", - httpc->settings.enable_push?"TRUE":"false")); - if(max_conn != httpc->settings.max_concurrent_streams) { - /* only signal change if the value actually changed */ - infof(conn->data, - "Connection state changed (MAX_CONCURRENT_STREAMS updated)!\n"); - Curl_multi_connchanged(conn->data->multi); - } - } - break; - default: - DEBUGF(infof(conn->data, "Got frame type %x for stream %u!\n", - frame->hd.type, stream_id)); - break; } return 0; } static int on_invalid_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, - int lib_error_code, void *userp) + uint32_t error_code, void *userp) { - struct SessionHandle *data_s = NULL; - (void)userp; - - data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); - if(data_s) { - DEBUGF(infof(data_s, - "on_invalid_frame_recv() was called, error=%d:%s\n", - lib_error_code, nghttp2_strerror(lib_error_code))); - } + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + infof(conn->data, "on_invalid_frame_recv() was called, error_code = %d\n", + error_code); return 0; } @@ -524,50 +289,30 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *userp) { - struct HTTP *stream; - struct SessionHandle *data_s; + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; size_t nread; (void)session; (void)flags; (void)data; - (void)userp; - - DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ - - /* get the stream from the hash based on Stream ID */ - data_s = nghttp2_session_get_stream_user_data(session, stream_id); - if(!data_s) - /* Receiving a Stream ID not in the hash should not happen, this is an - internal error more than anything else! */ - return NGHTTP2_ERR_CALLBACK_FAILURE; - - stream = data_s->req.protop; - if(!stream) - return NGHTTP2_ERR_CALLBACK_FAILURE; + infof(conn->data, "on_data_chunk_recv() " + "len = %u, stream = %x\n", len, stream_id); - nread = MIN(stream->len, len); - memcpy(&stream->mem[stream->memlen], data, nread); + if(stream_id != c->stream_id) { + return 0; + } - stream->len -= nread; - stream->memlen += nread; + nread = c->len < len ? c->len : len; + memcpy(c->mem, data, nread); - data_s->state.drain++; - Curl_expire(data_s, 1); /* TODO: fix so that this can be set to 0 for - immediately? */ + c->mem += nread; + c->len -= nread; - DEBUGF(infof(data_s, "%zu data received for stream %u " - "(%zu left in buffer %p, total %zu)\n", - nread, stream_id, - stream->len, stream->mem, - stream->memlen)); + infof(conn->data, "%zu data written\n", nread); if(nread < len) { - stream->pausedata = data + nread; - stream->pauselen = len - nread; - DEBUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" - ", stream %u\n", - len - nread, stream_id)); - data_s->easy_conn->proto.httpc.pause_stream_id = stream_id; + c->data = data + nread; + c->datalen = len - nread; return NGHTTP2_ERR_PAUSE; } return 0; @@ -577,89 +322,59 @@ static int before_frame_send(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { - struct SessionHandle *data_s; - (void)userp; - - data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); - if(data_s) { - DEBUGF(infof(data_s, "before_frame_send() was called\n")); - } - + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + infof(conn->data, "before_frame_send() was called\n"); return 0; } static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { - struct SessionHandle *data_s; - (void)userp; - - data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); - if(data_s) { - DEBUGF(infof(data_s, "on_frame_send() was called, length = %zd\n", - frame->hd.length)); - } + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + infof(conn->data, "on_frame_send() was called\n"); return 0; } static int on_frame_not_send(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, void *userp) { - struct SessionHandle *data_s; - (void)userp; - - data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); - if(data_s) { - DEBUGF(infof(data_s, - "on_frame_not_send() was called, lib_error_code = %d\n", - lib_error_code)); - } + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + infof(conn->data, "on_frame_not_send() was called, lib_error_code = %d\n", + lib_error_code); return 0; } static int on_stream_close(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *userp) { - struct SessionHandle *data_s; - struct HTTP *stream; + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; (void)session; (void)stream_id; - (void)userp; - - if(stream_id) { - /* get the stream from the hash based on Stream ID, stream ID zero is for - connection-oriented stuff */ - data_s = nghttp2_session_get_stream_user_data(session, stream_id); - if(!data_s) { - /* We could get stream ID not in the hash. For example, if we - decided to reject stream (e.g., PUSH_PROMISE). */ - return 0; - } - DEBUGF(infof(data_s, "on_stream_close(), error_code = %d, stream %u\n", - error_code, stream_id)); - stream = data_s->req.protop; - if(!stream) - return NGHTTP2_ERR_CALLBACK_FAILURE; - - stream->error_code = error_code; - stream->closed = TRUE; + infof(conn->data, "on_stream_close() was called, error_code = %d\n", + error_code); - /* remove the entry from the hash as the stream is now gone */ - nghttp2_session_set_stream_user_data(session, stream_id, 0); - DEBUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); + if(stream_id != c->stream_id) { + return 0; } + + c->closed = TRUE; + return 0; } static int on_begin_headers(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { - struct SessionHandle *data_s = NULL; - (void)userp; - - data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); - if(data_s) { - DEBUGF(infof(data_s, "on_begin_headers() was called\n")); - } + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + infof(conn->data, "on_begin_headers() was called\n"); return 0; } @@ -690,6 +405,8 @@ static int decode_status_code(const uint8_t *value, size_t len) return res; } +static const char STATUS[] = ":status"; + /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, @@ -697,94 +414,93 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, uint8_t flags, void *userp) { - struct HTTP *stream; - struct SessionHandle *data_s; - int32_t stream_id = frame->hd.stream_id; + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + int rv; + int goodname; + int goodheader; + (void)session; + (void)frame; (void)flags; - (void)userp; - - DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ - - /* get the stream from the hash based on Stream ID */ - data_s = nghttp2_session_get_stream_user_data(session, stream_id); - if(!data_s) - /* Receiving a Stream ID not in the hash should not happen, this is an - internal error more than anything else! */ - return NGHTTP2_ERR_CALLBACK_FAILURE; - stream = data_s->req.protop; - if(!stream) { - failf(data_s, "Internal NULL stream! 5\n"); - return NGHTTP2_ERR_CALLBACK_FAILURE; + if(frame->hd.stream_id != c->stream_id) { + return 0; } - if(stream->bodystarted) + if(c->bodystarted) { /* Ignore trailer or HEADERS not mapped to HTTP semantics. The consequence is handled in on_frame_recv(). */ return 0; + } - /* Store received PUSH_PROMISE headers to be used when the subsequent - PUSH_PROMISE callback comes */ - if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { - char *h; + goodname = nghttp2_check_header_name(name, namelen); + goodheader = nghttp2_check_header_value(value, valuelen); - if(!stream->push_headers) { - stream->push_headers_alloc = 10; - stream->push_headers = malloc(stream->push_headers_alloc * - sizeof(char *)); - stream->push_headers_used = 0; - } - else if(stream->push_headers_used == - stream->push_headers_alloc) { - char **headp; - stream->push_headers_alloc *= 2; - headp = realloc(stream->push_headers, - stream->push_headers_alloc * sizeof(char *)); - if(!headp) { - free(stream->push_headers); - stream->push_headers = NULL; - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - stream->push_headers = headp; + if(!goodname || !goodheader) { + + infof(conn->data, "Detected bad incoming header %s%s, reset stream!\n", + goodname?"":"name", + goodheader?"":"value"); + + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; } - h = aprintf("%s:%s", name, value); - if(h) - stream->push_headers[stream->push_headers_used++] = h; - return 0; + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } if(namelen == sizeof(":status") - 1 && - memcmp(":status", name, namelen) == 0) { - /* nghttp2 guarantees :status is received first and only once, and - value is 3 digits status code, and decode_status_code always - succeeds. */ - stream->status_code = decode_status_code(value, valuelen); - DEBUGASSERT(stream->status_code != -1); - - Curl_add_buffer(stream->header_recvbuf, "HTTP/2.0 ", 9); - Curl_add_buffer(stream->header_recvbuf, value, valuelen); - Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); - data_s->state.drain++; - Curl_expire(data_s, 1); - - DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d\n", - stream->status_code)); + memcmp(STATUS, name, namelen) == 0) { + + /* :status must appear exactly once. */ + if(c->status_code != -1 || + (c->status_code = decode_status_code(value, valuelen)) == -1) { + + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + Curl_add_buffer(c->header_recvbuf, "HTTP/2.0 ", 9); + Curl_add_buffer(c->header_recvbuf, value, valuelen); + Curl_add_buffer(c->header_recvbuf, "\r\n", 2); + return 0; } + else { + /* Here we are sure that namelen > 0 because of + nghttp2_check_header_name(). Pseudo header other than :status + is illegal. */ + if(c->status_code == -1 || name[0] == ':') { + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } - /* nghttp2 guarantees that namelen > 0, and :status was already - received, and this is not pseudo-header field . */ - /* convert to a HTTP1-style header */ - Curl_add_buffer(stream->header_recvbuf, name, namelen); - Curl_add_buffer(stream->header_recvbuf, ":", 1); - Curl_add_buffer(stream->header_recvbuf, value, valuelen); - Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); - data_s->state.drain++; - Curl_expire(data_s, 1); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } - DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, - value)); + /* convert to a HTTP1-style header */ + Curl_add_buffer(c->header_recvbuf, name, namelen); + Curl_add_buffer(c->header_recvbuf, ":", 1); + Curl_add_buffer(c->header_recvbuf, value, valuelen); + Curl_add_buffer(c->header_recvbuf, "\r\n", 2); + + infof(conn->data, "got http2 header: %.*s: %.*s\n", + namelen, name, valuelen, value); + } return 0; /* 0 is successful */ } @@ -796,45 +512,26 @@ static ssize_t data_source_read_callback(nghttp2_session *session, nghttp2_data_source *source, void *userp) { - struct SessionHandle *data_s; - struct HTTP *stream = NULL; + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; size_t nread; + (void)session; + (void)stream_id; (void)source; - (void)userp; - - if(stream_id) { - /* get the stream from the hash based on Stream ID, stream ID zero is for - connection-oriented stuff */ - data_s = nghttp2_session_get_stream_user_data(session, stream_id); - if(!data_s) - /* Receiving a Stream ID not in the hash should not happen, this is an - internal error more than anything else! */ - return NGHTTP2_ERR_CALLBACK_FAILURE; - - stream = data_s->req.protop; - if(!stream) - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - else - return NGHTTP2_ERR_INVALID_ARGUMENT; - nread = MIN(stream->upload_len, length); + nread = c->upload_len < length ? c->upload_len : length; if(nread > 0) { - memcpy(buf, stream->upload_mem, nread); - stream->upload_mem += nread; - stream->upload_len -= nread; - stream->upload_left -= nread; + memcpy(buf, c->upload_mem, nread); + c->upload_mem += nread; + c->upload_len -= nread; + c->upload_left -= nread; } - if(stream->upload_left == 0) + if(c->upload_left == 0) *data_flags = 1; else if(nread == 0) return NGHTTP2_ERR_DEFERRED; - DEBUGF(infof(data_s, "data_source_read_callback: " - "returns %zu bytes stream %u\n", - nread, stream_id)); - return nread; } @@ -846,7 +543,7 @@ static nghttp2_settings_entry settings[] = { { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE }, }; -#define H2_BUFSIZE 32768 +#define H2_BUFSIZE 4096 /* * Initialize nghttp2 for a Curl connection @@ -898,7 +595,8 @@ CURLcode Curl_http2_init(struct connectdata *conn) nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header); /* The nghttp2 session is not yet setup, do it */ - rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); + rc = nghttp2_session_client_new(&conn->proto.httpc.h2, + callbacks, conn); nghttp2_session_callbacks_del(callbacks); @@ -906,11 +604,6 @@ CURLcode Curl_http2_init(struct connectdata *conn) failf(conn->data, "Couldn't initialize nghttp2!"); return CURLE_OUT_OF_MEMORY; /* most likely at least */ } - - if(rc) { - failf(conn->data, "Couldn't init stream hash!"); - return CURLE_OUT_OF_MEMORY; /* most likely at least */ - } } return CURLE_OK; } @@ -937,6 +630,14 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, struct SingleRequest *k = &conn->data->req; uint8_t *binsettings = conn->proto.httpc.binsettings; + result = Curl_http2_init(conn); + if(result) + return result; + + result = Curl_http2_setup(conn); + if(result) + return result; + /* As long as we have a fixed set of settings, we don't have to dynamically * figure out the base64 strings since it'll always be the same. However, * the settings will likely not be fixed every time in the future. @@ -962,32 +663,13 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, "Upgrade: %s\r\n" "HTTP2-Settings: %s\r\n", NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); - free(base64); + Curl_safefree(base64); k->upgr101 = UPGR101_REQUESTED; return result; } -static ssize_t http2_handle_stream_close(struct http_conn *httpc, - struct SessionHandle *data, - struct HTTP *stream, CURLcode *err) { - if(httpc->pause_stream_id == stream->stream_id) { - httpc->pause_stream_id = 0; - } - /* Reset to FALSE to prevent infinite loop in readwrite_data - function. */ - stream->closed = FALSE; - if(stream->error_code != NGHTTP2_NO_ERROR) { - failf(data, "HTTP/2 stream %u was not closed cleanly: error_code = %d", - stream->stream_id, stream->error_code); - *err = CURLE_HTTP2; - return -1; - } - DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); - return 0; -} - /* * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return * a regular CURLcode value. @@ -999,184 +681,103 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, ssize_t rv; ssize_t nread; struct http_conn *httpc = &conn->proto.httpc; - struct SessionHandle *data = conn->data; - struct HTTP *stream = data->req.protop; (void)sockindex; /* we always do HTTP2 on sockindex 0 */ - /* If stream is closed, return 0 to signal the http routine to close - the connection. We need to handle stream closure here, - otherwise, we may be going to read from underlying connection, - and gets EAGAIN, and we will get stuck there. */ - if(stream->memlen == 0 && stream->closed) { - return http2_handle_stream_close(httpc, data, stream, err); + if(httpc->closed) { + /* Reset to FALSE to prevent infinite loop in readwrite_data + function. */ + httpc->closed = FALSE; + return 0; } /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ - stream->upload_mem = NULL; - stream->upload_len = 0; + httpc->upload_mem = NULL; + httpc->upload_len = 0; - /* - * At this point 'stream' is just in the SessionHandle the connection - * identifies as its owner at this time. - */ - - if(stream->bodystarted && - stream->nread_header_recvbuf < stream->header_recvbuf->size_used) { - /* If there is body data pending for this stream to return, do that */ + if(httpc->bodystarted && + httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) { size_t left = - stream->header_recvbuf->size_used - stream->nread_header_recvbuf; - size_t ncopy = MIN(len, left); - memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf, + httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf; + size_t ncopy = len < left ? len : left; + memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf, ncopy); - stream->nread_header_recvbuf += ncopy; - - infof(data, "http2_recv: Got %d bytes from header_recvbuf\n", - (int)ncopy); + httpc->nread_header_recvbuf += ncopy; return ncopy; } - infof(data, "http2_recv: %d bytes buffer at %p (stream %u)\n", - len, mem, stream->stream_id); - - if((data->state.drain) && stream->memlen) { - DEBUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", - stream->memlen, stream->stream_id, - stream->mem, mem)); - if(mem != stream->mem) { - /* if we didn't get the same buffer this time, we must move the data to - the beginning */ - memmove(mem, stream->mem, stream->memlen); - stream->len = len - stream->memlen; - stream->mem = mem; - } - } - else if(stream->pausedata) { - nread = MIN(len, stream->pauselen); - memcpy(mem, stream->pausedata, nread); - - stream->pausedata += nread; - stream->pauselen -= nread; + if(httpc->data) { + nread = len < httpc->datalen ? len : httpc->datalen; + memcpy(mem, httpc->data, nread); - infof(data, "%zu data bytes written\n", nread); - if(stream->pauselen == 0) { - DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); - assert(httpc->pause_stream_id == stream->stream_id); - httpc->pause_stream_id = 0; + httpc->data += nread; + httpc->datalen -= nread; - stream->pausedata = NULL; - stream->pauselen = 0; + infof(conn->data, "%zu data written\n", nread); + if(httpc->datalen == 0) { + httpc->data = NULL; + httpc->datalen = 0; } - infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n", - nread, stream->stream_id); return nread; } - else if(httpc->pause_stream_id) { - /* If a stream paused nghttp2_session_mem_recv previously, and has - not processed all data, it still refers to the buffer in - nghttp2_session. If we call nghttp2_session_mem_recv(), we may - overwrite that buffer. To avoid that situation, just return - here with CURLE_AGAIN. This could be busy loop since data in - socket is not read. But it seems that usually streams are - notified with its drain property, and socket is read again - quickly. */ - *err = CURLE_AGAIN; - return -1; - } - else { - char *inbuf; - /* remember where to store incoming data for this stream and how big the - buffer is */ - stream->mem = mem; - stream->len = len; - stream->memlen = 0; - - if(httpc->inbuflen == 0) { - nread = ((Curl_recv *)httpc->recv_underlying)( - conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); - - if(result == CURLE_AGAIN) { - *err = result; - return -1; - } - if(nread == -1) { - failf(data, "Failed receiving HTTP2 data"); - *err = result; - return 0; - } + conn->proto.httpc.mem = mem; + conn->proto.httpc.len = len; - if(nread == 0) { - failf(data, "Unexpected EOF"); - *err = CURLE_RECV_ERROR; - return -1; - } + infof(conn->data, "http2_recv: %d bytes buffer\n", + conn->proto.httpc.len); - DEBUGF(infof(data, "nread=%zd\n", nread)); + nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET, + httpc->inbuf, H2_BUFSIZE, + &result); + if(result == CURLE_AGAIN) { + *err = result; + return -1; + } - httpc->inbuflen = nread; - inbuf = httpc->inbuf; - } - else { - nread = httpc->inbuflen - httpc->nread_inbuf; - inbuf = httpc->inbuf + httpc->nread_inbuf; + if(nread == -1) { + failf(conn->data, "Failed receiving HTTP2 data"); + *err = result; + return 0; + } - DEBUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", - nread)); - } - rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); + infof(conn->data, "nread=%zd\n", nread); - if(nghttp2_is_fatal((int)rv)) { - failf(data, "nghttp2_session_mem_recv() returned %d:%s\n", - rv, nghttp2_strerror((int)rv)); - *err = CURLE_RECV_ERROR; - return 0; - } - DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv)); - if(nread == rv) { - DEBUGF(infof(data, "All data in connection buffer processed\n")); - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - } - else { - httpc->nread_inbuf += rv; - DEBUGF(infof(data, "%zu bytes left in connection buffer\n", - httpc->inbuflen - httpc->nread_inbuf)); - } - /* Always send pending frames in nghttp2 session, because - nghttp2_session_mem_recv() may queue new frame */ - rv = nghttp2_session_send(httpc->h2); - if(rv != 0) { - *err = CURLE_SEND_ERROR; - return 0; - } + if(nread == 0) { + failf(conn->data, "EOF"); + return 0; } - if(stream->memlen) { - ssize_t retlen = stream->memlen; - infof(data, "http2_recv: returns %zd for stream %u\n", - retlen, stream->stream_id); - stream->memlen = 0; - - if(httpc->pause_stream_id == stream->stream_id) { - /* data for this stream is returned now, but this stream caused a pause - already so we need it called again asap */ - DEBUGF(infof(data, "Data returned for PAUSED stream %u\n", - stream->stream_id)); - } - else - data->state.drain = 0; /* this stream is hereby drained */ - return retlen; + rv = nghttp2_session_mem_recv(httpc->h2, + (const uint8_t *)httpc->inbuf, nread); + + if(nghttp2_is_fatal((int)rv)) { + failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n", + rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return 0; + } + infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv); + /* Always send pending frames in nghttp2 session, because + nghttp2_session_mem_recv() may queue new frame */ + rv = nghttp2_session_send(httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return 0; + } + if(len != httpc->len) { + return len - conn->proto.httpc.len; } /* If stream is closed, return 0 to signal the http routine to close the connection */ - if(stream->closed) { - return http2_handle_stream_close(httpc, data, stream, err); + if(httpc->closed) { + /* Reset to FALSE to prevent infinite loop in readwrite_data + function. */ + httpc->closed = FALSE; + return 0; } *err = CURLE_AGAIN; - DEBUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", - stream->stream_id)); return -1; } @@ -1195,7 +796,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, */ int rv; struct http_conn *httpc = &conn->proto.httpc; - struct HTTP *stream = conn->data->req.protop; nghttp2_nv *nva; size_t nheader; size_t i; @@ -1204,41 +804,23 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, char *end; nghttp2_data_provider data_prd; int32_t stream_id; - nghttp2_session *h2 = httpc->h2; (void)sockindex; - DEBUGF(infof(conn->data, "http2_send len=%zu\n", len)); + infof(conn->data, "http2_send len=%zu\n", len); - if(stream->stream_id != -1) { + if(httpc->stream_id != -1) { /* If stream_id != -1, we have dispatched request HEADERS, and now are going to send or sending request body in DATA frame */ - stream->upload_mem = mem; - stream->upload_len = len; - nghttp2_session_resume_data(h2, stream->stream_id); - rv = nghttp2_session_send(h2); + httpc->upload_mem = mem; + httpc->upload_len = len; + nghttp2_session_resume_data(httpc->h2, httpc->stream_id); + rv = nghttp2_session_send(httpc->h2); if(nghttp2_is_fatal(rv)) { *err = CURLE_SEND_ERROR; return -1; } - len -= stream->upload_len; - - /* Nullify here because we call nghttp2_session_send() and they - might refer to the old buffer. */ - stream->upload_mem = NULL; - stream->upload_len = 0; - - if(stream->upload_left) { - /* we are sure that we have more data to send here. Calling the - following API will make nghttp2_session_want_write() return - nonzero if remote window allows it, which then libcurl checks - socket is writable or not. See http2_perform_getsock(). */ - nghttp2_session_resume_data(h2, stream->stream_id); - } - - DEBUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len, - stream->stream_id)); - return len; + return len - httpc->upload_len; } /* Calculate number of headers contained in [mem, mem + len) */ @@ -1261,8 +843,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, } /* Extract :method, :path from request line */ end = strchr(hdbuf, ' '); - if(!end) - goto fail; nva[0].name = (unsigned char *)":method"; nva[0].namelen = (uint16_t)strlen((char *)nva[0].name); nva[0].value = (unsigned char *)hdbuf; @@ -1272,8 +852,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, hdbuf = end + 1; end = strchr(hdbuf, ' '); - if(!end) - goto fail; nva[1].name = (unsigned char *)":path"; nva[1].namelen = (uint16_t)strlen((char *)nva[1].name); nva[1].value = (unsigned char *)hdbuf; @@ -1290,16 +868,13 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nva[2].flags = NGHTTP2_NV_FLAG_NONE; hdbuf = strchr(hdbuf, 0x0a); - if(!hdbuf) - goto fail; ++hdbuf; authority_idx = 0; for(i = 3; i < nheader; ++i) { end = strchr(hdbuf, ':'); - if(!end) - goto fail; + assert(end); if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) { authority_idx = i; nva[i].name = (unsigned char *)":authority"; @@ -1312,8 +887,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, hdbuf = end + 1; for(; *hdbuf == ' '; ++hdbuf); end = strchr(hdbuf, 0x0d); - if(!end) - goto fail; + assert(end); nva[i].value = (unsigned char *)hdbuf; nva[i].valuelen = (uint16_t)(end - hdbuf); nva[i].flags = NGHTTP2_NV_FLAG_NONE; @@ -1325,15 +899,11 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, if(nva[i].namelen == 14 && Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) { size_t j; - stream->upload_left = 0; for(j = 0; j < nva[i].valuelen; ++j) { - stream->upload_left *= 10; - stream->upload_left += nva[i].value[j] - '0'; + httpc->upload_left *= 10; + httpc->upload_left += nva[i].value[j] - '0'; } - DEBUGF(infof(conn->data, - "request content-length=%" - CURL_FORMAT_CURL_OFF_T - "\n", stream->upload_left)); + infof(conn->data, "request content-length=%zu\n", httpc->upload_left); } } @@ -1352,34 +922,31 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, case HTTPREQ_PUT: data_prd.read_callback = data_source_read_callback; data_prd.source.ptr = NULL; - stream_id = nghttp2_submit_request(h2, NULL, nva, nheader, - &data_prd, conn->data); + stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + &data_prd, NULL); break; default: - stream_id = nghttp2_submit_request(h2, NULL, nva, nheader, - NULL, conn->data); + stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + NULL, NULL); } Curl_safefree(nva); if(stream_id < 0) { - DEBUGF(infof(conn->data, "http2_send() send error\n")); *err = CURLE_SEND_ERROR; return -1; } - infof(conn->data, "Using Stream ID: %x (easy handle %p)\n", - stream_id, conn->data); - stream->stream_id = stream_id; + httpc->stream_id = stream_id; - rv = nghttp2_session_send(h2); + rv = nghttp2_session_send(httpc->h2); if(rv != 0) { *err = CURLE_SEND_ERROR; return -1; } - if(stream->stream_id != -1) { + if(httpc->stream_id != -1) { /* If whole HEADERS frame was sent off to the underlying socket, the nghttp2 library calls data_source_read_callback. But only it found that no data available, so it deferred the DATA @@ -1388,59 +955,36 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, writable socket check is performed. To workaround this, we issue nghttp2_session_resume_data() here to bring back DATA transmission from deferred state. */ - nghttp2_session_resume_data(h2, stream->stream_id); + nghttp2_session_resume_data(httpc->h2, httpc->stream_id); } return len; - - fail: - free(nva); - *err = CURLE_SEND_ERROR; - return -1; } CURLcode Curl_http2_setup(struct connectdata *conn) { - CURLcode result; struct http_conn *httpc = &conn->proto.httpc; - struct HTTP *stream = conn->data->req.protop; - - stream->stream_id = -1; - - if(!stream->header_recvbuf) - stream->header_recvbuf = Curl_add_buffer_init(); - - if((conn->handler == &Curl_handler_http2_ssl) || - (conn->handler == &Curl_handler_http2)) - return CURLE_OK; /* already done */ - if(conn->handler->flags & PROTOPT_SSL) conn->handler = &Curl_handler_http2_ssl; else conn->handler = &Curl_handler_http2; - result = Curl_http2_init(conn); - if(result) - return result; - - infof(conn->data, "Using HTTP2, server supports multi-use\n"); - stream->upload_left = 0; - stream->upload_mem = NULL; - stream->upload_len = 0; + infof(conn->data, "Using HTTP2\n"); + httpc->bodystarted = FALSE; + httpc->closed = FALSE; + httpc->header_recvbuf = Curl_add_buffer_init(); + httpc->nread_header_recvbuf = 0; + httpc->data = NULL; + httpc->datalen = 0; + httpc->upload_left = 0; + httpc->upload_mem = NULL; + httpc->upload_len = 0; + httpc->stream_id = -1; + httpc->status_code = -1; - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - - httpc->pause_stream_id = 0; - - conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ conn->httpversion = 20; - conn->bundle->multiuse = BUNDLE_MULTIPLEX; - infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); - Curl_multi_connchanged(conn->data->multi); - - return CURLE_OK; + return 0; } CURLcode Curl_http2_switched(struct connectdata *conn, @@ -1449,22 +993,30 @@ CURLcode Curl_http2_switched(struct connectdata *conn, CURLcode result; struct http_conn *httpc = &conn->proto.httpc; int rv; - ssize_t nproc; struct SessionHandle *data = conn->data; - struct HTTP *stream = conn->data->req.protop; - - result = Curl_http2_setup(conn); - if(result) - return result; httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET]; httpc->send_underlying = (sending)conn->send[FIRSTSOCKET]; conn->recv[FIRSTSOCKET] = http2_recv; conn->send[FIRSTSOCKET] = http2_send; + rv = (int) ((Curl_send*)httpc->send_underlying) + (conn, FIRSTSOCKET, + NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN, + &result); + if(result) + /* TODO: This may get CURLE_AGAIN */ + return result; + + if(rv != 24) { + failf(data, "Only sent partial HTTP2 packet"); + return CURLE_SEND_ERROR; + } + if(conn->data->req.upgr101 == UPGR101_RECEIVED) { /* stream 1 is opened implicitly on upgrade */ - stream->stream_id = 1; + httpc->stream_id = 1; /* queue SETTINGS frame (again) */ rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, httpc->binlen, NULL); @@ -1473,14 +1025,10 @@ CURLcode Curl_http2_switched(struct connectdata *conn, nghttp2_strerror(rv), rv); return CURLE_HTTP2; } - - nghttp2_session_set_stream_user_data(httpc->h2, - stream->stream_id, - conn->data); } else { /* stream ID is unknown at this point */ - stream->stream_id = -1; + httpc->stream_id = -1; rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); if(rv != 0) { failf(data, "nghttp2_submit_settings() failed: %s(%d)", @@ -1489,48 +1037,10 @@ CURLcode Curl_http2_switched(struct connectdata *conn, } } - /* we are going to copy mem to httpc->inbuf. This is required since - mem is part of buffer pointed by stream->mem, and callbacks - called by nghttp2_session_mem_recv() will write stream specific - data into stream->mem, overwriting data already there. */ - if(H2_BUFSIZE < nread) { - failf(data, "connection buffer size is too small to store data following " - "HTTP Upgrade response header: buflen=%zu, datalen=%zu", - H2_BUFSIZE, nread); - return CURLE_HTTP2; - } - - infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer" - " after upgrade: len=%zu\n", - nread); - - memcpy(httpc->inbuf, mem, nread); - httpc->inbuflen = nread; + rv = (int)nghttp2_session_mem_recv(httpc->h2, (const uint8_t*)mem, nread); - nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, - httpc->inbuflen); - - if(nghttp2_is_fatal((int)nproc)) { + if(rv != (int)nread) { failf(data, "nghttp2_session_mem_recv() failed: %s(%d)", - nghttp2_strerror((int)nproc), (int)nproc); - return CURLE_HTTP2; - } - - DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc)); - - if((ssize_t)nread == nproc) { - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - } - else { - httpc->nread_inbuf += nproc; - } - - /* Try to send some frames since we may read SETTINGS already. */ - rv = nghttp2_session_send(httpc->h2); - - if(rv != 0) { - failf(data, "nghttp2_session_send() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; } @@ -1538,25 +1048,4 @@ CURLcode Curl_http2_switched(struct connectdata *conn, return CURLE_OK; } -#else /* !USE_NGHTTP2 */ - -/* Satisfy external references even if http2 is not compiled in. */ - -#define CURL_DISABLE_TYPECHECK -#include <curl/curl.h> - -char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) -{ - (void) h; - (void) num; - return NULL; -} - -char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) -{ - (void) h; - (void) header; - return NULL; -} - -#endif /* USE_NGHTTP2 */ +#endif diff --git a/lib/http2.h b/lib/http2.h index bb7ad9c4c..a2e4eb7c2 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,11 +26,6 @@ #ifdef USE_NGHTTP2 #include "http.h" - -/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting - from the peer */ -#define DEFAULT_MAX_CONCURRENT_STREAMS 13 - /* * Store nghttp2 version info in this buffer, Prefix with a space. Return * total length written. @@ -44,17 +39,12 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, CURLcode Curl_http2_setup(struct connectdata *conn); CURLcode Curl_http2_switched(struct connectdata *conn, const char *data, size_t nread); -/* called from Curl_http_setup_conn */ -void Curl_http2_setup_conn(struct connectdata *conn); -void Curl_http2_setup_req(struct SessionHandle *data); #else /* USE_NGHTTP2 */ #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL -#define Curl_http2_setup_conn(x) -#define Curl_http2_setup_req(x) #endif #endif /* HEADER_CURL_HTTP2_H */ diff --git a/lib/http_chunks.c b/lib/http_chunks.c index 7e91b37dc..61a6098a7 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,12 +29,15 @@ #include "content_encoding.h" #include "http.h" +#include "curl_memory.h" #include "non-ascii.h" /* for Curl_convert_to_network prototype */ #include "strtoofft.h" #include "warnless.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -155,7 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, if(result) { /* Curl_convert_from_network calls failf if unsuccessful */ /* Treat it as a bad hex character */ - return CHUNKE_ILLEGAL_HEX; + return CHUNKE_ILLEGAL_HEX ; } ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16); @@ -218,6 +221,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, (ssize_t)piece); break; + case COMPRESS: default: failf (conn->data, "Unrecognized content encoding type. " diff --git a/lib/http_digest.c b/lib/http_digest.c index 929e2c60f..ba59e5d14 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,10 +28,12 @@ #include "rawstr.h" #include "curl_sasl.h" #include "http_digest.h" -#include "curl_printf.h" - -/* The last #include files should be: */ #include "curl_memory.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* Test example headers: diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index a1baf29c3..97d0cb762 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,7 +22,14 @@ #include "curl_setup.h" -#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) +#ifdef HAVE_GSSAPI + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif #include "urldata.h" #include "sendf.h" @@ -30,24 +37,52 @@ #include "rawstr.h" #include "curl_base64.h" #include "http_negotiate.h" -#include "curl_sasl.h" +#include "curl_memory.h" #include "url.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" -CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header) +static int +get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server) +{ + OM_uint32 major_status, minor_status; + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + char name[2048]; + const char* service = "HTTP"; + + token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : + conn->host.name) + 1; + if(token.length + 1 > sizeof(name)) + return EMSGSIZE; + + snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : + conn->host.name); + + token.value = (void *) name; + major_status = gss_import_name(&minor_status, + &token, + GSS_C_NT_HOSTBASED_SERVICE, + server); + + return GSS_ERROR(major_status) ? -1 : 0; +} + +/* returning zero (0) means success, everything else is treated as "failure" + with no care exactly what the failure was */ +int Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) { struct SessionHandle *data = conn->data; struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg: &data->state.negotiate; OM_uint32 major_status, minor_status, discard_st; - gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret; size_t len; size_t rawlen = 0; CURLcode result; @@ -57,36 +92,12 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, * rejected it (since we're again here). Exit with an error since we * can't invent anything better */ Curl_cleanup_negotiate(data); - return CURLE_LOGIN_DENIED; + return -1; } - if(!neg_ctx->server_name) { - /* Generate our SPN */ - char *spn = Curl_sasl_build_gssapi_spn( - proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] : - data->set.str[STRING_SERVICE_NAME], - proxy ? conn->proxy.name : conn->host.name); - if(!spn) - return CURLE_OUT_OF_MEMORY; - - /* Populate the SPN structure */ - spn_token.value = spn; - spn_token.length = strlen(spn); - - /* Import the SPN */ - major_status = gss_import_name(&minor_status, &spn_token, - GSS_C_NT_HOSTBASED_SERVICE, - &neg_ctx->server_name); - if(GSS_ERROR(major_status)) { - Curl_gss_log_error(data, minor_status, "gss_import_name() failed: "); - - free(spn); - - return CURLE_OUT_OF_MEMORY; - } - - free(spn); - } + if(neg_ctx->server_name == NULL && + (ret = get_gss_name(conn, proxy, &neg_ctx->server_name))) + return ret; header += strlen("Negotiate"); while(*header && ISSPACE(*header)) @@ -96,15 +107,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, if(len > 0) { result = Curl_base64_decode(header, (unsigned char **)&input_token.value, &rawlen); - if(result) - return result; - - if(!rawlen) { - infof(data, "Negotiate handshake failure (empty challenge message)\n"); - - return CURLE_BAD_CONTENT_ENCODING; - } - + if(result || rawlen == 0) + return -1; input_token.length = rawlen; DEBUGASSERT(input_token.value != NULL); @@ -128,20 +132,20 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, gss_release_buffer(&discard_st, &output_token); Curl_gss_log_error(conn->data, minor_status, "gss_init_sec_context() failed: "); - return CURLE_OUT_OF_MEMORY; + return -1; } if(!output_token.value || !output_token.length) { if(output_token.value) gss_release_buffer(&discard_st, &output_token); - return CURLE_OUT_OF_MEMORY; + return -1; } neg_ctx->output_token = output_token; - - return CURLE_OK; + return 0; } + CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) { struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: @@ -181,7 +185,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) conn->allocptr.userpwd = userp; } - free(encoded); + Curl_safefree(encoded); return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; } @@ -207,4 +211,6 @@ void Curl_cleanup_negotiate(struct SessionHandle *data) cleanup(&data->state.proxyneg); } -#endif /* HAVE_GSSAPI && !CURL_DISABLE_HTTP && USE_SPNEGO */ +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ + +#endif /* HAVE_GSSAPI */ diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h index a8eb98016..f7efe8cdd 100644 --- a/lib/http_negotiate.h +++ b/lib/http_negotiate.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2011, 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 @@ -25,8 +25,8 @@ #ifdef USE_SPNEGO /* this is for Negotiate header input */ -CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header); +int Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header); /* this is for creating Negotiate header output */ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c index a50ea96f1..d651ac9c8 100644 --- a/lib/http_negotiate_sspi.c +++ b/lib/http_negotiate_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -33,27 +33,30 @@ #include "curl_base64.h" #include "curl_sasl.h" #include "http_negotiate.h" +#include "curl_memory.h" #include "curl_multibyte.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" -CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header) +/* returning zero (0) means success, everything else is treated as "failure" + with no care exactly what the failure was */ +int Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) { - struct SessionHandle *data = conn->data; BYTE *input_token = NULL; SecBufferDesc out_buff_desc; SecBuffer out_sec_buff; SecBufferDesc in_buff_desc; SecBuffer in_sec_buff; - SECURITY_STATUS status; - unsigned long attrs; - TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + unsigned long context_attributes; + TimeStamp expiry; + int ret; size_t len = 0, input_token_len = 0; - CURLcode result; + CURLcode error; /* Point to the username and password */ const char *userp; @@ -65,12 +68,12 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, if(proxy) { userp = conn->proxyuser; passwdp = conn->proxypasswd; - neg_ctx = &data->state.proxyneg; + neg_ctx = &conn->data->state.proxyneg; } else { userp = conn->user; passwdp = conn->passwd; - neg_ctx = &data->state.negotiate; + neg_ctx = &conn->data->state.negotiate; } /* Not set means empty */ @@ -84,31 +87,29 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, /* We finished successfully our part of authentication, but server * rejected it (since we're again here). Exit with an error since we * can't invent anything better */ - Curl_cleanup_negotiate(data); - return CURLE_LOGIN_DENIED; + Curl_cleanup_negotiate(conn->data); + return -1; } if(!neg_ctx->server_name) { /* Check proxy auth requested but no given proxy name */ if(proxy && !conn->proxy.name) - return CURLE_BAD_FUNCTION_ARGUMENT; + return -1; /* Generate our SPN */ - neg_ctx->server_name = Curl_sasl_build_spn( - proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] : - data->set.str[STRING_SERVICE_NAME], - proxy ? conn->proxy.name : conn->host.name); + neg_ctx->server_name = Curl_sasl_build_spn("HTTP", + proxy ? conn->proxy.name : + conn->host.name); if(!neg_ctx->server_name) - return CURLE_OUT_OF_MEMORY; + return -1; } if(!neg_ctx->output_token) { PSecPkgInfo SecurityPackage; - status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) - TEXT(SP_NAME_NEGOTIATE), - &SecurityPackage); - if(status != SEC_E_OK) - return CURLE_NOT_BUILT_IN; + ret = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + if(ret != SEC_E_OK) + return -1; /* Allocate input and output buffers according to the max token size as indicated by the security package */ @@ -128,7 +129,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, if(neg_ctx->context) { /* The server rejected our authentication and hasn't suppled any more negotiation mechanisms */ - return CURLE_LOGIN_DENIED; + return -1; } /* We have to acquire credentials and allocate memory for the context */ @@ -136,13 +137,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, neg_ctx->context = malloc(sizeof(CtxtHandle)); if(!neg_ctx->credentials || !neg_ctx->context) - return CURLE_OUT_OF_MEMORY; + return -1; if(userp && *userp) { /* Populate our identity structure */ - result = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity); - if(result) - return result; + error = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity); + if(error) + return -1; /* Allow proper cleanup of the identity structure */ neg_ctx->p_identity = &neg_ctx->identity; @@ -159,21 +160,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, neg_ctx->p_identity, NULL, NULL, neg_ctx->credentials, &expiry); if(neg_ctx->status != SEC_E_OK) - return CURLE_LOGIN_DENIED; + return -1; } else { - result = Curl_base64_decode(header, - (unsigned char **)&input_token, - &input_token_len); - if(result) - return result; - - if(!input_token_len) { - infof(data, - "Negotiate handshake failure (empty challenge message)\n"); - - return CURLE_BAD_CONTENT_ENCODING; - } + error = Curl_base64_decode(header, + (unsigned char **)&input_token, + &input_token_len); + if(error || !input_token_len) + return -1; } /* Setup the "output" security buffer */ @@ -206,27 +200,28 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, 0, neg_ctx->context, &out_buff_desc, - &attrs, + &context_attributes, &expiry); - free(input_token); + Curl_safefree(input_token); if(GSS_ERROR(neg_ctx->status)) - return CURLE_OUT_OF_MEMORY; + return -1; if(neg_ctx->status == SEC_I_COMPLETE_NEEDED || neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE) { neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context, &out_buff_desc); if(GSS_ERROR(neg_ctx->status)) - return CURLE_RECV_ERROR; + return -1; } neg_ctx->output_token_length = out_sec_buff.cbBuffer; - return CURLE_OK; + return 0; } + CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) { struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 4373d6284..72123ed99 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,7 +35,10 @@ #include "progress.h" #include "non-ascii.h" #include "connect.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curlx.h" #include "curl_memory.h" @@ -68,11 +71,10 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) conn->data->req.protop = &http_proxy; connkeep(conn, "HTTP proxy CONNECT"); result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port, FALSE); + conn->host.name, conn->remote_port); conn->data->req.protop = prot_save; if(CURLE_OK != result) return result; - Curl_safefree(conn->allocptr.proxyuserpwd); #else return CURLE_NOT_BUILT_IN; #endif @@ -85,16 +87,12 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This * function will issue the necessary commands to get a seamless tunnel through * this proxy. After that, the socket can be used just as a normal socket. - * - * 'blocking' set to TRUE means that this function will do the entire CONNECT - * + response in a blocking fashion. Should be avoided! */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int sockindex, const char *hostname, - int remote_port, - bool blocking) + int remote_port) { int subversion=0; struct SessionHandle *data=conn->data; @@ -125,11 +123,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%hu\n", hostname, remote_port); + if(data->req.newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() it. */ - free(data->req.newurl); - data->req.newurl = NULL; + free(data->req.newurl); + data->req.newurl = NULL; + } /* initialize a dynamic send-buffer */ req_buffer = Curl_add_buffer_init(); @@ -139,7 +139,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, host_port = aprintf("%s:%hu", hostname, remote_port); if(!host_port) { - Curl_add_buffer_free(req_buffer); + free(req_buffer); return CURLE_OUT_OF_MEMORY; } @@ -159,7 +159,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, hostname, conn->bits.ipv6_ip?"]":"", remote_port); if(!hostheader) { - Curl_add_buffer_free(req_buffer); + free(req_buffer); return CURLE_OUT_OF_MEMORY; } @@ -167,7 +167,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, host = aprintf("Host: %s\r\n", hostheader); if(!host) { free(hostheader); - Curl_add_buffer_free(req_buffer); + free(req_buffer); return CURLE_OUT_OF_MEMORY; } } @@ -216,7 +216,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, failf(data, "Failed sending CONNECT to proxy"); } - Curl_add_buffer_free(req_buffer); + Curl_safefree(req_buffer); if(result) return result; @@ -229,14 +229,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, return CURLE_RECV_ERROR; } - if(!blocking) { - if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) - /* return so we'll be called again polling-style */ - return CURLE_OK; - else { - DEBUGF(infof(data, - "Read response immediately from proxy CONNECT\n")); - } + if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) + /* return so we'll be called again polling-style */ + return CURLE_OK; + else { + DEBUGF(infof(data, + "Read response immediately from proxy CONNECT\n")); } /* at this point, the tunnel_connecting phase is over. */ @@ -287,7 +285,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* proxy auth was requested and there was proxy auth available, then deem this as "mere" proxy disconnect */ conn->bits.proxy_connect_closed = TRUE; - infof(data, "Proxy CONNECT connection closed\n"); + infof(data, "Proxy CONNECT connection closed"); } else { error = SELECT_ERROR; @@ -469,7 +467,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, result = Curl_http_input_auth(conn, proxy, auth); - free(auth); + Curl_safefree(auth); if(result) return result; @@ -556,8 +554,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, infof(data, "Connect me again please\n"); } else { - free(data->req.newurl); - data->req.newurl = NULL; + if(data->req.newurl) { + /* this won't be used anymore for the CONNECT so free it now */ + free(data->req.newurl); + data->req.newurl = NULL; + } /* failure, close this connection to avoid re-use */ connclose(conn, "proxy CONNECT failure"); Curl_closesocket(conn, conn->sock[sockindex]); diff --git a/lib/http_proxy.h b/lib/http_proxy.h index 9c4f0207d..2b5e9c9b4 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,8 +26,7 @@ /* ftp can use this as well */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int tunnelsocket, - const char *hostname, int remote_port, - bool blocking); + const char *hostname, int remote_port); /* Default proxy timeout in milliseconds */ #define PROXY_TIMEOUT (3600*1000) @@ -35,7 +34,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, CURLcode Curl_proxy_connect(struct connectdata *conn); #else -#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN #define Curl_proxy_connect(x) CURLE_OK #endif diff --git a/lib/if2ip.c b/lib/if2ip.c index 6e6f9692e..389feed1c 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,9 @@ #include "inet_ntop.h" #include "strequal.h" #include "if2ip.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ diff --git a/lib/imap.c b/lib/imap.c index e6d83f2cf..767ac804b 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -80,7 +80,9 @@ #include "rawstr.h" #include "curl_sasl.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -103,12 +105,10 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...); static CURLcode imap_parse_url_options(struct connectdata *conn); static CURLcode imap_parse_url_path(struct connectdata *conn); static CURLcode imap_parse_custom_request(struct connectdata *conn); -static CURLcode imap_perform_authenticate(struct connectdata *conn, - const char *mech, - const char *initresp); -static CURLcode imap_continue_authenticate(struct connectdata *conn, - const char *resp); -static void imap_get_message(char *buffer, char** outptr); +static CURLcode imap_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + imapstate *state1, imapstate *state2); /* * IMAP protocol handler. @@ -131,7 +131,7 @@ const struct Curl_handler Curl_handler_imap = { ZERO_NULL, /* readwrite */ PORT_IMAP, /* defport */ CURLPROTO_IMAP, /* protocol */ - PROTOPT_CLOSEACTION /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD /* flags */ }; #ifdef USE_SSL @@ -156,7 +156,8 @@ const struct Curl_handler Curl_handler_imaps = { ZERO_NULL, /* readwrite */ PORT_IMAPS, /* defport */ CURLPROTO_IMAPS, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_SSL | + PROTOPT_NEEDSPWD /* flags */ }; #endif @@ -212,18 +213,6 @@ static const struct Curl_handler Curl_handler_imaps_proxy = { #endif #endif -/* SASL parameters for the imap protocol */ -static const struct SASLproto saslimap = { - "imap", /* The service name */ - '+', /* Code received when continuation is expected */ - 'O', /* Code to receive upon authentication success */ - 0, /* Maximum initial response length (no max) */ - imap_perform_authenticate, /* Send authentication command */ - imap_continue_authenticate, /* Send authentication continuation */ - imap_get_message /* Get SASL response message */ -}; - - #ifdef USE_SSL static void imap_to_imaps(struct connectdata *conn) { @@ -364,7 +353,16 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, (len >= 2 && !memcmp("+ ", line, 2))) { switch(imapc->state) { /* States which are interested in continuation responses */ - case IMAP_AUTHENTICATE: + case IMAP_AUTHENTICATE_PLAIN: + case IMAP_AUTHENTICATE_LOGIN: + case IMAP_AUTHENTICATE_LOGIN_PASSWD: + case IMAP_AUTHENTICATE_CRAMMD5: + case IMAP_AUTHENTICATE_DIGESTMD5: + case IMAP_AUTHENTICATE_DIGESTMD5_RESP: + case IMAP_AUTHENTICATE_NTLM: + case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: + case IMAP_AUTHENTICATE_XOAUTH2: + case IMAP_AUTHENTICATE_FINAL: case IMAP_APPEND: *resp = '+'; break; @@ -427,7 +425,20 @@ static void state(struct connectdata *conn, imapstate newstate) "CAPABILITY", "STARTTLS", "UPGRADETLS", - "AUTHENTICATE", + "AUTHENTICATE_PLAIN", + "AUTHENTICATE_LOGIN", + "AUTHENTICATE_LOGIN_PASSWD", + "AUTHENTICATE_CRAMMD5", + "AUTHENTICATE_DIGESTMD5", + "AUTHENTICATE_DIGESTMD5_RESP", + "AUTHENTICATE_NTLM", + "AUTHENTICATE_NTLM_TYPE2MSG", + "AUTHENTICATE_GSSAPI", + "AUTHENTICATE_GSSAPI_TOKEN", + "AUTHENTICATE_GSSAPI_NO_DATA", + "AUTHENTICATE_XOAUTH2", + "AUTHENTICATE_CANCEL", + "AUTHENTICATE_FINAL", "LOGIN", "LIST", "SELECT", @@ -460,9 +471,9 @@ static CURLcode imap_perform_capability(struct connectdata *conn) CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; - imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ - imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ - imapc->tls_supported = FALSE; /* Clear the TLS capability */ + imapc->authmechs = 0; /* No known authentication mechanisms yet */ + imapc->authused = 0; /* Clear the authentication mechanism used */ + imapc->tls_supported = FALSE; /* Clear the TLS capability */ /* Send the CAPABILITY command */ result = imap_sendf(conn, "CAPABILITY"); @@ -547,8 +558,8 @@ static CURLcode imap_perform_login(struct connectdata *conn) result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", passwd ? passwd : ""); - free(user); - free(passwd); + Curl_safefree(user); + Curl_safefree(passwd); if(!result) state(conn, IMAP_LOGIN); @@ -565,17 +576,24 @@ static CURLcode imap_perform_login(struct connectdata *conn) */ static CURLcode imap_perform_authenticate(struct connectdata *conn, const char *mech, - const char *initresp) + const char *initresp, + imapstate state1, imapstate state2) { CURLcode result = CURLE_OK; if(initresp) { /* Send the AUTHENTICATE command with the initial response */ result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); + + if(!result) + state(conn, state2); } else { /* Send the AUTHENTICATE command */ result = imap_sendf(conn, "AUTHENTICATE %s", mech); + + if(!result) + state(conn, state1); } return result; @@ -583,20 +601,6 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn, /*********************************************************************** * - * imap_continue_authenticate() - * - * Sends SASL continuation data or cancellation. - */ -static CURLcode imap_continue_authenticate(struct connectdata *conn, - const char *resp) -{ - struct imap_conn *imapc = &conn->proto.imapc; - - return Curl_pp_sendf(&imapc->pp, "%s", resp); -} - -/*********************************************************************** - * * imap_perform_authentication() * * Initiates the authentication sequence, with the appropriate SASL @@ -607,22 +611,31 @@ static CURLcode imap_perform_authentication(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; - saslprogress progress; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + imapstate state1 = IMAP_STOP; + imapstate state2 = IMAP_STOP; - /* Check we have enough data to authenticate with and end the + /* Check we have a username and password to authenticate with and end the connect phase if we don't */ - if(!Curl_sasl_can_authenticate(&imapc->sasl, conn)) { + if(!conn->bits.user_passwd) { state(conn, IMAP_STOP); + return result; } /* Calculate the SASL login details */ - result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress); + result = imap_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); if(!result) { - if(progress == SASL_INPROGRESS) - state(conn, IMAP_AUTHENTICATE); - else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + if(mech && (imapc->preftype & IMAP_TYPE_SASL)) { + /* Perform SASL based authentication */ + result = imap_perform_authenticate(conn, mech, initresp, state1, state2); + } + else if((!imapc->login_disabled) && + (imapc->preftype & IMAP_TYPE_CLEARTEXT)) /* Perform clear text authentication */ result = imap_perform_login(conn); else { @@ -632,6 +645,8 @@ static CURLcode imap_perform_authentication(struct connectdata *conn) } } + Curl_safefree(initresp); + return result; } @@ -661,7 +676,7 @@ static CURLcode imap_perform_list(struct connectdata *conn) /* Send the LIST command */ result = imap_sendf(conn, "LIST \"%s\" *", mailbox); - free(mailbox); + Curl_safefree(mailbox); } if(!result) @@ -702,7 +717,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) /* Send the SELECT command */ result = imap_sendf(conn, "SELECT %s", mailbox); - free(mailbox); + Curl_safefree(mailbox); if(!result) state(conn, IMAP_SELECT); @@ -777,7 +792,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", mailbox, conn->data->state.infilesize); - free(mailbox); + Curl_safefree(mailbox); if(!result) state(conn, IMAP_APPEND); @@ -899,16 +914,26 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, /* Do we have a SASL based authentication mechanism? */ else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { - size_t llen; - unsigned int mechbit; - line += 5; wordlen -= 5; /* Test the word for a matching authentication mechanism */ - if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && - llen == wordlen) - imapc->sasl.authmechs |= mechbit; + if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN)) + imapc->authmechs |= SASL_MECH_LOGIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN)) + imapc->authmechs |= SASL_MECH_PLAIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5)) + imapc->authmechs |= SASL_MECH_CRAM_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5)) + imapc->authmechs |= SASL_MECH_DIGEST_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI)) + imapc->authmechs |= SASL_MECH_GSSAPI; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL)) + imapc->authmechs |= SASL_MECH_EXTERNAL; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM)) + imapc->authmechs |= SASL_MECH_NTLM; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) + imapc->authmechs |= SASL_MECH_XOAUTH2; } line += wordlen; @@ -961,36 +986,569 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, return result; } -/* For SASL authentication responses */ -static CURLcode imap_state_auth_resp(struct connectdata *conn, - int imapcode, - imapstate instate) +/* For AUTHENTICATE PLAIN (without initial response) responses */ +static CURLcode imap_state_auth_plain_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *plainauth = NULL; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied. %c", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, + &plainauth, &len); + if(!result && plainauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + + Curl_safefree(plainauth); + + return result; +} + +/* For AUTHENTICATE LOGIN (without initial response) responses */ +static CURLcode imap_state_auth_login_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authuser = NULL; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the user message */ + result = Curl_sasl_create_login_message(data, conn->user, + &authuser, &len); + if(!result && authuser) { + /* Send the user */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser); + + if(!result) + state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD); + } + } + + Curl_safefree(authuser); + + return result; +} + +/* For AUTHENTICATE LOGIN user entry responses */ +static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authpasswd = NULL; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the password message */ + result = Curl_sasl_create_login_message(data, conn->passwd, + &authpasswd, &len); + if(!result && authpasswd) { + /* Send the password */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + + Curl_safefree(authpasswd); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/* For AUTHENTICATE CRAM-MD5 responses */ +static CURLcode imap_state_auth_cram_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg = NULL; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + imap_get_message(data->state.buffer, &chlg64); + + /* Decode the challenge message */ + result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); + + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); + } + else { + /* Create the response message */ + result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &rplyb64, &len); + if(!result && rplyb64) { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + + Curl_safefree(chlg); + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTHENTICATE DIGEST-MD5 challenge responses */ +static CURLcode imap_state_auth_digest_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + imap_get_message(data->state.buffer, &chlg64); + + /* Create the response message */ + result = Curl_sasl_create_digest_md5_message(data, chlg64, + conn->user, conn->passwd, + "imap", &rplyb64, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); + + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); + } + } + else { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); + + if(!result) + state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP); + } + + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTHENTICATE DIGEST-MD5 challenge-response responses */ +static CURLcode imap_state_auth_digest_resp_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Authentication failed: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Send an empty response */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + + return result; +} +#endif + +#ifdef USE_NTLM +/* For AUTHENTICATE NTLM (without initial response) responses */ +static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *type1msg = NULL; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the type-1 message */ + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + &type1msg, &len); + if(!result && type1msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg); + + if(!result) + state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG); + } + } + + Curl_safefree(type1msg); + + return result; +} + +/* For NTLM type-2 responses (sent in reponse to our type-1 message) */ +static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *type2msg = NULL; + char *type3msg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + imap_get_message(data->state.buffer, &type2msg); + + /* Decode the type-2 message */ + result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); + + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); + } + else { + /* Create the type-3 message */ + result = Curl_sasl_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &type3msg, &len); + if(!result && type3msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + } + + Curl_safefree(type3msg); + + return result; +} +#endif + +#if defined(USE_KERBEROS5) +/* For AUTHENTICATE GSSAPI (without initial response) responses */ +static CURLcode imap_state_auth_gssapi_resp(struct connectdata *conn, + int imapcode, + imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; - saslprogress progress; + size_t len = 0; + char *respmsg = NULL; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress); - if(!result) - switch(progress) { - case SASL_DONE: - state(conn, IMAP_STOP); /* Authenticated */ - break; - case SASL_IDLE: /* No mechanism left after cancellation */ - if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) - /* Perform clear text authentication */ - result = imap_perform_login(conn); - else { - failf(data, "Authentication cancelled"); - result = CURLE_LOGIN_DENIED; + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the initial response message */ + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "imap", + imapc->mutual_auth, + NULL, &conn->krb5, + &respmsg, &len); + if(!result && respmsg) { + /* Send the message */ + result = Curl_pp_sendf(&imapc->pp, "%s", respmsg); + + if(!result) + state(conn, IMAP_AUTHENTICATE_GSSAPI_TOKEN); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTHENTICATE GSSAPI user token responses */ +static CURLcode imap_state_auth_gssapi_token_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + imap_get_message(data->state.buffer, &chlgmsg); + + if(imapc->mutual_auth) + /* Decode the user token challenge and create the optional response + message */ + result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL, + imapc->mutual_auth, + chlgmsg, &conn->krb5, + &respmsg, &len); + else + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&imapc->pp, "%s", "*"); + + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); } - break; - default: - break; } + else { + /* Send the response */ + if(respmsg) + result = Curl_pp_sendf(&imapc->pp, "%s", respmsg); + else + result = Curl_pp_sendf(&imapc->pp, "%s", ""); + + if(!result) + state(conn, (imapc->mutual_auth ? IMAP_AUTHENTICATE_GSSAPI_NO_DATA : + IMAP_AUTHENTICATE_FINAL)); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTHENTICATE GSSAPI no data responses */ +static CURLcode imap_state_auth_gssapi_no_data_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + imap_get_message(data->state.buffer, &chlgmsg); + + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); + + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); + } + } + else { + /* Send the response */ + if(respmsg) { + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", respmsg); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + } + + Curl_safefree(respmsg); + + return result; +} +#endif + +/* For AUTHENTICATE XOAUTH2 (without initial response) responses */ +static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *xoauth = NULL; + + (void)instate; /* no use for this yet */ + + if(imapcode != '+') { + failf(data, "Access denied: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, + conn->xoauth2_bearer, + &xoauth, &len); + if(!result && xoauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth); + + if(!result) + state(conn, IMAP_AUTHENTICATE_FINAL); + } + } + + Curl_safefree(xoauth); + + return result; +} + +/* For AUTHENTICATE cancellation responses */ +static CURLcode imap_state_auth_cancel_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + imapstate state1 = IMAP_STOP; + imapstate state2 = IMAP_STOP; + + (void)imapcode; + (void)instate; /* no use for this yet */ + + /* Remove the offending mechanism from the supported list */ + imapc->authmechs ^= imapc->authused; + + /* Calculate alternative SASL login details */ + result = imap_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); + + if(!result) { + /* Do we have any mechanisms left or can we fallback to clear text? */ + if(mech) { + /* Retry SASL based authentication */ + result = imap_perform_authenticate(conn, mech, initresp, state1, state2); + + Curl_safefree(initresp); + } + else if((!imapc->login_disabled) && + (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + failf(data, "Authentication cancelled"); + + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/* For final responses in the AUTHENTICATE sequence */ +static CURLcode imap_state_auth_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != 'O') { + failf(data, "Authentication failed: %d", imapcode); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, IMAP_STOP); return result; } @@ -1314,8 +1872,69 @@ static CURLcode imap_statemach_act(struct connectdata *conn) result = imap_state_starttls_resp(conn, imapcode, imapc->state); break; - case IMAP_AUTHENTICATE: - result = imap_state_auth_resp(conn, imapcode, imapc->state); + case IMAP_AUTHENTICATE_PLAIN: + result = imap_state_auth_plain_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_LOGIN: + result = imap_state_auth_login_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_LOGIN_PASSWD: + result = imap_state_auth_login_password_resp(conn, imapcode, + imapc->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case IMAP_AUTHENTICATE_CRAMMD5: + result = imap_state_auth_cram_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_DIGESTMD5: + result = imap_state_auth_digest_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_DIGESTMD5_RESP: + result = imap_state_auth_digest_resp_resp(conn, imapcode, imapc->state); + break; +#endif + +#ifdef USE_NTLM + case IMAP_AUTHENTICATE_NTLM: + result = imap_state_auth_ntlm_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: + result = imap_state_auth_ntlm_type2msg_resp(conn, imapcode, + imapc->state); + break; +#endif + +#if defined(USE_KERBEROS5) + case IMAP_AUTHENTICATE_GSSAPI: + result = imap_state_auth_gssapi_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_GSSAPI_TOKEN: + result = imap_state_auth_gssapi_token_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_GSSAPI_NO_DATA: + result = imap_state_auth_gssapi_no_data_resp(conn, imapcode, + imapc->state); + break; +#endif + + case IMAP_AUTHENTICATE_XOAUTH2: + result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_CANCEL: + result = imap_state_auth_cancel_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE_FINAL: + result = imap_state_auth_final_resp(conn, imapcode, imapc->state); break; case IMAP_LOGIN: @@ -1442,7 +2061,7 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) /* Set the default preferred authentication type and mechanism */ imapc->preftype = IMAP_TYPE_ANY; - Curl_sasl_init(&imapc->sasl, &saslimap); + imapc->prefmech = SASL_AUTH_ANY; /* Initialise the pingpong layer */ Curl_pp_init(pp); @@ -1655,7 +2274,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) Curl_pp_disconnect(&imapc->pp); /* Cleanup the SASL module */ - Curl_sasl_cleanup(conn, imapc->sasl.authused); + Curl_sasl_cleanup(conn, imapc->authused); /* Cleanup our connection based variables */ Curl_safefree(imapc->mailbox); @@ -1800,7 +2419,7 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); va_end(ap); - free(taggedfmt); + Curl_safefree(taggedfmt); return result; } @@ -1929,42 +2548,69 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; - const char *ptr = conn->options; - - imapc->sasl.resetprefs = TRUE; + const char *options = conn->options; + const char *ptr = options; + bool reset = TRUE; - while(!result && ptr && *ptr) { + while(ptr && *ptr) { const char *key = ptr; - const char *value; while(*ptr && *ptr != '=') ptr++; - value = ptr + 1; + if(strnequal(key, "AUTH", 4)) { + size_t len = 0; + const char *value = ++ptr; - while(*ptr && *ptr != ';') - ptr++; + if(reset) { + reset = FALSE; + imapc->preftype = IMAP_TYPE_NONE; + imapc->prefmech = SASL_AUTH_NONE; + } - if(strnequal(key, "AUTH=", 5)) - result = Curl_sasl_parse_url_auth_option(&imapc->sasl, - value, ptr - value); - else - result = CURLE_URL_MALFORMAT; + while(*ptr && *ptr != ';') { + ptr++; + len++; + } - if(*ptr == ';') - ptr++; - } + if(strnequal(value, "*", len)) { + imapc->preftype = IMAP_TYPE_ANY; + imapc->prefmech = SASL_AUTH_ANY; + } + else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_LOGIN; + } + else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_PLAIN; + } + else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_CRAM_MD5; + } + else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_DIGEST_MD5; + } + else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_GSSAPI; + } + else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_NTLM; + } + else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) { + imapc->preftype = IMAP_TYPE_SASL; + imapc->prefmech |= SASL_MECH_XOAUTH2; + } - switch(imapc->sasl.prefmech) { - case SASL_AUTH_NONE: - imapc->preftype = IMAP_TYPE_NONE; - break; - case SASL_AUTH_DEFAULT: - imapc->preftype = IMAP_TYPE_ANY; - break; - default: - imapc->preftype = IMAP_TYPE_SASL; - break; + if(*ptr == ';') + ptr++; + } + else + result = CURLE_URL_MALFORMAT; } return result; @@ -2031,7 +2677,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) /* Decode the value parameter */ result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE); if(result) { - free(name); + Curl_safefree(name); return result; } @@ -2070,14 +2716,14 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) value = NULL; } else { - free(name); - free(value); + Curl_safefree(name); + Curl_safefree(value); return CURLE_URL_MALFORMAT; } - free(name); - free(value); + Curl_safefree(name); + Curl_safefree(value); } /* Does the URL contain a query parameter? Only valid when we have a mailbox @@ -2139,4 +2785,108 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn) return result; } +/*********************************************************************** + * + * imap_calc_sasl_details() + * + * Calculate the required login details for SASL authentication. + */ +static CURLcode imap_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + imapstate *state1, imapstate *state2) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ +#if defined(USE_KERBEROS5) + if((imapc->authmechs & SASL_MECH_GSSAPI) && + (imapc->prefmech & SASL_MECH_GSSAPI)) { + imapc->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */ + + *mech = SASL_MECH_STRING_GSSAPI; + *state1 = IMAP_AUTHENTICATE_GSSAPI; + *state2 = IMAP_AUTHENTICATE_GSSAPI_TOKEN; + imapc->authused = SASL_MECH_GSSAPI; + + if(imapc->ir_supported || data->set.sasl_ir) + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "imap", + imapc->mutual_auth, + NULL, &conn->krb5, + initresp, len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if((imapc->authmechs & SASL_MECH_DIGEST_MD5) && + (imapc->prefmech & SASL_MECH_DIGEST_MD5)) { + *mech = SASL_MECH_STRING_DIGEST_MD5; + *state1 = IMAP_AUTHENTICATE_DIGESTMD5; + imapc->authused = SASL_MECH_DIGEST_MD5; + } + else if((imapc->authmechs & SASL_MECH_CRAM_MD5) && + (imapc->prefmech & SASL_MECH_CRAM_MD5)) { + *mech = SASL_MECH_STRING_CRAM_MD5; + *state1 = IMAP_AUTHENTICATE_CRAMMD5; + imapc->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if((imapc->authmechs & SASL_MECH_NTLM) && + (imapc->prefmech & SASL_MECH_NTLM)) { + *mech = SASL_MECH_STRING_NTLM; + *state1 = IMAP_AUTHENTICATE_NTLM; + *state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; + imapc->authused = SASL_MECH_NTLM; + + if(imapc->ir_supported || data->set.sasl_ir) + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + initresp, len); + } + else +#endif + if(((imapc->authmechs & SASL_MECH_XOAUTH2) && + (imapc->prefmech & SASL_MECH_XOAUTH2) && + (imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) { + *mech = SASL_MECH_STRING_XOAUTH2; + *state1 = IMAP_AUTHENTICATE_XOAUTH2; + *state2 = IMAP_AUTHENTICATE_FINAL; + imapc->authused = SASL_MECH_XOAUTH2; + + if(imapc->ir_supported || data->set.sasl_ir) + result = Curl_sasl_create_xoauth2_message(data, conn->user, + conn->xoauth2_bearer, + initresp, len); + } + else if((imapc->authmechs & SASL_MECH_LOGIN) && + (imapc->prefmech & SASL_MECH_LOGIN)) { + *mech = SASL_MECH_STRING_LOGIN; + *state1 = IMAP_AUTHENTICATE_LOGIN; + *state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; + imapc->authused = SASL_MECH_LOGIN; + + if(imapc->ir_supported || data->set.sasl_ir) + result = Curl_sasl_create_login_message(data, conn->user, initresp, len); + } + else if((imapc->authmechs & SASL_MECH_PLAIN) && + (imapc->prefmech & SASL_MECH_PLAIN)) { + *mech = SASL_MECH_STRING_PLAIN; + *state1 = IMAP_AUTHENTICATE_PLAIN; + *state2 = IMAP_AUTHENTICATE_FINAL; + imapc->authused = SASL_MECH_PLAIN; + + if(imapc->ir_supported || data->set.sasl_ir) + result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, + initresp, len); + } + + return result; +} + #endif /* CURL_DISABLE_IMAP */ diff --git a/lib/imap.h b/lib/imap.h index 3189daa3c..768fc4b8c 100644 --- a/lib/imap.h +++ b/lib/imap.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2009 - 2014, 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 "pingpong.h" -#include "curl_sasl.h" /**************************************************************************** * IMAP unique setup @@ -36,7 +35,20 @@ typedef enum { IMAP_STARTTLS, IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ - IMAP_AUTHENTICATE, + IMAP_AUTHENTICATE_PLAIN, + IMAP_AUTHENTICATE_LOGIN, + IMAP_AUTHENTICATE_LOGIN_PASSWD, + IMAP_AUTHENTICATE_CRAMMD5, + IMAP_AUTHENTICATE_DIGESTMD5, + IMAP_AUTHENTICATE_DIGESTMD5_RESP, + IMAP_AUTHENTICATE_NTLM, + IMAP_AUTHENTICATE_NTLM_TYPE2MSG, + IMAP_AUTHENTICATE_GSSAPI, + IMAP_AUTHENTICATE_GSSAPI_TOKEN, + IMAP_AUTHENTICATE_GSSAPI_NO_DATA, + IMAP_AUTHENTICATE_XOAUTH2, + IMAP_AUTHENTICATE_CANCEL, + IMAP_AUTHENTICATE_FINAL, IMAP_LOGIN, IMAP_LIST, IMAP_SELECT, @@ -71,13 +83,16 @@ struct imap_conn { struct pingpong pp; imapstate state; /* Always use imap.c:state() to change state! */ bool ssldone; /* Is connect() over SSL done? */ - struct SASL sasl; /* SASL-related parameters */ + unsigned int authmechs; /* Accepted authentication mechanisms */ unsigned int preftype; /* Preferred authentication type */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ int cmdid; /* Last used command ID */ char resptag[5]; /* Response tag to wait for */ bool tls_supported; /* StartTLS capability supported by server */ bool login_disabled; /* LOGIN command disabled by server */ bool ir_supported; /* Initial response supported by server */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ char *mailbox; /* The last selected mailbox */ char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ }; diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index da9a3ab43..c32715005 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -32,7 +32,8 @@ #include <arpa/inet.h> #endif -#include "curl_printf.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "inet_ntop.h" diff --git a/lib/inet_ntop.h b/lib/inet_ntop.h index cc4bdbb89..db28ed807 100644 --- a/lib/inet_ntop.h +++ b/lib/inet_ntop.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2009, 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 @@ char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); #include <arpa/inet.h> #endif #define Curl_inet_ntop(af,addr,buf,size) \ - inet_ntop(af, addr, buf, (curl_socklen_t)size) + inet_ntop(af,addr,buf,(curl_socklen_t)size) #endif #endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/lib/krb5.c b/lib/krb5.c index ad7dd67af..a0d7bb4f0 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -1,8 +1,8 @@ /* GSSAPI/krb5 support for FTP - loosely based on old krb4.c * - * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2013 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). - * Copyright (c) 2004 - 2015 Daniel Stenberg + * Copyright (c) 2004 - 2014 Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,13 @@ #include "curl_setup.h" -#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP) +#ifndef CURL_DISABLE_FTP +#ifdef HAVE_GSSAPI + +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif #ifdef HAVE_NETDB_H #include <netdb.h> @@ -46,11 +52,13 @@ #include "curl_gssapi.h" #include "sendf.h" #include "curl_sec.h" +#include "curl_memory.h" #include "warnless.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" #define LOCAL_ADDR (&conn->local_addr) @@ -246,8 +254,7 @@ krb5_auth(void *app_data, struct connectdata *conn) result = Curl_base64_encode(data, (char *)output_buffer.value, output_buffer.length, &p, &base64_sz); if(result) { - Curl_infof(data, "base64-encoding: %s\n", - curl_easy_strerror(result)); + Curl_infof(data,"base64-encoding: %s\n", curl_easy_strerror(result)); ret = AUTH_CONTINUE; break; } @@ -279,8 +286,7 @@ krb5_auth(void *app_data, struct connectdata *conn) (unsigned char **)&_gssresp.value, &_gssresp.length); if(result) { - Curl_failf(data, "base64-decoding: %s", - curl_easy_strerror(result)); + Curl_failf(data,"base64-decoding: %s", curl_easy_strerror(result)); ret = AUTH_CONTINUE; break; } @@ -329,4 +335,5 @@ struct Curl_sec_client_mech Curl_krb5_client_mech = { krb5_decode }; -#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */ +#endif /* HAVE_GSSAPI */ +#endif /* CURL_DISABLE_FTP */ diff --git a/lib/ldap.c b/lib/ldap.c index 4d9128226..f27fa9008 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -35,7 +35,7 @@ * OpenLDAP library versions, USE_OPENLDAP shall not be defined. */ -#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ +#ifdef CURL_LDAP_WIN /* Use Windows LDAP implementation. */ # include <winldap.h> # ifndef LDAP_VENDOR_NAME # error Your Platform SDK is NOT sufficient for LDAP support! \ @@ -54,15 +54,6 @@ # endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ #endif -/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs - * in BoringSSL's <openssl/x509.h> - */ -#ifdef HAVE_BORINGSSL -# undef X509_NAME -# undef X509_CERT_PAIR -# undef X509_EXTENSIONS -#endif - #include "urldata.h" #include <curl/curl.h> #include "sendf.h" @@ -72,14 +63,15 @@ #include "strequal.h" #include "strtok.h" #include "curl_ldap.h" +#include "curl_memory.h" #include "curl_multibyte.h" #include "curl_base64.h" #include "rawstr.h" #include "connect.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "memdebug.h" #ifndef HAVE_LDAP_URL_PARSE @@ -89,7 +81,7 @@ typedef struct { char *lud_host; int lud_port; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) TCHAR *lud_dn; TCHAR **lud_attrs; #else @@ -97,7 +89,7 @@ typedef struct { char **lud_attrs; #endif int lud_scope; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) TCHAR *lud_filter; #else char *lud_filter; @@ -200,9 +192,9 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) size_t val_b64_sz = 0; curl_off_t dlsize = 0; #ifdef LDAP_OPT_NETWORK_TIMEOUT - struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ + struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */ #endif -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) TCHAR *host = NULL; TCHAR *user = NULL; TCHAR *passwd = NULL; @@ -234,7 +226,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) infof(data, "LDAP local: trying to establish %s connection\n", ldap_ssl ? "encrypted" : "cleartext"); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) host = Curl_convert_UTF8_to_tchar(conn->host.name); if(!host) { result = CURLE_OUT_OF_MEMORY; @@ -267,7 +259,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) if(ldap_ssl) { #ifdef HAVE_LDAP_SSL -#ifdef USE_WIN32_LDAP +#ifdef CURL_LDAP_WIN /* Win32 LDAP SDK doesn't support insecure mode without CA! */ server = ldap_sslinit(host, (int)conn->port, 1); ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); @@ -400,7 +392,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } } -#ifdef USE_WIN32_LDAP +#ifdef CURL_LDAP_WIN ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #endif @@ -429,7 +421,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) entryIterator; entryIterator = ldap_next_entry(server, entryIterator), num++) { BerElement *ber = NULL; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) TCHAR *attribute; #else char *attribute; /*! suspicious that this isn't 'const' */ @@ -440,7 +432,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) { char *name; size_t name_len; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) TCHAR *dn = ldap_get_dn(server, entryIterator); name = Curl_convert_tchar_to_UTF8(dn); if(!name) { @@ -457,7 +449,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); if(result) { -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(name); #endif ldap_memfree(dn); @@ -468,7 +460,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, name_len); if(result) { -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(name); #endif ldap_memfree(dn); @@ -478,7 +470,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) { -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(name); #endif ldap_memfree(dn); @@ -488,7 +480,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) dlsize += name_len + 5; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(name); #endif ldap_memfree(dn); @@ -500,7 +492,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) attribute = ldap_next_attribute(server, entryIterator, ber)) { BerValue **vals; size_t attr_len; -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) char *attr = Curl_convert_tchar_to_UTF8(attribute); if(!attr) { if(ber) @@ -521,7 +513,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -535,7 +527,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) (char *) attr, attr_len); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -548,7 +540,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -570,7 +562,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) &val_b64_sz); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -586,7 +578,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) free(val_b64); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -604,7 +596,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) vals[i]->bv_len); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -620,7 +612,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) { ldap_value_free_len(vals); -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -638,7 +630,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) } /* Free the attribute as we are done with it */ -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(attr); #endif ldap_memfree(attribute); @@ -670,7 +662,7 @@ quit: ldapssl_client_deinit(); #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) Curl_unicodefree(passwd); Curl_unicodefree(user); Curl_unicodefree(host); @@ -810,7 +802,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) goto quit; } -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) /* Convert the unescaped string to a tchar */ ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped); @@ -848,13 +840,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) } /* Allocate our array (+1 for the NULL entry) */ -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *)); #else ludp->lud_attrs = calloc(count + 1, sizeof(char *)); #endif if(!ludp->lud_attrs) { - free(attributes); + Curl_safefree(attributes); rc = LDAP_NO_MEMORY; @@ -869,14 +861,14 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) /* Unescape the attribute */ unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL); if(!unescaped) { - free(attributes); + Curl_safefree(attributes); rc = LDAP_NO_MEMORY; goto quit; } -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) /* Convert the unescaped string to a tchar */ ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped); @@ -884,7 +876,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) Curl_unicodefree(unescaped); if(!ludp->lud_attrs[i]) { - free(attributes); + Curl_safefree(attributes); rc = LDAP_NO_MEMORY; @@ -897,7 +889,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) ludp->lud_attrs_dups++; } - free(attributes); + Curl_safefree(attributes); } p = q; @@ -942,7 +934,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) goto quit; } -#if defined(USE_WIN32_LDAP) +#if defined(CURL_LDAP_WIN) /* Convert the unescaped string to a tchar */ ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped); @@ -967,7 +959,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) } quit: - free(path); + Curl_safefree(path); return rc; } @@ -998,8 +990,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp) if(!ludp) return; - free(ludp->lud_dn); - free(ludp->lud_filter); + if(ludp->lud_dn) + free(ludp->lud_dn); + + if(ludp->lud_filter) + free(ludp->lud_filter); if(ludp->lud_attrs) { for(i = 0; i < ludp->lud_attrs_dups; i++) diff --git a/lib/libcurl.plist b/lib/libcurl.plist index bc66d1977..cb602712c 100644 --- a/lib/libcurl.plist +++ b/lib/libcurl.plist @@ -15,7 +15,7 @@ <string>se.haxx.curl.libcurl</string> <key>CFBundleVersion</key> - <string>7.44.0</string> + <string>7.40.0</string> <key>CFBundleName</key> <string>libcurl</string> @@ -27,9 +27,9 @@ <string>????</string> <key>CFBundleShortVersionString</key> - <string>libcurl 7.44.0</string> + <string>libcurl 7.40.0</string> <key>CFBundleGetInfoString</key> - <string>libcurl.plist 7.44.0</string> + <string>libcurl.plist 7.40.0</string> </dict> </plist> @@ -1,38 +1,23 @@ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD4 Message-Digest Algorithm (RFC 1320). - * - * Homepage: - http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4 - * - * Author: - * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. In case - * this attempt to disclaim copyright and place the software in the public - * domain is deemed null and void, then the software is Copyright (c) 2001 - * Alexander Peslyak and it is hereby released to the general public under the - * following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * (This is a heavily cut-down "BSD license".) - * - * This differs from Colin Plumb's older public domain implementation in that - * no exactly 32-bit integer data type is required (any 32-bit or wider - * unsigned integer data type will do), there's no compile-time endianness - * configuration, and the function prototypes match OpenSSL's. No code from - * Colin Plumb's implementation has been reused; this comment merely compares - * the properties of the two independent implementations. - * - * The primary goals of this implementation are portability and ease of use. - * It is meant to be fast, but not as fast as possible. Some known - * optimizations are not included to reduce source code size and avoid - * compile-time configuration. +/*- + Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD4 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD4 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. */ #include "curl_setup.h" @@ -44,261 +29,254 @@ #include "curl_md4.h" #include "warnless.h" -#ifndef HAVE_OPENSSL +typedef unsigned int UINT4; -#include <string.h> - -/* Any 32-bit or wider unsigned integer data type will do */ -typedef unsigned int MD4_u32plus; - -typedef struct { - MD4_u32plus lo, hi; - MD4_u32plus a, b, c, d; - unsigned char buffer[64]; - MD4_u32plus block[16]; +typedef struct MD4Context { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ } MD4_CTX; -static void MD4_Init(MD4_CTX *ctx); -static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size); -static void MD4_Final(unsigned char *result, MD4_CTX *ctx); - -/* - * The basic MD4 functions. - * - * F and G are optimized compared to their RFC 1320 definitions, with the - * optimization for F borrowed from Colin Plumb's MD5 implementation. +/* Constants for MD4Transform routine. */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* - * The MD4 transformation for all three rounds. +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + +static void MD4Transform(UINT4 [4], const unsigned char [64]); +static void Encode(unsigned char *, UINT4 *, unsigned int); +static void Decode(UINT4 *, const unsigned char *, unsigned int); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G and H are basic MD4 functions. */ -#define STEP(f, a, b, c, d, x, s) \ - (a) += f((b), (c), (d)) + (x); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); - -/* - * SET reads 4 input bytes in little-endian byte order and stores them - * in a properly aligned word in host byte order. - * - * The check for little-endian architectures that tolerate unaligned - * memory accesses is just an optimization. Nothing will break if it - * doesn't work. +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits. */ -#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define SET(n) \ - (*(MD4_u32plus *)&ptr[(n) * 4]) -#define GET(n) \ - SET(n) -#else -#define SET(n) \ - (ctx->block[(n)] = \ - (MD4_u32plus)ptr[(n) * 4] | \ - ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) -#define GET(n) \ - (ctx->block[(n)]) -#endif - -/* - * This processes one or more 64-byte data blocks, but does NOT update - * the bit counters. There are no alignment requirements. +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + +/* MD4 initialization. Begins an MD4 operation, writing a new context. */ -static const void *body(MD4_CTX *ctx, const void *data, unsigned long size) +static void MD4Init(MD4_CTX *context) { - const unsigned char *ptr; - MD4_u32plus a, b, c, d; - MD4_u32plus saved_a, saved_b, saved_c, saved_d; - - ptr = (const unsigned char *)data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - do { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - -/* Round 1 */ - STEP(F, a, b, c, d, SET(0), 3) - STEP(F, d, a, b, c, SET(1), 7) - STEP(F, c, d, a, b, SET(2), 11) - STEP(F, b, c, d, a, SET(3), 19) - STEP(F, a, b, c, d, SET(4), 3) - STEP(F, d, a, b, c, SET(5), 7) - STEP(F, c, d, a, b, SET(6), 11) - STEP(F, b, c, d, a, SET(7), 19) - STEP(F, a, b, c, d, SET(8), 3) - STEP(F, d, a, b, c, SET(9), 7) - STEP(F, c, d, a, b, SET(10), 11) - STEP(F, b, c, d, a, SET(11), 19) - STEP(F, a, b, c, d, SET(12), 3) - STEP(F, d, a, b, c, SET(13), 7) - STEP(F, c, d, a, b, SET(14), 11) - STEP(F, b, c, d, a, SET(15), 19) - -/* Round 2 */ - STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3) - STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5) - STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9) - STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13) - STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3) - STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5) - STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9) - STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13) - STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3) - STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5) - STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9) - STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13) - STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3) - STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5) - STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9) - STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13) - -/* Round 3 */ - STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3) - STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9) - STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11) - STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15) - STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3) - STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9) - STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11) - STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15) - STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3) - STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9) - STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11) - STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15) - STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3) - STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9) - STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11) - STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15) - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - - ptr += 64; - } while(size -= 64); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - - return ptr; + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. + */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; } -static void MD4_Init(MD4_CTX *ctx) +/* MD4 block update operation. Continues an MD4 message-digest + operation, processing another message block, and updating the + context. + */ +static void MD4Update(MD4_CTX *context, const unsigned char *input, + unsigned int inputLen) { - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; + unsigned int i, bufindex, partLen; + + /* Compute number of bytes mod 64 */ + bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F); + /* Update number of bits */ + if((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - bufindex; + /* Transform as many times as possible. + */ + if(inputLen >= partLen) { + memcpy(&context->buffer[bufindex], input, partLen); + MD4Transform (context->state, context->buffer); + + for(i = partLen; i + 63 < inputLen; i += 64) + MD4Transform (context->state, &input[i]); + + bufindex = 0; + } + else + i = 0; - ctx->lo = 0; - ctx->hi = 0; + /* Buffer remaining input */ + memcpy(&context->buffer[bufindex], &input[i], inputLen-i); } -static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) +/* MD4 padding. */ +static void MD4Pad(MD4_CTX *context) { - MD4_u32plus saved_lo; - unsigned long used, available; + unsigned char bits[8]; + unsigned int bufindex, padLen; - saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) - ctx->hi++; - ctx->hi += (MD4_u32plus)size >> 29; + /* Save number of bits */ + Encode (bits, context->count, 8); - used = saved_lo & 0x3f; + /* Pad out to 56 mod 64. + */ + bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex); + MD4Update (context, PADDING, padLen); - if(used) { - available = 64 - used; - - if(size < available) { - memcpy(&ctx->buffer[used], data, size); - return; - } + /* Append length (before padding) */ + MD4Update (context, bits, 8); +} - memcpy(&ctx->buffer[used], data, available); - data = (const unsigned char *)data + available; - size -= available; - body(ctx, ctx->buffer, 64); - } +/* MD4 finalization. Ends an MD4 message-digest operation, writing the + the message digest and zeroizing the context. + */ +static void MD4Final (unsigned char digest[16], MD4_CTX *context) +{ + /* Do padding */ + MD4Pad (context); - if(size >= 64) { - data = body(ctx, data, size & ~(unsigned long)0x3f); - size &= 0x3f; - } + /* Store state in digest */ + Encode (digest, context->state, 16); - memcpy(ctx->buffer, data, size); + /* Zeroize sensitive information. + */ + memset(context, 0, sizeof(*context)); } -static void MD4_Final(unsigned char *result, MD4_CTX *ctx) +/* MD4 basic transformation. Transforms state based on block. + */ +static void MD4Transform (UINT4 state[4], const unsigned char block[64]) { - unsigned long used, available; - - used = ctx->lo & 0x3f; - - ctx->buffer[used++] = 0x80; + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11); /* 1 */ + FF (d, a, b, c, x[ 1], S12); /* 2 */ + FF (c, d, a, b, x[ 2], S13); /* 3 */ + FF (b, c, d, a, x[ 3], S14); /* 4 */ + FF (a, b, c, d, x[ 4], S11); /* 5 */ + FF (d, a, b, c, x[ 5], S12); /* 6 */ + FF (c, d, a, b, x[ 6], S13); /* 7 */ + FF (b, c, d, a, x[ 7], S14); /* 8 */ + FF (a, b, c, d, x[ 8], S11); /* 9 */ + FF (d, a, b, c, x[ 9], S12); /* 10 */ + FF (c, d, a, b, x[10], S13); /* 11 */ + FF (b, c, d, a, x[11], S14); /* 12 */ + FF (a, b, c, d, x[12], S11); /* 13 */ + FF (d, a, b, c, x[13], S12); /* 14 */ + FF (c, d, a, b, x[14], S13); /* 15 */ + FF (b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 0], S21); /* 17 */ + GG (d, a, b, c, x[ 4], S22); /* 18 */ + GG (c, d, a, b, x[ 8], S23); /* 19 */ + GG (b, c, d, a, x[12], S24); /* 20 */ + GG (a, b, c, d, x[ 1], S21); /* 21 */ + GG (d, a, b, c, x[ 5], S22); /* 22 */ + GG (c, d, a, b, x[ 9], S23); /* 23 */ + GG (b, c, d, a, x[13], S24); /* 24 */ + GG (a, b, c, d, x[ 2], S21); /* 25 */ + GG (d, a, b, c, x[ 6], S22); /* 26 */ + GG (c, d, a, b, x[10], S23); /* 27 */ + GG (b, c, d, a, x[14], S24); /* 28 */ + GG (a, b, c, d, x[ 3], S21); /* 29 */ + GG (d, a, b, c, x[ 7], S22); /* 30 */ + GG (c, d, a, b, x[11], S23); /* 31 */ + GG (b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 0], S31); /* 33 */ + HH (d, a, b, c, x[ 8], S32); /* 34 */ + HH (c, d, a, b, x[ 4], S33); /* 35 */ + HH (b, c, d, a, x[12], S34); /* 36 */ + HH (a, b, c, d, x[ 2], S31); /* 37 */ + HH (d, a, b, c, x[10], S32); /* 38 */ + HH (c, d, a, b, x[ 6], S33); /* 39 */ + HH (b, c, d, a, x[14], S34); /* 40 */ + HH (a, b, c, d, x[ 1], S31); /* 41 */ + HH (d, a, b, c, x[ 9], S32); /* 42 */ + HH (c, d, a, b, x[ 5], S33); /* 43 */ + HH (b, c, d, a, x[13], S34); /* 44 */ + HH (a, b, c, d, x[ 3], S31); /* 45 */ + HH (d, a, b, c, x[11], S32); /* 46 */ + HH (c, d, a, b, x[ 7], S33); /* 47 */ + HH (b, c, d, a, x[15], S34); /* 48 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + */ + memset(x, 0, sizeof(x)); +} - available = 64 - used; +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode(unsigned char *output, UINT4 *input, unsigned int len) +{ + unsigned int i, j; - if(available < 8) { - memset(&ctx->buffer[used], 0, available); - body(ctx, ctx->buffer, 64); - used = 0; - available = 64; + for(i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } - - memset(&ctx->buffer[used], 0, available - 8); - - ctx->lo <<= 3; - ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); - ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); - ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); - ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff); - ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); - ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); - ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); - ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); - - body(ctx, ctx->buffer, 64); - - result[0] = curlx_ultouc((ctx->a)&0xff); - result[1] = curlx_ultouc((ctx->a >> 8)&0xff); - result[2] = curlx_ultouc((ctx->a >> 16)&0xff); - result[3] = curlx_ultouc(ctx->a >> 24); - result[4] = curlx_ultouc((ctx->b)&0xff); - result[5] = curlx_ultouc((ctx->b >> 8)&0xff); - result[6] = curlx_ultouc((ctx->b >> 16)&0xff); - result[7] = curlx_ultouc(ctx->b >> 24); - result[8] = curlx_ultouc((ctx->c)&0xff); - result[9] = curlx_ultouc((ctx->c >> 8)&0xff); - result[10] = curlx_ultouc((ctx->c >> 16)&0xff); - result[11] = curlx_ultouc(ctx->c >> 24); - result[12] = curlx_ultouc((ctx->d)&0xff); - result[13] = curlx_ultouc((ctx->d >> 8)&0xff); - result[14] = curlx_ultouc((ctx->d >> 16)&0xff); - result[15] = curlx_ultouc(ctx->d >> 24); - - memset(ctx, 0, sizeof(*ctx)); } -#endif +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (UINT4 *output, const unsigned char *input, + unsigned int len) +{ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) { MD4_CTX ctx; - MD4_Init(&ctx); - MD4_Update(&ctx, input, curlx_uztoui(len)); - MD4_Final(output, &ctx); + MD4Init(&ctx); + MD4Update(&ctx, input, curlx_uztoui(len)); + MD4Final(output, &ctx); } #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */ @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,10 +28,11 @@ #include "curl_hmac.h" #include "warnless.h" +#include "curl_memory.h" + #if defined(USE_GNUTLS_NETTLE) #include <nettle/md5.h> -#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -57,7 +58,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) #elif defined(USE_GNUTLS) #include <gcrypt.h> -#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -81,12 +81,14 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) gcry_md_close(*ctx); } -#elif defined(USE_OPENSSL) +#elif defined(USE_SSLEAY) /* When OpenSSL is available we use the MD5-function from OpenSSL */ -#include <openssl/md5.h> -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" + +# ifdef USE_OPENSSL +# include <openssl/md5.h> +# else +# include <md5.h> +# endif #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ @@ -101,9 +103,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */ # include <CommonCrypto/CommonDigest.h> # define MD5_CTX CC_MD5_CTX -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" static void MD5_Init(MD5_CTX *ctx) { @@ -125,9 +124,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) #elif defined(_WIN32) #include <wincrypt.h> -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" typedef struct { HCRYPTPROV hCryptProv; @@ -161,326 +157,314 @@ 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 */ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD5 Message-Digest Algorithm (RFC 1321). - * - * Homepage: - http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * - * Author: - * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. - * In case this attempt to disclaim copyright and place the software in the - * public domain is deemed null and void, then the software is - * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * (This is a heavily cut-down "BSD license".) - * - * This differs from Colin Plumb's older public domain implementation in that - * no exactly 32-bit integer data type is required (any 32-bit or wider - * unsigned integer data type will do), there's no compile-time endianness - * configuration, and the function prototypes match OpenSSL's. No code from - * Colin Plumb's implementation has been reused; this comment merely compares - * the properties of the two independent implementations. - * - * The primary goals of this implementation are portability and ease of use. - * It is meant to be fast, but not as fast as possible. Some known - * optimizations are not included to reduce source code size and avoid - * compile-time configuration. - */ -#include <string.h> +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. -/* Any 32-bit or wider unsigned integer data type will do */ -typedef unsigned int MD5_u32plus; +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. -typedef struct { - MD5_u32plus lo, hi; - MD5_u32plus a, b, c, d; - unsigned char buffer[64]; - MD5_u32plus block[16]; -} MD5_CTX; +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. -static void MD5_Init(MD5_CTX *ctx); -static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); -static void MD5_Final(unsigned char *result, MD5_CTX *ctx); +These notices must be retained in any copies of any part of this +documentation and/or software. + */ -/* - * The basic MD5 functions. - * - * F and G are optimized compared to their RFC 1321 definitions for - * architectures that lack an AND-NOT instruction, just like in Colin Plumb's - * implementation. +/* UINT4 defines a four byte word */ +typedef unsigned int UINT4; + +/* MD5 context. */ +struct md5_ctx { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +}; + +typedef struct md5_ctx MD5_CTX; + +static void MD5_Init(struct md5_ctx *); +static void MD5_Update(struct md5_ctx *, const unsigned char *, unsigned int); +static void MD5_Final(unsigned char [16], struct md5_ctx *); + +/* Constants for MD5Transform routine. */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) -#define H(x, y, z) (((x) ^ (y)) ^ (z)) -#define H2(x, y, z) ((x) ^ ((y) ^ (z))) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) - -/* - * The MD5 transformation for all four rounds. + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(UINT4 [4], const unsigned char [64]); +static void Encode(unsigned char *, UINT4 *, unsigned int); +static void Decode(UINT4 *, const unsigned char *, unsigned int); + +static const unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. */ -#define STEP(f, a, b, c, d, x, t, s) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); - -/* - * SET reads 4 input bytes in little-endian byte order and stores them - * in a properly aligned word in host byte order. - * - * The check for little-endian architectures that tolerate unaligned - * memory accesses is just an optimization. Nothing will break if it - * doesn't work. +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ -#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define SET(n) \ - (*(MD5_u32plus *)&ptr[(n) * 4]) -#define GET(n) \ - SET(n) -#else -#define SET(n) \ - (ctx->block[(n)] = \ - (MD5_u32plus)ptr[(n) * 4] | \ - ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) -#define GET(n) \ - (ctx->block[(n)]) -#endif - -/* - * This processes one or more 64-byte data blocks, but does NOT update - * the bit counters. There are no alignment requirements. +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. */ -static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) -{ - const unsigned char *ptr; - MD5_u32plus a, b, c, d; - MD5_u32plus saved_a, saved_b, saved_c, saved_d; - - ptr = (const unsigned char *)data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - do { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - -/* Round 1 */ - STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) - STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) - STEP(F, c, d, a, b, SET(2), 0x242070db, 17) - STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) - STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) - STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) - STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) - STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) - STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) - STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) - STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) - STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) - STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) - STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) - STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) - STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) - -/* Round 2 */ - STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) - STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) - STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) - STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) - STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) - STEP(G, d, a, b, c, GET(10), 0x02441453, 9) - STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) - STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) - STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) - STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) - STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) - STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) - STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) - STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) - STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) - STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) - -/* Round 3 */ - STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) - STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) - STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) - STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) - STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) - STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) - STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) - STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) - STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) - STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) - STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) - STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) - STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) - STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) - STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) - STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) - -/* Round 4 */ - STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) - STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) - STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) - STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) - STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) - STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) - STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) - STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) - STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) - STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) - STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) - STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) - STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) - STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) - STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) - STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - - ptr += 64; - } while(size -= 64); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - - return ptr; -} +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } -static void MD5_Init(MD5_CTX *ctx) +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +static void MD5_Init(struct md5_ctx *context) { - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - - ctx->lo = 0; - ctx->hi = 0; + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; } -static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +static void MD5_Update (struct md5_ctx *context, /* context */ + const unsigned char *input, /* input block */ + unsigned int inputLen) /* length of input block */ { - MD5_u32plus saved_lo; - unsigned long used, available; + unsigned int i, bufindex, partLen; - saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) - ctx->hi++; - ctx->hi += (MD5_u32plus)size >> 29; + /* Compute number of bytes mod 64 */ + bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F); - used = saved_lo & 0x3f; + /* Update number of bits */ + if((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); - if(used) { - available = 64 - used; + partLen = 64 - bufindex; - if(size < available) { - memcpy(&ctx->buffer[used], data, size); - return; - } + /* Transform as many times as possible. */ + if(inputLen >= partLen) { + memcpy(&context->buffer[bufindex], input, partLen); + MD5Transform(context->state, context->buffer); - memcpy(&ctx->buffer[used], data, available); - data = (const unsigned char *)data + available; - size -= available; - body(ctx, ctx->buffer, 64); - } + for(i = partLen; i + 63 < inputLen; i += 64) + MD5Transform(context->state, &input[i]); - if(size >= 64) { - data = body(ctx, data, size & ~(unsigned long)0x3f); - size &= 0x3f; + bufindex = 0; } + else + i = 0; - memcpy(ctx->buffer, data, size); + /* Buffer remaining input */ + memcpy(&context->buffer[bufindex], &input[i], inputLen-i); } -static void MD5_Final(unsigned char *result, MD5_CTX *ctx) +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. +*/ +static void MD5_Final(unsigned char digest[16], /* message digest */ + struct md5_ctx *context) /* context */ { - unsigned long used, available; + unsigned char bits[8]; + unsigned int count, padLen; - used = ctx->lo & 0x3f; + /* Save number of bits */ + Encode (bits, context->count, 8); - ctx->buffer[used++] = 0x80; + /* Pad out to 56 mod 64. */ + count = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (count < 56) ? (56 - count) : (120 - count); + MD5_Update (context, PADDING, padLen); - available = 64 - used; + /* Append length (before padding) */ + MD5_Update (context, bits, 8); - if(available < 8) { - memset(&ctx->buffer[used], 0, available); - body(ctx, ctx->buffer, 64); - used = 0; - available = 64; + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset ((void *)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ +static void MD5Transform(UINT4 state[4], + const unsigned char block[64]) +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset((void *)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (unsigned char *output, + UINT4 *input, + unsigned int len) +{ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. +*/ +static void Decode (UINT4 *output, + const unsigned char *input, + unsigned int len) +{ + unsigned int i, j; - memset(&ctx->buffer[used], 0, available - 8); - - ctx->lo <<= 3; - ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); - ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); - ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); - ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24); - ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); - ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); - ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); - ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); - - body(ctx, ctx->buffer, 64); - - result[0] = curlx_ultouc((ctx->a)&0xff); - result[1] = curlx_ultouc((ctx->a >> 8)&0xff); - result[2] = curlx_ultouc((ctx->a >> 16)&0xff); - result[3] = curlx_ultouc(ctx->a >> 24); - result[4] = curlx_ultouc((ctx->b)&0xff); - result[5] = curlx_ultouc((ctx->b >> 8)&0xff); - result[6] = curlx_ultouc((ctx->b >> 16)&0xff); - result[7] = curlx_ultouc(ctx->b >> 24); - result[8] = curlx_ultouc((ctx->c)&0xff); - result[9] = curlx_ultouc((ctx->c >> 8)&0xff); - result[10] = curlx_ultouc((ctx->c >> 16)&0xff); - result[11] = curlx_ultouc(ctx->c >> 24); - result[12] = curlx_ultouc((ctx->d)&0xff); - result[13] = curlx_ultouc((ctx->d >> 8)&0xff); - result[14] = curlx_ultouc((ctx->d >> 16)&0xff); - result[15] = curlx_ultouc(ctx->d >> 24); - - memset(ctx, 0, sizeof(*ctx)); + for(i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } #endif /* CRYPTO LIBS */ +/* The last #include file should be: */ +#include "memdebug.h" + const HMAC_params Curl_HMAC_MD5[] = { { (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */ @@ -502,9 +486,6 @@ const MD5_params Curl_DIGEST_MD5[] = { } }; -/* - * @unittest: 1601 - */ void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ const unsigned char *input) { diff --git a/lib/memdebug.c b/lib/memdebug.c index dd8889b2d..4afa620a0 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,7 +26,8 @@ #include <curl/curl.h> -#include "curl_printf.h" +#define _MPRINTF_REPLACE +#include <curl/mprintf.h> #include "urldata.h" #define MEMDEBUG_NODEFINES /* don't redefine the standard functions */ @@ -112,7 +113,7 @@ void curl_memdebug(const char *logname) { if(!logfile) { if(logname && *logname) - logfile = fopen(logname, FOPEN_WRITETEXT); + logfile = fopen(logname, "w"); else logfile = stderr; #ifdef MEMDEBUG_LOG_SYNC @@ -342,10 +343,10 @@ curl_socket_t curl_socket(int domain, int type, int protocol, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d socket() = %d\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d socket() = %ld\n" : - "FD %s:%d socket() = %zd\n"; + "FD %s:%d socket() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socket() = %ld\n" : + "FD %s:%d socket() = %zd\n" ; curl_socket_t sockfd = socket(domain, type, protocol); @@ -361,10 +362,10 @@ int curl_socketpair(int domain, int type, int protocol, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d socketpair() = %d %d\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d socketpair() = %ld %ld\n" : - "FD %s:%d socketpair() = %zd %zd\n"; + "FD %s:%d socketpair() = %d %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socketpair() = %ld %ld\n" : + "FD %s:%d socketpair() = %zd %zd\n" ; int res = socketpair(domain, type, protocol, socket_vector); @@ -379,10 +380,10 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d accept() = %d\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d accept() = %ld\n" : - "FD %s:%d accept() = %zd\n"; + "FD %s:%d accept() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d accept() = %ld\n" : + "FD %s:%d accept() = %zd\n" ; struct sockaddr *addr = (struct sockaddr *)saddr; curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen; @@ -399,10 +400,10 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d sclose(%d)\n": - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d sclose(%ld)\n": - "FD %s:%d sclose(%zd)\n"; + "FD %s:%d sclose(%d)\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d sclose(%ld)\n" : + "FD %s:%d sclose(%zd)\n" ; if(source) curl_memlog(fmt, source, line, sockfd); diff --git a/lib/memdebug.h b/lib/memdebug.h index cfac1e077..bd565c8dc 100644 --- a/lib/memdebug.h +++ b/lib/memdebug.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, 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 @@ -104,13 +104,13 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); #endif #define socket(domain,type,protocol)\ - curl_socket(domain, type, protocol, __LINE__, __FILE__) + curl_socket(domain,type,protocol,__LINE__,__FILE__) #undef accept /* for those with accept as a macro */ #define accept(sock,addr,len)\ - curl_accept(sock, addr, len, __LINE__, __FILE__) + curl_accept(sock,addr,len,__LINE__,__FILE__) #ifdef HAVE_SOCKETPAIR #define socketpair(domain,type,protocol,socket_vector)\ - curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) + curl_socketpair(domain,type,protocol,socket_vector,__LINE__,__FILE__) #endif #ifdef HAVE_GETADDRINFO @@ -119,25 +119,25 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); our macro as for other platforms. Instead, we redefine the new name they define getaddrinfo to become! */ #define ogetaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__) #else #undef getaddrinfo #define getaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__) #endif #endif /* HAVE_GETADDRINFO */ #ifdef HAVE_GETNAMEINFO #undef getnameinfo #define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \ - curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \ - __LINE__, __FILE__) + curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \ + __FILE__) #endif /* HAVE_GETNAMEINFO */ #ifdef HAVE_FREEADDRINFO #undef freeaddrinfo #define freeaddrinfo(data) \ - curl_dofreeaddrinfo(data, __LINE__, __FILE__) + curl_dofreeaddrinfo(data,__LINE__,__FILE__) #endif /* HAVE_FREEADDRINFO */ /* sclose is probably already defined, redefine it! */ @@ -171,6 +171,6 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); */ #define Curl_safefree(ptr) \ - do { free((ptr)); (ptr) = NULL;} WHILE_FALSE + do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE #endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/lib/mk-ca-bundle.pl b/lib/mk-ca-bundle.pl index c2080e952..0b1331840 100755 --- a/lib/mk-ca-bundle.pl +++ b/lib/mk-ca-bundle.pl @@ -185,12 +185,6 @@ sub VERSION_MESSAGE() { warning_message() unless ($opt_q || $url =~ m/^(ht|f)tps:/i ); HELP_MESSAGE() if ($opt_h); -sub report($@) { - my $output = shift; - - print STDERR $output . "\n" unless $opt_q; -} - sub is_in_list($@) { my $target = shift; @@ -284,20 +278,20 @@ my $fetched; my $oldsha1 = oldsha1($crt); -report "SHA1 of old file: $oldsha1"; +print STDERR "SHA1 of old file: $oldsha1\n" if (!$opt_q); -report "Downloading '$txt' ..."; +print STDERR "Downloading '$txt' ...\n" if (!$opt_q); if($curl && !$opt_n) { my $https = $url; $https =~ s/^http:/https:/; - report "Get certdata over HTTPS with curl!"; + print STDERR "Get certdata over HTTPS with curl!\n" if (!$opt_q); my $quiet = $opt_q ? "-s" : ""; my @out = `curl -w %{response_code} $quiet -O $https`; if(@out && $out[0] == 200) { $fetched = 1; } else { - report "Failed downloading HTTPS with curl, trying HTTP with LWP"; + print STDERR "Failed downloading HTTPS with curl, trying HTTP with LWP\n" if (!$opt_q); } } @@ -306,14 +300,15 @@ unless ($fetched || ($opt_n and -e $txt)) { $ua->env_proxy(); $resp = $ua->mirror($url, $txt); if ($resp && $resp->code eq '304') { - report "Not modified"; + print STDERR "Not modified\n" unless $opt_q; exit 0 if -e $crt && !$opt_f; } else { $fetched = 1; } if( !$resp || $resp->code !~ /^(?:200|304)$/ ) { - report "Unable to download latest data: " - . ($resp? $resp->code . ' - ' . $resp->message : "LWP failed"); + print STDERR "Unable to download latest data: " + . ($resp? $resp->code . ' - ' . $resp->message : "LWP failed") . "\n" + unless $opt_q; exit 1 if -e $crt || ! -r $txt; } } @@ -330,11 +325,11 @@ if(!$filedate) { my $newsha1= sha1($txt); if(!$opt_f && $oldsha1 eq $newsha1) { - report "Downloaded file identical to previous run\'s source file. Exiting"; + print STDERR "Downloaded file identical to previous run\'s source file. Exiting\n"; exit; } -report "SHA1 of new file: $newsha1"; +print STDERR "SHA1 of new file: $newsha1\n"; my $currentdate = scalar gmtime($filedate); @@ -366,7 +361,7 @@ print CRT <<EOT; EOT -report "Processing '$txt' ..."; +print STDERR "Processing '$txt' ...\n" if (!$opt_q); my $caname; my $certnum = 0; my $skipnum = 0; @@ -418,9 +413,9 @@ while (<TXT>) { last if (/^#/); if (/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) { if ( !is_in_list($1,@valid_mozilla_trust_purposes) ) { - report "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2"; + print STDERR "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2\n" if (!$opt_q); } elsif ( !is_in_list($2,@valid_mozilla_trust_levels) ) { - report "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2"; + print STDERR "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2\n" if (!$opt_q); } else { push @{$trust_purposes_by_level{$2}}, $1; } @@ -475,7 +470,7 @@ while (<TXT>) { open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; } } - report "Parsing: $caname" if ($opt_v); + print STDERR "Parsing: $caname\n" if ($opt_v); $certnum ++; $start_of_cert = 0; } @@ -496,4 +491,4 @@ unless( $stdout ) { rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n"; } unlink $txt if ($opt_u); -report "Done ($certnum CA certs processed, $skipnum skipped)."; +print STDERR "Done ($certnum CA certs processed, $skipnum skipped).\n" if (!$opt_q); diff --git a/lib/multi.c b/lib/multi.c index 00520873c..97c9e65cf 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -39,10 +39,14 @@ #include "warnless.h" #include "speedcheck.h" #include "conncache.h" +#include "bundles.h" #include "multihandle.h" #include "pipeline.h" #include "sigpipe.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -62,11 +66,15 @@ #define GOOD_MULTI_HANDLE(x) \ ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE)) +#define GOOD_EASY_HANDLE(x) \ + ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)) static void singlesocket(struct Curl_multi *multi, struct SessionHandle *data); static int update_timer(struct Curl_multi *multi); +static bool isHandleAtHead(struct SessionHandle *handle, + struct curl_llist *pipeline); static CURLMcode add_next_timeout(struct timeval now, struct Curl_multi *multi, struct SessionHandle *d); @@ -81,7 +89,6 @@ static const char * const statename[]={ "WAITRESOLVE", "WAITCONNECT", "WAITPROXYCONNECT", - "SENDPROTOCONNECT", "PROTOCONNECT", "WAITDO", "DO", @@ -150,6 +157,7 @@ static void mstate(struct SessionHandle *data, CURLMstate state struct Curl_sh_entry { struct SessionHandle *easy; + time_t timestamp; int action; /* what action READ/WRITE this socket waits for */ curl_socket_t socket; /* mainly to ease debugging */ void *socketp; /* settable by users with curl_multi_assign() */ @@ -211,7 +219,8 @@ static void sh_freeentry(void *freethis) { struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis; - free(p); + if(p) + free(p); } static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) @@ -247,10 +256,10 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num) * per call." * */ -static int sh_init(struct curl_hash *hash, int hashsize) +static struct curl_hash *sh_init(int hashsize) { - return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare, - sh_freeentry); + return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare, + sh_freeentry); } /* @@ -289,13 +298,16 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ multi->type = CURL_MULTI_HANDLE; - if(Curl_mk_dnscache(&multi->hostcache)) + multi->hostcache = Curl_mk_dnscache(); + if(!multi->hostcache) goto error; - if(sh_init(&multi->sockhash, hashsize)) + multi->sockhash = sh_init(hashsize); + if(!multi->sockhash) goto error; - if(Curl_conncache_init(&multi->conn_cache, chashsize)) + multi->conn_cache = Curl_conncache_init(chashsize); + if(!multi->conn_cache) goto error; multi->msglist = Curl_llist_alloc(multi_freeamsg); @@ -312,7 +324,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ goto error; multi->closure_handle->multi = multi; - multi->closure_handle->state.conn_cache = &multi->conn_cache; + multi->closure_handle->state.conn_cache = multi->conn_cache; multi->max_pipeline_length = 5; @@ -322,9 +334,12 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ error: - Curl_hash_destroy(&multi->sockhash); - Curl_hash_destroy(&multi->hostcache); - Curl_conncache_destroy(&multi->conn_cache); + Curl_hash_destroy(multi->sockhash); + multi->sockhash = NULL; + Curl_hash_destroy(multi->hostcache); + multi->hostcache = NULL; + Curl_conncache_destroy(multi->conn_cache); + multi->conn_cache = NULL; Curl_close(multi->closure_handle); multi->closure_handle = NULL; Curl_llist_destroy(multi->msglist, NULL); @@ -393,12 +408,14 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, easy handle's one is currently not set. */ else if(!data->dns.hostcache || (data->dns.hostcachetype == HCACHE_NONE)) { - data->dns.hostcache = &multi->hostcache; + data->dns.hostcache = multi->hostcache; data->dns.hostcachetype = HCACHE_MULTI; } /* Point to the multi's connection cache */ - data->state.conn_cache = &multi->conn_cache; + data->state.conn_cache = multi->conn_cache; + + data->state.infilesize = data->set.filesize; /* This adds the new entry at the 'end' of the doubly-linked circular list of SessionHandle structs to try and maintain a FIFO queue so @@ -414,7 +431,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, multi->easylp = data; /* the new last node */ } else { - /* first node, make prev NULL! */ + /* first node, make both prev and next be NULL! */ + data->next = NULL; data->prev = NULL; multi->easylp = multi->easyp = data; /* both first and last */ } @@ -490,22 +508,18 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle, if(!data->multi) return CURLM_OK; /* it is already removed so let's say it is fine! */ + premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE; easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ? TRUE : FALSE; /* If the 'state' is not INIT or COMPLETED, we might need to do something nice to put the easy_handle in a good known state when this returns. */ - if(premature) { + if(premature) /* this handle is "alive" so we need to count down the total number of alive connections when this is removed */ multi->num_alive--; - /* When this handle gets removed, other handles may be able to get the - connection */ - Curl_multi_process_pending_handles(multi); - } - if(data->easy_conn && data->mstate > CURLM_STATE_DO && data->mstate < CURLM_STATE_COMPLETED) { @@ -607,10 +621,9 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle, return CURLM_OK; } -/* Return TRUE if the application asked for a certain set of pipelining */ -bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits) +bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi) { - return (multi && (multi->pipelining & bits)) ? TRUE : FALSE; + return (multi && multi->pipelining_enabled) ? TRUE : FALSE; } void Curl_multi_handlePipeBreak(struct SessionHandle *data) @@ -636,24 +649,14 @@ static int waitconnect_getsock(struct connectdata *conn, } } - return rc; -} - -static int waitproxyconnect_getsock(struct connectdata *conn, - curl_socket_t *sock, - int numsocks) -{ - if(!numsocks) - return GETSOCK_BLANK; - - sock[0] = conn->sock[FIRSTSOCKET]; - /* when we've sent a CONNECT to a proxy, we should rather wait for the socket to become readable to be able to get the response headers */ - if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) - return GETSOCK_READSOCK(0); + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) { + sock[0] = conn->sock[FIRSTSOCKET]; + rc = GETSOCK_READSOCK(0); + } - return GETSOCK_WRITESOCK(0); + return rc; } static int domore_getsock(struct connectdata *conn, @@ -706,7 +709,6 @@ static int multi_getsock(struct SessionHandle *data, return Curl_resolver_getsock(data->easy_conn, socks, numsocks); case CURLM_STATE_PROTOCONNECT: - case CURLM_STATE_SENDPROTOCONNECT: return Curl_protocol_getsock(data->easy_conn, socks, numsocks); case CURLM_STATE_DO: @@ -714,8 +716,6 @@ static int multi_getsock(struct SessionHandle *data, return Curl_doing_getsock(data->easy_conn, socks, numsocks); case CURLM_STATE_WAITPROXYCONNECT: - return waitproxyconnect_getsock(data->easy_conn, socks, numsocks); - case CURLM_STATE_WAITCONNECT: return waitconnect_getsock(data->easy_conn, socks, numsocks); @@ -916,62 +916,12 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, else i = 0; - free(ufds); + Curl_safefree(ufds); if(ret) *ret = i; return CURLM_OK; } -/* - * Curl_multi_connchanged() is called to tell that there is a connection in - * this multi handle that has changed state (pipelining become possible, the - * number of allowed streams changed or similar), and a subsequent use of this - * multi handle should move CONNECT_PEND handles back to CONNECT to have them - * retry. - */ -void Curl_multi_connchanged(struct Curl_multi *multi) -{ - multi->recheckstate = TRUE; -} - -/* - * multi_ischanged() is called - * - * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND - * => CONNECT action. - * - * Set 'clear' to TRUE to have it also clear the state variable. - */ -static bool multi_ischanged(struct Curl_multi *multi, bool clear) -{ - bool retval = multi->recheckstate; - if(clear) - multi->recheckstate = FALSE; - return retval; -} - -CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, - struct SessionHandle *data, - struct connectdata *conn) -{ - CURLMcode rc; - - rc = curl_multi_add_handle(multi, data); - if(!rc) { - struct SingleRequest *k = &data->req; - - /* pass in NULL for 'conn' here since we don't want to init the - connection, only this transfer */ - Curl_init_do(data, NULL); - - /* take this handle to the perform state right away */ - multistate(data, CURLM_STATE_PERFORM); - data->easy_conn = conn; - k->keepon |= KEEP_RECV; /* setup to receive! */ - } - return rc; -} - static CURLMcode multi_runsingle(struct Curl_multi *multi, struct timeval now, struct SessionHandle *data) @@ -1023,11 +973,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, return CURLM_INTERNAL_ERROR; } - if(multi_ischanged(multi, TRUE)) { - DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n")); - Curl_multi_process_pending_handles(multi); - } - if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT && data->mstate < CURLM_STATE_COMPLETED) /* Make sure we set the connection's current owner */ @@ -1074,7 +1019,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, disconnect_conn = TRUE; } result = CURLE_OPERATION_TIMEDOUT; - (void)Curl_done(&data->easy_conn, result, TRUE); /* Skip the statemachine and go directly to error handling section. */ goto statemachine_end; } @@ -1132,7 +1076,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, rc = CURLM_CALL_MULTI_PERFORM; if(protocol_connect) - multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)? + multistate(data, multi->pipelining_enabled? CURLM_STATE_WAITDO:CURLM_STATE_DO); else { #ifndef CURL_DISABLE_HTTP @@ -1154,9 +1098,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, struct connectdata *conn = data->easy_conn; /* check if we have the name resolved by now */ + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port); if(dns) { + dns->inuse++; /* we use it! */ #ifdef CURLRES_ASYNCH conn->async.dns = dns; conn->async.done = TRUE; @@ -1165,6 +1113,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, infof(data, "Hostname was found in DNS cache\n"); } + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + if(!dns) result = Curl_resolver_is_resolved(data->easy_conn, &dns); @@ -1189,7 +1140,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* call again please so that we get the next socket setup */ rc = CURLM_CALL_MULTI_PERFORM; if(protocol_connect) - multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)? + multistate(data, multi->pipelining_enabled? CURLM_STATE_WAITDO:CURLM_STATE_DO); else { #ifndef CURL_DISABLE_HTTP @@ -1215,29 +1166,40 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ result = Curl_http_connect(data->easy_conn, &protocol_connect); - rc = CURLM_CALL_MULTI_PERFORM; if(data->easy_conn->bits.proxy_connect_closed) { /* connect back to proxy again */ result = CURLE_OK; - Curl_done(&data->easy_conn, CURLE_OK, FALSE); + rc = CURLM_CALL_MULTI_PERFORM; multistate(data, CURLM_STATE_CONNECT); } else if(!result) { if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) - /* initiate protocol connect phase */ - multistate(data, CURLM_STATE_SENDPROTOCONNECT); + multistate(data, CURLM_STATE_WAITCONNECT); } break; #endif case CURLM_STATE_WAITCONNECT: - /* awaiting a completion of an asynch TCP connect */ - result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected); - if(connected && !result) { + /* awaiting a completion of an asynch connect */ + result = Curl_is_connected(data->easy_conn, + FIRSTSOCKET, + &connected); + if(connected) { + + if(!result) + /* if everything is still fine we do the protocol-specific connect + setup */ + result = Curl_protocol_connect(data->easy_conn, + &protocol_connect); + } + + if(data->easy_conn->bits.proxy_connect_closed) { + /* connect back to proxy again since it was closed in a proxy CONNECT + setup */ + result = CURLE_OK; rc = CURLM_CALL_MULTI_PERFORM; - multistate(data, data->easy_conn->bits.tunnel_proxy? - CURLM_STATE_WAITPROXYCONNECT: - CURLM_STATE_SENDPROTOCONNECT); + multistate(data, CURLM_STATE_CONNECT); + break; } else if(result) { /* failure detected */ @@ -1245,25 +1207,29 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, disconnect_conn = TRUE; break; } - break; - case CURLM_STATE_SENDPROTOCONNECT: - result = Curl_protocol_connect(data->easy_conn, &protocol_connect); - if(!protocol_connect) - /* switch to waiting state */ - multistate(data, CURLM_STATE_PROTOCONNECT); - else if(!result) { - /* protocol connect has completed, go WAITDO or DO */ - multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)? - CURLM_STATE_WAITDO:CURLM_STATE_DO); + if(connected) { + if(!protocol_connect) { + /* We have a TCP connection, but 'protocol_connect' may be false + and then we continue to 'STATE_PROTOCONNECT'. If protocol + connect is TRUE, we move on to STATE_DO. + BUT if we are using a proxy we must change to WAITPROXYCONNECT + */ +#ifndef CURL_DISABLE_HTTP + if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_PROTOCONNECT); + + } + else + /* after the connect has completed, go WAITDO or DO */ + multistate(data, multi->pipelining_enabled? + CURLM_STATE_WAITDO:CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; } - else if(result) { - /* failure detected */ - Curl_posttransfer(data); - Curl_done(&data->easy_conn, result, TRUE); - disconnect_conn = TRUE; - } break; case CURLM_STATE_PROTOCONNECT: @@ -1271,7 +1237,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, result = Curl_protocol_connecting(data->easy_conn, &protocol_connect); if(!result && protocol_connect) { /* after the connect has completed, go WAITDO or DO */ - multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)? + multistate(data, multi->pipelining_enabled? CURLM_STATE_WAITDO:CURLM_STATE_DO); rc = CURLM_CALL_MULTI_PERFORM; } @@ -1285,8 +1251,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_WAITDO: /* Wait for our turn to DO when we're pipelining requests */ - if(Curl_pipeline_checkget_write(data, data->easy_conn)) { - /* Grabbed the channel */ +#ifdef DEBUGBUILD + infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n", + data->easy_conn->connection_id, + data->easy_conn->send_pipe->size, + data->easy_conn->writechannel_inuse?"TRUE":"FALSE", + isHandleAtHead(data, + data->easy_conn->send_pipe)?"TRUE":"FALSE"); +#endif + if(!data->easy_conn->writechannel_inuse && + isHandleAtHead(data, + data->easy_conn->send_pipe)) { + /* Grab the channel */ + data->easy_conn->writechannel_inuse = TRUE; multistate(data, CURLM_STATE_DO); rc = CURLM_CALL_MULTI_PERFORM; } @@ -1469,11 +1446,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_WAITPERFORM: /* Wait for our turn to PERFORM */ - if(Curl_pipeline_checkget_read(data, data->easy_conn)) { - /* Grabbed the channel */ + if(!data->easy_conn->readchannel_inuse && + isHandleAtHead(data, + data->easy_conn->recv_pipe)) { + /* Grab the channel */ + data->easy_conn->readchannel_inuse = TRUE; multistate(data, CURLM_STATE_PERFORM); rc = CURLM_CALL_MULTI_PERFORM; } +#ifdef DEBUGBUILD + else { + infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n", + data->easy_conn->connection_id, + data->easy_conn->recv_pipe->size, + data->easy_conn->readchannel_inuse?"TRUE":"FALSE", + isHandleAtHead(data, + data->easy_conn->recv_pipe)?"TRUE":"FALSE"); + } +#endif break; case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ @@ -1528,17 +1518,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } /* read/write data if it is ready to do so */ - result = Curl_readwrite(data->easy_conn, data, &done); + result = Curl_readwrite(data->easy_conn, &done); k = &data->req; - if(!(k->keepon & KEEP_RECV)) + if(!(k->keepon & KEEP_RECV)) { /* We're done receiving */ - Curl_pipeline_leave_read(data->easy_conn); + data->easy_conn->readchannel_inuse = FALSE; + } - if(!(k->keepon & KEEP_SEND)) + if(!(k->keepon & KEEP_SEND)) { /* We're done sending */ - Curl_pipeline_leave_write(data->easy_conn); + data->easy_conn->writechannel_inuse = FALSE; + } if(done || (result == CURLE_RECV_ERROR)) { /* If CURLE_RECV_ERROR happens early enough, we assume it was a race @@ -1594,7 +1586,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(!retry) { /* if the URL is a follow-location and not just a retried request then figure out the URL here */ - free(newurl); + if(newurl) + free(newurl); newurl = data->req.newurl; data->req.newurl = NULL; follow = FOLLOW_REDIR; @@ -1619,7 +1612,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* but first check to see if we got a location info even though we're not following redirects */ if(data->req.location) { - free(newurl); + if(newurl) + free(newurl); newurl = data->req.location; data->req.location = NULL; result = Curl_follow(data, newurl, FOLLOW_FAKE); @@ -1634,7 +1628,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } } - free(newurl); + if(newurl) + free(newurl); break; } @@ -1715,15 +1710,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, data->state.pipe_broke = FALSE; - /* Check if we can move pending requests to send pipe */ - Curl_multi_process_pending_handles(multi); - if(data->easy_conn) { /* if this has a connection, unsubscribe from the pipelines */ - Curl_pipeline_leave_write(data->easy_conn); - Curl_pipeline_leave_read(data->easy_conn); + data->easy_conn->writechannel_inuse = FALSE; + data->easy_conn->readchannel_inuse = FALSE; Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe); Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + /* Check if we can move pending requests to send pipe */ + Curl_multi_process_pending_handles(multi); if(disconnect_conn) { /* Don't attempt to send data over a connection that timed out */ @@ -1770,7 +1764,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_MSGSENT); } - } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); + } while(rc == CURLM_CALL_MULTI_PERFORM); data->result = result; @@ -1850,7 +1844,7 @@ static void close_all_connections(struct Curl_multi *multi) { struct connectdata *conn; - conn = Curl_conncache_find_first_connection(&multi->conn_cache); + conn = Curl_conncache_find_first_connection(multi->conn_cache); while(conn) { SIGPIPE_VARIABLE(pipe_st); conn->data = multi->closure_handle; @@ -1860,7 +1854,7 @@ static void close_all_connections(struct Curl_multi *multi) (void)Curl_disconnect(conn, FALSE); sigpipe_restore(&pipe_st); - conn = Curl_conncache_find_first_connection(&multi->conn_cache); + conn = Curl_conncache_find_first_connection(multi->conn_cache); } } @@ -1883,15 +1877,15 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle) sigpipe_ignore(multi->closure_handle, &pipe_st); restore_pipe = TRUE; - multi->closure_handle->dns.hostcache = &multi->hostcache; + multi->closure_handle->dns.hostcache = multi->hostcache; Curl_hostcache_clean(multi->closure_handle, multi->closure_handle->dns.hostcache); Curl_close(multi->closure_handle); } - Curl_hash_destroy(&multi->sockhash); - Curl_conncache_destroy(&multi->conn_cache); + Curl_hash_destroy(multi->sockhash); + Curl_conncache_destroy(multi->conn_cache); Curl_llist_destroy(multi->msglist, NULL); Curl_llist_destroy(multi->pending, NULL); @@ -1913,7 +1907,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle) data = nextdata; } - Curl_hash_destroy(&multi->hostcache); + Curl_hash_destroy(multi->hostcache); /* Free the blacklists by setting them to NULL */ Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); @@ -2002,7 +1996,7 @@ static void singlesocket(struct Curl_multi *multi, s = socks[i]; /* get it from the hash */ - entry = Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s)); + entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); if(curraction & GETSOCK_READSOCK(i)) action |= CURL_POLL_IN; @@ -2017,7 +2011,7 @@ static void singlesocket(struct Curl_multi *multi, } else { /* this is a socket we didn't have before, add it! */ - entry = sh_addentry(&multi->sockhash, s, data); + entry = sh_addentry(multi->sockhash, s, data); if(!entry) /* fatal */ return; @@ -2053,7 +2047,7 @@ static void singlesocket(struct Curl_multi *multi, /* this socket has been removed. Tell the app to remove it */ remove_sock_from_hash = TRUE; - entry = Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s)); + entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); if(entry) { /* check if the socket to be removed serves a connection which has other easy-s in a pipeline. In this case the socket should not be @@ -2068,7 +2062,7 @@ static void singlesocket(struct Curl_multi *multi, for the recv_pipe, or the first (in case this particular easy isn't already) */ if(entry->easy == data) { - if(Curl_recvpipe_head(data, easy_conn)) + if(isHandleAtHead(data, easy_conn->recv_pipe)) entry->easy = easy_conn->recv_pipe->head->next->ptr; else entry->easy = easy_conn->recv_pipe->head->ptr; @@ -2082,7 +2076,7 @@ static void singlesocket(struct Curl_multi *multi, for the send_pipe, or the first (in case this particular easy isn't already) */ if(entry->easy == data) { - if(Curl_sendpipe_head(data, easy_conn)) + if(isHandleAtHead(data, easy_conn->send_pipe)) entry->easy = easy_conn->send_pipe->head->next->ptr; else entry->easy = easy_conn->send_pipe->head->ptr; @@ -2108,7 +2102,7 @@ static void singlesocket(struct Curl_multi *multi, CURL_POLL_REMOVE, multi->socket_userp, entry->socketp); - sh_delentry(&multi->sockhash, s); + sh_delentry(multi->sockhash, s); } } @@ -2135,7 +2129,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) /* this is set if this connection is part of a handle that is added to a multi handle, and only then this is necessary */ struct Curl_sh_entry *entry = - Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s)); + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); if(entry) { if(multi->socket_cb) @@ -2144,7 +2138,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) entry->socketp); /* now remove it from the socket hash */ - sh_delentry(&multi->sockhash, s); + sh_delentry(multi->sockhash, s); } } } @@ -2237,7 +2231,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi, else if(s != CURL_SOCKET_TIMEOUT) { struct Curl_sh_entry *entry = - Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s)); + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); if(!entry) /* Unmatched socket, we can't act on it but we ignore this fact. In @@ -2361,14 +2355,8 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle, case CURLMOPT_SOCKETDATA: multi->socket_userp = va_arg(param, void *); break; - case CURLMOPT_PUSHFUNCTION: - multi->push_cb = va_arg(param, curl_push_callback); - break; - case CURLMOPT_PUSHDATA: - multi->push_userp = va_arg(param, void *); - break; case CURLMOPT_PIPELINING: - multi->pipelining = va_arg(param, long); + multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLMOPT_TIMERFUNCTION: multi->timer_cb = va_arg(param, curl_multi_timer_callback); @@ -2446,7 +2434,7 @@ CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles) static CURLMcode multi_timeout(struct Curl_multi *multi, long *timeout_ms) { - static struct timeval tv_zero = {0, 0}; + static struct timeval tv_zero = {0,0}; if(multi->timetree) { /* we have a tree of expire times */ @@ -2504,7 +2492,7 @@ static int update_timer(struct Curl_multi *multi) return -1; } if(timeout_ms < 0) { - static const struct timeval none={0, 0}; + static const struct timeval none={0,0}; if(Curl_splaycomparekeys(none, multi->timer_lastcall)) { multi->timer_lastcall = none; /* there's no timeout now but there was one previously, tell the app to @@ -2526,6 +2514,16 @@ static int update_timer(struct Curl_multi *multi) return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp); } +static bool isHandleAtHead(struct SessionHandle *handle, + struct curl_llist *pipeline) +{ + struct curl_llist_element *curr = pipeline->head; + if(curr) + return (curr->ptr == handle) ? TRUE : FALSE; + + return FALSE; +} + /* * multi_freetimeout() * @@ -2725,8 +2723,7 @@ CURLMcode curl_multi_assign(CURLM *multi_handle, struct Curl_multi *multi = (struct Curl_multi *)multi_handle; if(s != CURL_SOCKET_BAD) - there = Curl_hash_pick(&multi->sockhash, (char *)&s, - sizeof(curl_socket_t)); + there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t)); if(!there) return CURLM_BAD_SOCKET; @@ -2746,6 +2743,11 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi) return multi ? multi->max_total_connections : 0; } +size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi) +{ + return multi ? multi->max_pipeline_length : 0; +} + curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi) { return multi ? multi->content_length_penalty_size : 0; @@ -2805,7 +2807,7 @@ void Curl_multi_dump(const struct Curl_multi *multi_handle) for(i=0; i < data->numsocks; i++) { curl_socket_t s = data->sockets[i]; struct Curl_sh_entry *entry = - Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s)); + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); fprintf(stderr, "%d ", (int)s); if(!entry) { diff --git a/lib/multihandle.h b/lib/multihandle.h index 6c24f50f1..1a4b1d966 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,8 +22,6 @@ * ***************************************************************************/ -#include "conncache.h" - struct Curl_message { /* the 'CURLMsg' is the part that is visible to the external user */ struct CURLMsg extmsg; @@ -37,23 +35,22 @@ typedef enum { CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ - CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ + CURLM_STATE_WAITCONNECT, /* 4 - awaiting the connect to finalize */ CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */ - CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ - CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect + CURLM_STATE_PROTOCONNECT, /* 6 - completing the protocol-specific connect phase */ - CURLM_STATE_WAITDO, /* 8 - wait for our turn to send the request */ - CURLM_STATE_DO, /* 9 - start send off the request (part 1) */ - CURLM_STATE_DOING, /* 10 - sending off the request (part 1) */ - CURLM_STATE_DO_MORE, /* 11 - send off the request (part 2) */ - CURLM_STATE_DO_DONE, /* 12 - done sending off request */ - CURLM_STATE_WAITPERFORM, /* 13 - wait for our turn to read the response */ - CURLM_STATE_PERFORM, /* 14 - transfer data */ - CURLM_STATE_TOOFAST, /* 15 - wait because limit-rate exceeded */ - CURLM_STATE_DONE, /* 16 - post data transfer operation */ - CURLM_STATE_COMPLETED, /* 17 - operation complete */ - CURLM_STATE_MSGSENT, /* 18 - the operation complete message is sent */ - CURLM_STATE_LAST /* 19 - not a true state, never use this */ + CURLM_STATE_WAITDO, /* 7 - wait for our turn to send the request */ + CURLM_STATE_DO, /* 8 - start send off the request (part 1) */ + CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */ + CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */ + CURLM_STATE_DO_DONE, /* 11 - done sending off request */ + CURLM_STATE_WAITPERFORM, /* 12 - wait for our turn to read the response */ + CURLM_STATE_PERFORM, /* 13 - transfer data */ + CURLM_STATE_TOOFAST, /* 14 - wait because limit-rate exceeded */ + CURLM_STATE_DONE, /* 15 - post data transfer operation */ + CURLM_STATE_COMPLETED, /* 16 - operation complete */ + CURLM_STATE_MSGSENT, /* 17 - the operation complete message is sent */ + CURLM_STATE_LAST /* 18 - not a true state, never use this */ } CURLMstate; /* we support N sockets per easy handle. Set the corresponding bit to what @@ -62,8 +59,6 @@ typedef enum { #define GETSOCK_READABLE (0x00ff) #define GETSOCK_WRITABLE (0xff00) -#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX) - /* This is the struct known as CURLM on the outside */ struct Curl_multi { /* First a simple identifier to easier detect if a user mix up @@ -87,12 +82,8 @@ struct Curl_multi { curl_socket_callback socket_cb; void *socket_userp; - /* callback function and user data pointer for server push */ - curl_push_callback push_cb; - void *push_userp; - /* Hostname cache */ - struct curl_hash hostcache; + struct curl_hash *hostcache; /* timetree points to the splay-tree of time nodes to figure out expire times of all currently set timers */ @@ -101,15 +92,13 @@ struct Curl_multi { /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note the pluralis form, there can be more than one easy handle waiting on the same actual socket) */ - struct curl_hash sockhash; + struct curl_hash *sockhash; - /* pipelining wanted bits (CURLPIPE*) */ - long pipelining; - - bool recheckstate; /* see Curl_multi_connchanged */ + /* Whether pipelining is enabled for this multi handle */ + bool pipelining_enabled; /* Shared connection cache (bundles)*/ - struct conncache conn_cache; + struct conncache *conn_cache; /* This handle will be used for closing the cached connections in curl_multi_cleanup() */ @@ -150,3 +139,4 @@ struct Curl_multi { }; #endif /* HEADER_CURL_MULTIHANDLE_H */ + diff --git a/lib/multiif.h b/lib/multiif.h index e6323adf5..d8acfcabe 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,7 +27,8 @@ */ void Curl_expire(struct SessionHandle *data, long milli); void Curl_expire_latest(struct SessionHandle *data, long milli); -bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits); + +bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi); void Curl_multi_handlePipeBreak(struct SessionHandle *data); /* Internal version of curl_multi_init() accepts size parameters for the @@ -59,6 +60,9 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi); /* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */ size_t Curl_multi_max_host_connections(struct Curl_multi *multi); +/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */ +size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi); + /* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */ curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi); @@ -74,8 +78,6 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi); /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ size_t Curl_multi_max_total_connections(struct Curl_multi *multi); -void Curl_multi_connchanged(struct Curl_multi *multi); - /* * Curl_multi_closed() * @@ -88,10 +90,4 @@ void Curl_multi_connchanged(struct Curl_multi *multi); void Curl_multi_closed(struct connectdata *conn, curl_socket_t s); -/* - * Add a handle and move it into PERFORM state at once. For pushed streams. - */ -CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, - struct SessionHandle *data, - struct connectdata *conn); #endif /* HEADER_CURL_MULTIIF_H */ diff --git a/lib/netrc.c b/lib/netrc.c index 06f8ea15a..7435d94c4 100644 --- a/lib/netrc.c +++ b/lib/netrc.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,11 +31,13 @@ #include "strequal.h" #include "strtok.h" +#include "curl_memory.h" #include "rawstr.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* Get user and password from .netrc when given a machine name */ @@ -102,16 +104,16 @@ int Curl_parsenetrc(const char *host, netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC); if(home_alloc) - free(home); + Curl_safefree(home); if(!netrcfile) { return -1; } netrc_alloc = TRUE; } - file = fopen(netrcfile, FOPEN_READTEXT); + file = fopen(netrcfile, "r"); if(netrc_alloc) - free(netrcfile); + Curl_safefree(netrcfile); if(file) { char *tok; char *tok_buf; @@ -137,10 +139,6 @@ int Curl_parsenetrc(const char *host, 'password'. */ state=HOSTFOUND; } - else if(Curl_raw_equal("default", tok)) { - state=HOSTVALID; - retcode=0; /* we did find our host */ - } break; case HOSTFOUND: if(Curl_raw_equal(host, tok)) { diff --git a/lib/nwlib.c b/lib/nwlib.c index bd3f27eac..252bf11ec 100644 --- a/lib/nwlib.c +++ b/lib/nwlib.c @@ -282,7 +282,9 @@ int DisposeLibraryData( void *data ) if(data) { void *tenbytes = ((libdata_t *) data)->tenbytes; - free(tenbytes); + if(tenbytes) + free(tenbytes); + free(data); } @@ -294,7 +296,9 @@ void DisposeThreadData( void *data ) if(data) { void *twentybytes = ((libthreaddata_t *) data)->twentybytes; - free(twentybytes); + if(twentybytes) + free(twentybytes); + free(data); } } diff --git a/lib/openldap.c b/lib/openldap.c index bee552f33..b94c0348f 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010, Howard Chu, <hyc@openldap.org> - * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010, 2013, Howard Chu, <hyc@openldap.org> + * Copyright (C) 2011 - 2014, 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 @@ -44,12 +44,13 @@ #include "vtls/vtls.h" #include "transfer.h" #include "curl_ldap.h" +#include "curl_memory.h" #include "curl_base64.h" #include "connect.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "memdebug.h" #ifndef _LDAP_PVT_H @@ -229,7 +230,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) ldapconninfo *li = conn->proto.generic; struct SessionHandle *data = conn->data; LDAPMessage *msg = NULL; - struct timeval tv = {0, 1}, *tvp; + struct timeval tv = {0,1}, *tvp; int rc, err; char *info = NULL; @@ -380,7 +381,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); return CURLE_LDAP_SEARCH_FAILED; } - lr = calloc(1, sizeof(ldapreqinfo)); + lr = calloc(1,sizeof(ldapreqinfo)); if(!lr) return CURLE_OUT_OF_MEMORY; lr->msgid = msgid; @@ -422,7 +423,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, LDAPMessage *msg = NULL; LDAPMessage *ent; BerElement *ber = NULL; - struct timeval tv = {0, 1}; + struct timeval tv = {0,1}; (void)len; (void)buf; diff --git a/lib/pingpong.c b/lib/pingpong.c index 167079272..2c2741f0a 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,7 +34,9 @@ #include "multiif.h" #include "non-ascii.h" #include "vtls/vtls.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -493,8 +495,10 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp) CURLcode Curl_pp_disconnect(struct pingpong *pp) { - free(pp->cache); - pp->cache = NULL; + if(pp->cache) { + free(pp->cache); + pp->cache = NULL; + } return CURLE_OK; } diff --git a/lib/pipeline.c b/lib/pipeline.c index 1b38836cb..2645fdb48 100644 --- a/lib/pipeline.c +++ b/lib/pipeline.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se> - * Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2013-2014, 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 @@ -32,6 +32,7 @@ #include "pipeline.h" #include "sendf.h" #include "rawstr.h" +#include "bundles.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -48,13 +49,15 @@ static void site_blacklist_llist_dtor(void *user, void *element) (void)user; Curl_safefree(entry->hostname); - free(entry); + Curl_safefree(entry); } static void server_blacklist_llist_dtor(void *user, void *element) { + char *server_name = element; (void)user; - free(element); + + Curl_safefree(server_name); } bool Curl_pipeline_penalized(struct SessionHandle *data, @@ -91,15 +94,6 @@ bool Curl_pipeline_penalized(struct SessionHandle *data, return FALSE; } -static CURLcode addHandleToPipeline(struct SessionHandle *data, - struct curl_llist *pipeline) -{ - if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; -} - - CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle, struct connectdata *conn) { @@ -109,11 +103,11 @@ CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle, pipeline = conn->send_pipe; - result = addHandleToPipeline(handle, pipeline); + result = Curl_addHandleToPipeline(handle, pipeline); if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) { /* this is a new one as head, expire it */ - Curl_pipeline_leave_write(conn); /* not in use yet */ + conn->writechannel_inuse = FALSE; /* not in use yet */ Curl_expire(conn->send_pipe->head->ptr, 1); } @@ -144,7 +138,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle, if(conn->send_pipe->head) { /* Since there's a new easy handle at the start of the send pipeline, set its timeout value to 1ms to make it trigger instantly */ - Curl_pipeline_leave_write(conn); /* not used now */ + conn->writechannel_inuse = FALSE; /* not used now */ #ifdef DEBUGBUILD infof(conn->data, "%p is at send pipe head B!\n", (void *)conn->send_pipe->head->ptr); @@ -320,93 +314,6 @@ CURLMcode Curl_pipeline_set_server_blacklist(char **servers, return CURLM_OK; } -static bool pipe_head(struct SessionHandle *data, - struct curl_llist *pipeline) -{ - struct curl_llist_element *curr = pipeline->head; - if(curr) - return (curr->ptr == data) ? TRUE : FALSE; - - return FALSE; -} - -/* returns TRUE if the given handle is head of the recv pipe */ -bool Curl_recvpipe_head(struct SessionHandle *data, - struct connectdata *conn) -{ - return pipe_head(data, conn->recv_pipe); -} - -/* returns TRUE if the given handle is head of the send pipe */ -bool Curl_sendpipe_head(struct SessionHandle *data, - struct connectdata *conn) -{ - return pipe_head(data, conn->send_pipe); -} - - -/* - * Check if the write channel is available and this handle as at the head, - * then grab the channel and return TRUE. - * - * If not available, return FALSE. - */ - -bool Curl_pipeline_checkget_write(struct SessionHandle *data, - struct connectdata *conn) -{ - if(conn->bits.multiplex) - /* when multiplexing, we can use it at once */ - return TRUE; - - if(!conn->writechannel_inuse && Curl_sendpipe_head(data, conn)) { - /* Grab the channel */ - conn->writechannel_inuse = TRUE; - return TRUE; - } - return FALSE; -} - - -/* - * Check if the read channel is available and this handle as at the head, then - * grab the channel and return TRUE. - * - * If not available, return FALSE. - */ - -bool Curl_pipeline_checkget_read(struct SessionHandle *data, - struct connectdata *conn) -{ - if(conn->bits.multiplex) - /* when multiplexing, we can use it at once */ - return TRUE; - - if(!conn->readchannel_inuse && Curl_recvpipe_head(data, conn)) { - /* Grab the channel */ - conn->readchannel_inuse = TRUE; - return TRUE; - } - return FALSE; -} - -/* - * The current user of the pipeline write channel gives it up. - */ -void Curl_pipeline_leave_write(struct connectdata *conn) -{ - conn->writechannel_inuse = FALSE; -} - -/* - * The current user of the pipeline read channel gives it up. - */ -void Curl_pipeline_leave_read(struct connectdata *conn) -{ - conn->readchannel_inuse = FALSE; -} - - #if 0 void print_pipeline(struct connectdata *conn) { diff --git a/lib/pipeline.h b/lib/pipeline.h index bf229f199..96c4c33ec 100644 --- a/lib/pipeline.h +++ b/lib/pipeline.h @@ -7,7 +7,6 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, <linus@haxx.se> * * This software is licensed as described in the file COPYING, which @@ -42,15 +41,4 @@ bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle, CURLMcode Curl_pipeline_set_server_blacklist(char **servers, struct curl_llist **list_ptr); -bool Curl_pipeline_checkget_write(struct SessionHandle *data, - struct connectdata *conn); -bool Curl_pipeline_checkget_read(struct SessionHandle *data, - struct connectdata *conn); -void Curl_pipeline_leave_write(struct connectdata *conn); -void Curl_pipeline_leave_read(struct connectdata *conn); -bool Curl_recvpipe_head(struct SessionHandle *data, - struct connectdata *conn); -bool Curl_sendpipe_head(struct SessionHandle *data, - struct connectdata *conn); - #endif /* HEADER_CURL_PIPELINE_H */ diff --git a/lib/pop3.c b/lib/pop3.c index 53510a210..66004599a 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -83,7 +83,10 @@ #include "curl_sasl.h" #include "curl_md5.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -103,10 +106,10 @@ static CURLcode pop3_setup_connection(struct connectdata *conn); static CURLcode pop3_parse_url_options(struct connectdata *conn); static CURLcode pop3_parse_url_path(struct connectdata *conn); static CURLcode pop3_parse_custom_request(struct connectdata *conn); -static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, - const char *initresp); -static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); -static void pop3_get_message(char *buffer, char** outptr); +static CURLcode pop3_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + pop3state *state1, pop3state *state2); /* * POP3 protocol handler. @@ -211,17 +214,6 @@ static const struct Curl_handler Curl_handler_pop3s_proxy = { #endif #endif -/* SASL parameters for the pop3 protocol */ -static const struct SASLproto saslpop3 = { - "pop", /* The service name */ - '+', /* Code received when continuation is expected */ - '+', /* Code to receive upon authentication success */ - 255 - 8, /* Maximum initial response length (no max) */ - pop3_perform_auth, /* Send authentication command */ - pop3_continue_auth, /* Send authentication continuation */ - pop3_get_message /* Get SASL response message */ -}; - #ifdef USE_SSL static void pop3_to_pop3s(struct connectdata *conn) { @@ -320,7 +312,20 @@ static void state(struct connectdata *conn, pop3state newstate) "CAPA", "STARTTLS", "UPGRADETLS", - "AUTH", + "AUTH_PLAIN", + "AUTH_LOGIN", + "AUTH_LOGIN_PASSWD", + "AUTH_CRAMMD5", + "AUTH_DIGESTMD5", + "AUTH_DIGESTMD5_RESP", + "AUTH_NTLM", + "AUTH_NTLM_TYPE2MSG", + "AUTH_GSSAPI", + "AUTH_GSSAPI_TOKEN", + "AUTH_GSSAPI_NO_DATA", + "AUTH_XOAUTH2", + "AUTH_CANCEL", + "AUTH_FINAL", "APOP", "USER", "PASS", @@ -349,9 +354,9 @@ static CURLcode pop3_perform_capa(struct connectdata *conn) CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; - pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ - pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ - pop3c->tls_supported = FALSE; /* Clear the TLS capability */ + pop3c->authmechs = 0; /* No known authentication mechanisms yet */ + pop3c->authused = 0; /* Clear the authentication mechanism used */ + pop3c->tls_supported = FALSE; /* Clear the TLS capability */ /* Send the CAPA command */ result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); @@ -495,18 +500,25 @@ static CURLcode pop3_perform_apop(struct connectdata *conn) */ static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, - const char *initresp) + const char *initresp, size_t len, + pop3state state1, pop3state state2) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; - if(initresp) { /* AUTH <mech> ...<crlf> */ + if(initresp && 8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */ /* Send the AUTH command with the initial response */ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); + + if(!result) + state(conn, state2); } else { /* Send the AUTH command */ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); + + if(!result) + state(conn, state1); } return result; @@ -514,20 +526,6 @@ static CURLcode pop3_perform_auth(struct connectdata *conn, /*********************************************************************** * - * pop3_continue_auth() - * - * Sends SASL continuation data or cancellation. - */ -static CURLcode pop3_continue_auth(struct connectdata *conn, - const char *resp) -{ - struct pop3_conn *pop3c = &conn->proto.pop3c; - - return Curl_pp_sendf(&pop3c->pp, "%s", resp); -} - -/*********************************************************************** - * * pop3_perform_authentication() * * Initiates the authentication sequence, with the appropriate SASL @@ -538,32 +536,38 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; - saslprogress progress = SASL_IDLE; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + pop3state state1 = POP3_STOP; + pop3state state2 = POP3_STOP; - /* Check we have enough data to authenticate with and end the + /* Check we have a username and password to authenticate with and end the connect phase if we don't */ - if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { + if(!conn->bits.user_passwd) { state(conn, POP3_STOP); + return result; } - if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { - /* Calculate the SASL login details */ - result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress); - - if(!result) - if(progress == SASL_INPROGRESS) - state(conn, POP3_AUTH); - } + /* Calculate the SASL login details */ + if(pop3c->authtypes & POP3_TYPE_SASL) + result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); - if(!result && progress == SASL_IDLE) { + if(!result) { + if(mech && (pop3c->preftype & POP3_TYPE_SASL)) { + /* Perform SASL based authentication */ + result = pop3_perform_auth(conn, mech, initresp, len, state1, state2); + } #ifndef CURL_DISABLE_CRYPTO_AUTH - if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + else if((pop3c->authtypes & POP3_TYPE_APOP) && + (pop3c->preftype & POP3_TYPE_APOP)) /* Perform APOP authentication */ result = pop3_perform_apop(conn); - else #endif - if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) && + (pop3c->preftype & POP3_TYPE_CLEARTEXT)) /* Perform clear text authentication */ result = pop3_perform_user(conn); else { @@ -573,6 +577,8 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn) } } + Curl_safefree(initresp); + return result; } @@ -720,9 +726,6 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, /* Loop through the data line */ for(;;) { - size_t llen; - unsigned int mechbit; - while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { @@ -741,9 +744,22 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, wordlen++; /* Test the word for a matching authentication mechanism */ - if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && - llen == wordlen) - pop3c->sasl.authmechs |= mechbit; + if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN)) + pop3c->authmechs |= SASL_MECH_LOGIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN)) + pop3c->authmechs |= SASL_MECH_PLAIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5)) + pop3c->authmechs |= SASL_MECH_CRAM_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5)) + pop3c->authmechs |= SASL_MECH_DIGEST_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI)) + pop3c->authmechs |= SASL_MECH_GSSAPI; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL)) + pop3c->authmechs |= SASL_MECH_EXTERNAL; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM)) + pop3c->authmechs |= SASL_MECH_NTLM; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) + pop3c->authmechs |= SASL_MECH_XOAUTH2; line += wordlen; len -= wordlen; @@ -801,42 +817,575 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn, return result; } -/* For SASL authentication responses */ -static CURLcode pop3_state_auth_resp(struct connectdata *conn, - int pop3code, - pop3state instate) +/* For AUTH PLAIN (without initial response) responses */ +static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn, + int pop3code, + pop3state instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; - struct pop3_conn *pop3c = &conn->proto.pop3c; - saslprogress progress; + size_t len = 0; + char *plainauth = NULL; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress); - if(!result) - switch(progress) { - case SASL_DONE: - state(conn, POP3_STOP); /* Authenticated */ - break; - case SASL_IDLE: /* No mechanism left after cancellation */ + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, + &plainauth, &len); + if(!result && plainauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + } + + Curl_safefree(plainauth); + + return result; +} + +/* For AUTH LOGIN (without initial response) responses */ +static CURLcode pop3_state_auth_login_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authuser = NULL; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the user message */ + result = Curl_sasl_create_login_message(data, conn->user, + &authuser, &len); + if(!result && authuser) { + /* Send the user */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser); + + if(!result) + state(conn, POP3_AUTH_LOGIN_PASSWD); + } + } + + Curl_safefree(authuser); + + return result; +} + +/* For AUTH LOGIN user entry responses */ +static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authpasswd = NULL; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the password message */ + result = Curl_sasl_create_login_message(data, conn->passwd, + &authpasswd, &len); + if(!result && authpasswd) { + /* Send the password */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + } + + Curl_safefree(authpasswd); + + return result; +} + #ifndef CURL_DISABLE_CRYPTO_AUTH - if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) - /* Perform APOP authentication */ - result = pop3_perform_apop(conn); - else +/* For AUTH CRAM-MD5 responses */ +static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg = NULL; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + pop3_get_message(data->state.buffer, &chlg64); + + /* Decode the challenge message */ + result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*"); + + if(!result) + state(conn, POP3_AUTH_CANCEL); + } + else { + /* Create the response message */ + result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &rplyb64, &len); + if(!result && rplyb64) { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + } + + Curl_safefree(chlg); + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTH DIGEST-MD5 challenge responses */ +static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + pop3_get_message(data->state.buffer, &chlg64); + + /* Create the response message */ + result = Curl_sasl_create_digest_md5_message(data, chlg64, + conn->user, conn->passwd, + "pop", &rplyb64, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*"); + + if(!result) + state(conn, POP3_AUTH_CANCEL); + } + } + else { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64); + + if(!result) + state(conn, POP3_AUTH_DIGESTMD5_RESP); + } + + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTH DIGEST-MD5 challenge-response responses */ +static CURLcode pop3_state_auth_digest_resp_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Authentication failed: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Send an empty response */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", ""); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + + return result; +} #endif - if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) - /* Perform clear text authentication */ - result = pop3_perform_user(conn); - else { - failf(data, "Authentication cancelled"); - result = CURLE_LOGIN_DENIED; + +#ifdef USE_NTLM +/* For AUTH NTLM (without initial response) responses */ +static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *type1msg = NULL; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the type-1 message */ + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + &type1msg, &len); + if(!result && type1msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg); + + if(!result) + state(conn, POP3_AUTH_NTLM_TYPE2MSG); + } + } + + Curl_safefree(type1msg); + + return result; +} + +/* For NTLM type-2 responses (sent in reponse to our type-1 message) */ +static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *type2msg = NULL; + char *type3msg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the type-2 message */ + pop3_get_message(data->state.buffer, &type2msg); + + /* Decode the type-2 message */ + result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*"); + + if(!result) + state(conn, POP3_AUTH_CANCEL); + } + else { + /* Create the type-3 message */ + result = Curl_sasl_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &type3msg, &len); + if(!result && type3msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg); + + if(!result) + state(conn, POP3_AUTH_FINAL); } - break; - default: - break; } + } + + Curl_safefree(type3msg); + + return result; +} +#endif + +#if defined(USE_KERBEROS5) +/* For AUTH GSSAPI (without initial response) responses */ +static CURLcode pop3_state_auth_gssapi_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + size_t len = 0; + char *respmsg = NULL; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the initial response message */ + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "pop", + pop3c->mutual_auth, + NULL, &conn->krb5, + &respmsg, &len); + if(!result && respmsg) { + /* Send the message */ + result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg); + + if(!result) + state(conn, POP3_AUTH_GSSAPI_TOKEN); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTH GSSAPI user token responses */ +static CURLcode pop3_state_auth_gssapi_token_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + pop3_get_message(data->state.buffer, &chlgmsg); + + if(pop3c->mutual_auth) + /* Decode the user token challenge and create the optional response + message */ + result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL, + pop3c->mutual_auth, + chlgmsg, &conn->krb5, + &respmsg, &len); + else + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&pop3c->pp, "%s", "*"); + + if(!result) + state(conn, POP3_AUTH_CANCEL); + } + } + else { + /* Send the response */ + if(respmsg) + result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg); + else + result = Curl_pp_sendf(&pop3c->pp, "%s", ""); + + if(!result) + state(conn, (pop3c->mutual_auth ? POP3_AUTH_GSSAPI_NO_DATA : + POP3_AUTH_FINAL)); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTH GSSAPI no data responses */ +static CURLcode pop3_state_auth_gssapi_no_data_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + pop3_get_message(data->state.buffer, &chlgmsg); + + /* Decode the security challenge and create the security message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*"); + + if(!result) + state(conn, POP3_AUTH_CANCEL); + } + } + else { + /* Send the response */ + if(respmsg) { + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", respmsg); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + } + } + + Curl_safefree(respmsg); + + return result; +} +#endif + +/* For AUTH XOAUTH2 (without initial response) responses */ +static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn, + int pop3code, pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *xoauth = NULL; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, + conn->xoauth2_bearer, + &xoauth, &len); + if(!result && xoauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth); + + if(!result) + state(conn, POP3_AUTH_FINAL); + } + } + + Curl_safefree(xoauth); + + return result; +} + +/* For AUTH cancellation responses */ +static CURLcode pop3_state_auth_cancel_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + pop3state state1 = POP3_STOP; + pop3state state2 = POP3_STOP; + + (void)pop3code; + (void)instate; /* no use for this yet */ + + /* Remove the offending mechanism from the supported list */ + pop3c->authmechs ^= pop3c->authused; + + /* Calculate alternative SASL login details */ + result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); + + if(!result) { + /* Do we have any mechanisms left or can we fallback to another + authentication type? */ + if(mech) { + /* Retry SASL based authentication */ + result = pop3_perform_auth(conn, mech, initresp, len, state1, state2); + + Curl_safefree(initresp); + } +#ifndef CURL_DISABLE_CRYPTO_AUTH + else if((pop3c->authtypes & POP3_TYPE_APOP) && + (pop3c->preftype & POP3_TYPE_APOP)) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); +#endif + else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) && + (pop3c->preftype & POP3_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + failf(data, "Authentication cancelled"); + + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/* For final responses in the AUTH sequence */ +static CURLcode pop3_state_auth_final_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Authentication failed: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); return result; } @@ -1003,8 +1552,69 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); break; - case POP3_AUTH: - result = pop3_state_auth_resp(conn, pop3code, pop3c->state); + case POP3_AUTH_PLAIN: + result = pop3_state_auth_plain_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_LOGIN: + result = pop3_state_auth_login_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_LOGIN_PASSWD: + result = pop3_state_auth_login_password_resp(conn, pop3code, + pop3c->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case POP3_AUTH_CRAMMD5: + result = pop3_state_auth_cram_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_DIGESTMD5: + result = pop3_state_auth_digest_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_DIGESTMD5_RESP: + result = pop3_state_auth_digest_resp_resp(conn, pop3code, pop3c->state); + break; +#endif + +#ifdef USE_NTLM + case POP3_AUTH_NTLM: + result = pop3_state_auth_ntlm_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_NTLM_TYPE2MSG: + result = pop3_state_auth_ntlm_type2msg_resp(conn, pop3code, + pop3c->state); + break; +#endif + +#if defined(USE_KERBEROS5) + case POP3_AUTH_GSSAPI: + result = pop3_state_auth_gssapi_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_GSSAPI_TOKEN: + result = pop3_state_auth_gssapi_token_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_GSSAPI_NO_DATA: + result = pop3_state_auth_gssapi_no_data_resp(conn, pop3code, + pop3c->state); + break; +#endif + + case POP3_AUTH_XOAUTH2: + result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_CANCEL: + result = pop3_state_auth_cancel_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH_FINAL: + result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state); break; #ifndef CURL_DISABLE_CRYPTO_AUTH @@ -1117,7 +1727,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) /* Set the default preferred authentication type and mechanism */ pop3c->preftype = POP3_TYPE_ANY; - Curl_sasl_init(&pop3c->sasl, &saslpop3); + pop3c->prefmech = SASL_AUTH_ANY; /* Initialise the pingpong layer */ Curl_pp_init(pp); @@ -1269,7 +1879,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) Curl_pp_disconnect(&pop3c->pp); /* Cleanup the SASL module */ - Curl_sasl_cleanup(conn, pop3c->sasl.authused); + Curl_sasl_cleanup(conn, pop3c->authused); /* Cleanup our connection based variables */ Curl_safefree(pop3c->apoptimestamp); @@ -1384,52 +1994,75 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; - const char *ptr = conn->options; + const char *options = conn->options; + const char *ptr = options; + bool reset = TRUE; - pop3c->sasl.resetprefs = TRUE; - - while(!result && ptr && *ptr) { + while(ptr && *ptr) { const char *key = ptr; - const char *value; while(*ptr && *ptr != '=') ptr++; - value = ptr + 1; + if(strnequal(key, "AUTH", 4)) { + size_t len = 0; + const char *value = ++ptr; - while(*ptr && *ptr != ';') - ptr++; + if(reset) { + reset = FALSE; + pop3c->preftype = POP3_TYPE_NONE; + pop3c->prefmech = SASL_AUTH_NONE; + } - if(strnequal(key, "AUTH=", 5)) { - result = Curl_sasl_parse_url_auth_option(&pop3c->sasl, - value, ptr - value); + while(*ptr && *ptr != ';') { + ptr++; + len++; + } - if(result && strnequal(value, "+APOP", ptr - value)) { + if(strnequal(value, "*", len)) { + pop3c->preftype = POP3_TYPE_ANY; + pop3c->prefmech = SASL_AUTH_ANY; + } + else if(strnequal(value, "+APOP", len)) { pop3c->preftype = POP3_TYPE_APOP; - pop3c->sasl.prefmech = SASL_AUTH_NONE; - result = CURLE_OK; + pop3c->prefmech = SASL_AUTH_NONE; + } + else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_LOGIN; + } + else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_PLAIN; + } + else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_CRAM_MD5; + } + else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_DIGEST_MD5; + } + else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_GSSAPI; + } + else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_NTLM; } + else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) { + pop3c->preftype = POP3_TYPE_SASL; + pop3c->prefmech |= SASL_MECH_XOAUTH2; + } + + if(*ptr == ';') + ptr++; } else result = CURLE_URL_MALFORMAT; - - if(*ptr == ';') - ptr++; } - if(pop3c->preftype != POP3_TYPE_APOP) - switch(pop3c->sasl.prefmech) { - case SASL_AUTH_NONE: - pop3c->preftype = POP3_TYPE_NONE; - break; - case SASL_AUTH_DEFAULT: - pop3c->preftype = POP3_TYPE_ANY; - break; - default: - pop3c->preftype = POP3_TYPE_SASL; - break; - } - return result; } @@ -1472,6 +2105,110 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn) /*********************************************************************** * + * pop3_calc_sasl_details() + * + * Calculate the required login details for SASL authentication. + */ +static CURLcode pop3_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + pop3state *state1, pop3state *state2) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ +#if defined(USE_KERBEROS5) + if((pop3c->authmechs & SASL_MECH_GSSAPI) && + (pop3c->prefmech & SASL_MECH_GSSAPI)) { + pop3c->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */ + + *mech = SASL_MECH_STRING_GSSAPI; + *state1 = POP3_AUTH_GSSAPI; + *state2 = POP3_AUTH_GSSAPI_TOKEN; + pop3c->authused = SASL_MECH_GSSAPI; + + if(data->set.sasl_ir) + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "pop", + pop3c->mutual_auth, + NULL, &conn->krb5, + initresp, len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) && + (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) { + *mech = SASL_MECH_STRING_DIGEST_MD5; + *state1 = POP3_AUTH_DIGESTMD5; + pop3c->authused = SASL_MECH_DIGEST_MD5; + } + else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) && + (pop3c->prefmech & SASL_MECH_CRAM_MD5)) { + *mech = SASL_MECH_STRING_CRAM_MD5; + *state1 = POP3_AUTH_CRAMMD5; + pop3c->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if((pop3c->authmechs & SASL_MECH_NTLM) && + (pop3c->prefmech & SASL_MECH_NTLM)) { + *mech = SASL_MECH_STRING_NTLM; + *state1 = POP3_AUTH_NTLM; + *state2 = POP3_AUTH_NTLM_TYPE2MSG; + pop3c->authused = SASL_MECH_NTLM; + + if(data->set.sasl_ir) + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + initresp, len); + } + else +#endif + if(((pop3c->authmechs & SASL_MECH_XOAUTH2) && + (pop3c->prefmech & SASL_MECH_XOAUTH2) && + (pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) { + *mech = SASL_MECH_STRING_XOAUTH2; + *state1 = POP3_AUTH_XOAUTH2; + *state2 = POP3_AUTH_FINAL; + pop3c->authused = SASL_MECH_XOAUTH2; + + if(data->set.sasl_ir) + result = Curl_sasl_create_xoauth2_message(data, conn->user, + conn->xoauth2_bearer, + initresp, len); + } + else if((pop3c->authmechs & SASL_MECH_LOGIN) && + (pop3c->prefmech & SASL_MECH_LOGIN)) { + *mech = SASL_MECH_STRING_LOGIN; + *state1 = POP3_AUTH_LOGIN; + *state2 = POP3_AUTH_LOGIN_PASSWD; + pop3c->authused = SASL_MECH_LOGIN; + + if(data->set.sasl_ir) + result = Curl_sasl_create_login_message(data, conn->user, initresp, len); + } + else if((pop3c->authmechs & SASL_MECH_PLAIN) && + (pop3c->prefmech & SASL_MECH_PLAIN)) { + *mech = SASL_MECH_STRING_PLAIN; + *state1 = POP3_AUTH_PLAIN; + *state2 = POP3_AUTH_FINAL; + pop3c->authused = SASL_MECH_PLAIN; + + if(data->set.sasl_ir) + result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, + initresp, len); + } + + return result; +} + +/*********************************************************************** + * * Curl_pop3_write() * * This function scans the body after the end-of-body and writes everything diff --git a/lib/pop3.h b/lib/pop3.h index 7bc53aaf5..729a55ad5 100644 --- a/lib/pop3.h +++ b/lib/pop3.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2009 - 2014, 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 "pingpong.h" -#include "curl_sasl.h" /**************************************************************************** * POP3 unique setup @@ -36,7 +35,20 @@ typedef enum { POP3_STARTTLS, POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ - POP3_AUTH, + POP3_AUTH_PLAIN, + POP3_AUTH_LOGIN, + POP3_AUTH_LOGIN_PASSWD, + POP3_AUTH_CRAMMD5, + POP3_AUTH_DIGESTMD5, + POP3_AUTH_DIGESTMD5_RESP, + POP3_AUTH_NTLM, + POP3_AUTH_NTLM_TYPE2MSG, + POP3_AUTH_GSSAPI, + POP3_AUTH_GSSAPI_TOKEN, + POP3_AUTH_GSSAPI_NO_DATA, + POP3_AUTH_XOAUTH2, + POP3_AUTH_CANCEL, + POP3_AUTH_FINAL, POP3_APOP, POP3_USER, POP3_PASS, @@ -65,11 +77,14 @@ struct pop3_conn { have been received so far */ size_t strip; /* Number of bytes from the start to ignore as non-body */ - struct SASL sasl; /* SASL-related storage */ unsigned int authtypes; /* Accepted authentication types */ + unsigned int authmechs; /* Accepted SASL authentication mechanisms */ unsigned int preftype; /* Preferred authentication type */ + unsigned int prefmech; /* Preferred SASL authentication mechanism */ + unsigned int authused; /* SASL auth mechanism used for the connection */ char *apoptimestamp; /* APOP timestamp from the server greeting */ bool tls_supported; /* StartTLS capability supported by server */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ }; extern const struct Curl_handler Curl_handler_pop3; diff --git a/lib/progress.c b/lib/progress.c index b46e27405..f147ce71e 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -25,7 +25,9 @@ #include "urldata.h" #include "sendf.h" #include "progress.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero byte) */ diff --git a/lib/rtsp.c b/lib/rtsp.c index c30afd39d..029738d9b 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,12 +34,14 @@ #include "progress.h" #include "rtsp.h" #include "rawstr.h" +#include "curl_memory.h" #include "select.h" #include "connect.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -263,10 +265,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) * Since all RTSP requests are included here, there is no need to * support custom requests like HTTP. **/ + DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST)); data->set.opt_no_body = TRUE; /* most requests don't contain a body */ switch(rtspreq) { - default: - failf(data, "Got invalid RTSP request"); + case RTSPREQ_NONE: + failf(data, "Got invalid RTSP request: RTSPREQ_NONE"); return CURLE_BAD_FUNCTION_ARGUMENT; case RTSPREQ_OPTIONS: p_request = "OPTIONS"; @@ -322,7 +325,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) if(!p_session_id && (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", - p_request); + p_request ? p_request : ""); return CURLE_BAD_FUNCTION_ARGUMENT; } @@ -440,7 +443,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) Curl_add_bufferf(req_buffer, "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ "CSeq: %ld\r\n", /* CSeq */ - p_request, p_stream_uri, rtsp->CSeq_sent); + (p_request ? p_request : ""), p_stream_uri, + rtsp->CSeq_sent); if(result) return result; @@ -494,8 +498,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } else { - postsize = (data->state.infilesize != -1)? - data->state.infilesize: + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); data->set.httpreq = HTTPREQ_POST; } diff --git a/lib/security.c b/lib/security.c index 014bbf1b8..607048cc1 100644 --- a/lib/security.c +++ b/lib/security.c @@ -7,10 +7,10 @@ * rewrite to work around the paragraph 2 in the BSD licenses as explained * below. * - * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1998, 1999, 2013 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * - * Copyright (C) 2001 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2001 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * All rights reserved. * @@ -109,12 +109,19 @@ static char level_to_char(int level) { return 'P'; } +static const struct Curl_sec_client_mech * const mechs[] = { +#ifdef HAVE_GSSAPI + &Curl_krb5_client_mech, +#endif + NULL +}; + /* Send an FTP command defined by |message| and the optional arguments. The function returns the ftp_code. If an error occurs, -1 is returned. */ static int ftp_send_command(struct connectdata *conn, const char *message, ...) { int ftp_code; - ssize_t nread=0; + ssize_t nread; va_list args; char print_buffer[50]; @@ -359,7 +366,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, int */ int decoded_len; char *buf; - int ret_code = 0; + int ret_code; size_t decoded_sz = 0; CURLcode error; @@ -388,13 +395,13 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, } buf[decoded_len] = '\0'; - if(decoded_len <= 3) - /* suspiciously short */ - return 0; - - if(buf[3] != '-') - /* safe to ignore return code */ + DEBUGASSERT(decoded_len > 3); + if(buf[3] == '-') + ret_code = 0; + else { + /* Check for error? */ (void)sscanf(buf, "%d", &ret_code); + } if(buf[decoded_len - 1] == '\n') buf[decoded_len - 1] = '\0'; @@ -437,8 +444,8 @@ static int sec_set_protection_level(struct connectdata *conn) pbsz = strstr(conn->data->state.buffer, "PBSZ="); if(pbsz) { - /* ignore return code, use default value if it fails */ - (void)sscanf(pbsz, "PBSZ=%u", &buffer_size); + /* FIXME: Checks for errors in sscanf? */ + sscanf(pbsz, "PBSZ=%u", &buffer_size); if(buffer_size < conn->buffer_size) conn->buffer_size = buffer_size; } @@ -477,63 +484,72 @@ static CURLcode choose_mech(struct connectdata *conn) { int ret; struct SessionHandle *data = conn->data; + const struct Curl_sec_client_mech * const *mech; void *tmp_allocation; - const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; + const char *mech_name; + + for(mech = mechs; (*mech); ++mech) { + mech_name = (*mech)->name; + /* We have no mechanism with a NULL name but keep this check */ + DEBUGASSERT(mech_name != NULL); + if(mech_name == NULL) { + infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech); + continue; + } + tmp_allocation = realloc(conn->app_data, (*mech)->size); + if(tmp_allocation == NULL) { + failf(data, "Failed realloc of size %u", (*mech)->size); + mech = NULL; + return CURLE_OUT_OF_MEMORY; + } + conn->app_data = tmp_allocation; - tmp_allocation = realloc(conn->app_data, mech->size); - if(tmp_allocation == NULL) { - failf(data, "Failed realloc of size %u", mech->size); - mech = NULL; - return CURLE_OUT_OF_MEMORY; - } - conn->app_data = tmp_allocation; - - if(mech->init) { - ret = mech->init(conn->app_data); - if(ret) { - infof(data, "Failed initialization for %s. Skipping it.\n", - mech->name); - return CURLE_FAILED_INIT; + if((*mech)->init) { + ret = (*mech)->init(conn->app_data); + if(ret != 0) { + infof(data, "Failed initialization for %s. Skipping it.\n", mech_name); + continue; + } } - } - infof(data, "Trying mechanism %s...\n", mech->name); - ret = ftp_send_command(conn, "AUTH %s", mech->name); - if(ret < 0) - /* FIXME: This error is too generic but it is OK for now. */ - return CURLE_COULDNT_CONNECT; - - if(ret/100 != 3) { - switch(ret) { - case 504: - infof(data, "Mechanism %s is not supported by the server (server " - "returned ftp code: 504).\n", mech->name); - break; - case 534: - infof(data, "Mechanism %s was rejected by the server (server returned " - "ftp code: 534).\n", mech->name); - break; - default: - if(ret/100 == 5) { - infof(data, "server does not support the security extensions\n"); - return CURLE_USE_SSL_FAILED; + infof(data, "Trying mechanism %s...\n", mech_name); + ret = ftp_send_command(conn, "AUTH %s", mech_name); + if(ret < 0) + /* FIXME: This error is too generic but it is OK for now. */ + return CURLE_COULDNT_CONNECT; + + if(ret/100 != 3) { + switch(ret) { + case 504: + infof(data, "Mechanism %s is not supported by the server (server " + "returned ftp code: 504).\n", mech_name); + break; + case 534: + infof(data, "Mechanism %s was rejected by the server (server returned " + "ftp code: 534).\n", mech_name); + break; + default: + if(ret/100 == 5) { + infof(data, "server does not support the security extensions\n"); + return CURLE_USE_SSL_FAILED; + } + break; } - break; + continue; } - return CURLE_LOGIN_DENIED; - } - /* Authenticate */ - ret = mech->auth(conn->app_data, conn); + /* Authenticate */ + ret = (*mech)->auth(conn->app_data, conn); - if(ret != AUTH_CONTINUE) { - if(ret != AUTH_OK) { + if(ret == AUTH_CONTINUE) + continue; + else if(ret != AUTH_OK) { /* Mechanism has dumped the error to stderr, don't error here. */ return -1; } DEBUGASSERT(ret == AUTH_OK); - conn->mech = mech; + conn->mech = *mech; conn->sec_complete = 1; conn->recv[FIRSTSOCKET] = sec_recv; conn->send[FIRSTSOCKET] = sec_send; @@ -543,9 +559,10 @@ static CURLcode choose_mech(struct connectdata *conn) /* Set the requested protection level */ /* BLOCKING */ (void)sec_set_protection_level(conn); + break; } - return CURLE_OK; + return *mech != NULL ? CURLE_OK : CURLE_FAILED_INIT; } CURLcode @@ -560,8 +577,10 @@ Curl_sec_end(struct connectdata *conn) { if(conn->mech != NULL && conn->mech->end) conn->mech->end(conn->app_data); - free(conn->app_data); - conn->app_data = NULL; + if(conn->app_data) { + free(conn->app_data); + conn->app_data = NULL; + } if(conn->in_buffer.data) { free(conn->in_buffer.data); conn->in_buffer.data = NULL; diff --git a/lib/select.c b/lib/select.c index 24dc5fd79..1c6481cb7 100644 --- a/lib/select.c +++ b/lib/select.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -159,7 +159,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ fd_set fds_err; curl_socket_t maxfd; #endif - struct timeval initial_tv = {0, 0}; + struct timeval initial_tv = {0,0}; int pending_ms = 0; int error; int r; @@ -393,7 +393,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) fd_set fds_err; curl_socket_t maxfd; #endif - struct timeval initial_tv = {0, 0}; + struct timeval initial_tv = {0,0}; bool fds_none = TRUE; unsigned int i; int pending_ms = 0; @@ -573,6 +573,6 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); tpf_process_signals(); - return rc; + return(rc); } #endif /* TPF */ diff --git a/lib/sendf.c b/lib/sendf.c index 5f39d1f2d..2d1a166bd 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,11 +31,14 @@ #include "ssh.h" #include "multiif.h" #include "non-ascii.h" -#include "curl_printf.h" -#include "strerror.h" -/* The last #include files should be: */ +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include <curl/mprintf.h> + #include "curl_memory.h" +#include "strerror.h" + +/* The last #include file should be: */ #include "memdebug.h" #ifdef CURL_DO_LINEEND_CONV @@ -52,7 +55,7 @@ static size_t convert_lineends(struct SessionHandle *data, /* sanity check */ if((startPtr == NULL) || (size < 1)) { - return size; + return(size); } if(data->state.prev_block_had_trailing_cr) { @@ -114,9 +117,9 @@ static size_t convert_lineends(struct SessionHandle *data, /* tidy up by null terminating the now shorter data */ *outPtr = '\0'; - return (outPtr - startPtr); + return(outPtr - startPtr); } - return size; + return(size); } #endif /* CURL_DO_LINEEND_CONV */ @@ -551,7 +554,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ ssize_t nread = 0; size_t bytesfromsocket = 0; char *buffertofill = NULL; - bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1); + bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi); /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets diff --git a/lib/setup-vms.h b/lib/setup-vms.h index 520a35daa..4b3dded9d 100644 --- a/lib/setup-vms.h +++ b/lib/setup-vms.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -249,9 +249,6 @@ char * unix_path; #define MD5_Init MD5_INIT #define MD5_Update MD5_UPDATE #define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF -#ifndef __VAX -#define OPENSSL_load_builtin_modules OPENSSL_LOAD_BUILTIN_MODULES -#endif #define PEM_read_X509 PEM_READ_X509 #define PEM_write_bio_X509 PEM_WRITE_BIO_X509 #define PKCS12_PBE_add PKCS12_PBE_ADD @@ -275,7 +272,6 @@ char * unix_path; #define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST #define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD #define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB -#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK #define SSL_CTX_set_verify SSL_CTX_SET_VERIFY #define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY #define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE @@ -305,7 +301,6 @@ char * unix_path; #define SSL_set_fd SSL_SET_FD #define SSL_set_session SSL_SET_SESSION #define SSL_shutdown SSL_SHUTDOWN -#define SSL_version SSL_VERSION #define SSL_write SSL_WRITE #define SSLeay SSLEAY #define SSLv23_client_method SSLV23_CLIENT_METHOD @@ -330,7 +325,6 @@ char * unix_path; #define UI_set_result UI_SET_RESULT #define X509V3_EXT_print X509V3_EXT_PRINT #define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL -#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA #define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT #define X509_LOOKUP_file X509_LOOKUP_FILE #define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA @@ -355,12 +349,6 @@ char * unix_path; #define sk_pop SK_POP #define sk_pop_free SK_POP_FREE #define sk_value SK_VALUE -#ifdef __VAX -#define OPENSSL_NO_SHA256 -#endif -#define SHA256_Final SHA256_FINAL -#define SHA256_Init SHA256_INIT -#define SHA256_Update SHA256_UPDATE #define USE_UPPERCASE_GSSAPI 1 #define gss_seal GSS_SEAL @@ -426,7 +414,7 @@ char * unix_path; static void des_ecb_encrypt(const_des_cblock *input, des_cblock *output, - des_key_schedule ks, int enc) { + des_key_schedule ks,int enc) { DES_ECB_ENCRYPT(input, output, ks, enc); } #endif diff --git a/lib/share.c b/lib/share.c index 17202486c..b8b6bee80 100644 --- a/lib/share.c +++ b/lib/share.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,15 +35,9 @@ CURLSH * curl_share_init(void) { struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); - if(share) { + if(share) share->specifier |= (1<<CURL_LOCK_DATA_SHARE); - if(Curl_mk_dnscache(&share->hostcache)) { - free(share); - return NULL; - } - } - return share; } @@ -73,6 +67,11 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) share->specifier |= (1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: + if(!share->hostcache) { + share->hostcache = Curl_mk_dnscache(); + if(!share->hostcache) + res = CURLSHE_NOMEM; + } break; case CURL_LOCK_DATA_COOKIE: @@ -116,6 +115,10 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) share->specifier &= ~(1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: + if(share->hostcache) { + Curl_hash_destroy(share->hostcache); + share->hostcache = NULL; + } break; case CURL_LOCK_DATA_COOKIE: @@ -189,10 +192,14 @@ curl_share_cleanup(CURLSH *sh) return CURLSHE_IN_USE; } - Curl_hash_destroy(&share->hostcache); + if(share->hostcache) { + Curl_hash_destroy(share->hostcache); + share->hostcache = NULL; + } #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) - Curl_cookie_cleanup(share->cookies); + if(share->cookies) + Curl_cookie_cleanup(share->cookies); #endif #ifdef USE_SSL diff --git a/lib/share.h b/lib/share.h index 8e6629b7b..9a5128e93 100644 --- a/lib/share.h +++ b/lib/share.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, 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 @@ -44,7 +44,7 @@ struct Curl_share { curl_unlock_function unlockfunc; void *clientdata; - struct curl_hash hostcache; + struct curl_hash *hostcache; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) struct CookieInfo *cookies; #endif diff --git a/lib/slist.c b/lib/slist.c index 9c0b2a58a..3cac6ca21 100644 --- a/lib/slist.c +++ b/lib/slist.c @@ -22,10 +22,10 @@ #include "curl_setup.h" +#include "curl_memory.h" #include "slist.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" /* returns last node in linked list */ @@ -44,11 +44,11 @@ #include "transfer.h" #include "vtls/vtls.h" #include "curl_ntlm_core.h" +#include "curl_memory.h" #include "escape.h" #include "curl_endian.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" /* Local API functions */ @@ -783,15 +783,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) off = Curl_read16_le(((unsigned char *) msg) + sizeof(struct smb_header) + 13); if(len > 0) { - struct smb_conn *smbc = &conn->proto.smbc; - if(off + sizeof(unsigned int) + len > smbc->got) { - failf(conn->data, "Invalid input packet"); - result = CURLE_RECV_ERROR; - } - else - result = Curl_client_write(conn, CLIENTWRITE_BODY, - (char *)msg + off + sizeof(unsigned int), - len); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)msg + off + sizeof(unsigned int), + len); if(result) { req->result = result; next_state = SMB_CLOSE; @@ -941,7 +935,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn) /* Parse the path for the share */ req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); if(!req->share) { - free(path); + Curl_safefree(path); return CURLE_OUT_OF_MEMORY; } @@ -952,7 +946,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn) /* The share must be present */ if(!slash) { - free(path); + Curl_safefree(path); return CURLE_URL_MALFORMAT; } @@ -966,7 +960,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn) *slash = '\\'; } - free(path); + Curl_safefree(path); return CURLE_OK; } diff --git a/lib/smtp.c b/lib/smtp.c index dada087a9..7bd5158bf 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -82,7 +82,10 @@ #include "curl_gethostname.h" #include "curl_sasl.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -102,10 +105,10 @@ static CURLcode smtp_setup_connection(struct connectdata *conn); static CURLcode smtp_parse_url_options(struct connectdata *conn); static CURLcode smtp_parse_url_path(struct connectdata *conn); static CURLcode smtp_parse_custom_request(struct connectdata *conn); -static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, - const char *initresp); -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); -static void smtp_get_message(char *buffer, char** outptr); +static CURLcode smtp_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + smtpstate *state1, smtpstate *state2); /* * SMTP protocol handler. @@ -210,17 +213,6 @@ static const struct Curl_handler Curl_handler_smtps_proxy = { #endif #endif -/* SASL parameters for the smtp protocol */ -static const struct SASLproto saslsmtp = { - "smtp", /* The service name */ - 334, /* Code received when continuation is expected */ - 235, /* Code to receive upon authentication success */ - 512 - 8, /* Maximum initial response length (no max) */ - smtp_perform_auth, /* Send authentication command */ - smtp_continue_auth, /* Send authentication continuation */ - smtp_get_message /* Get SASL response message */ -}; - #ifdef USE_SSL static void smtp_to_smtps(struct connectdata *conn) { @@ -317,7 +309,20 @@ static void state(struct connectdata *conn, smtpstate newstate) "HELO", "STARTTLS", "UPGRADETLS", - "AUTH", + "AUTH_PLAIN", + "AUTH_LOGIN", + "AUTH_LOGIN_PASSWD", + "AUTH_CRAMMD5", + "AUTH_DIGESTMD5", + "AUTH_DIGESTMD5_RESP", + "AUTH_NTLM", + "AUTH_NTLM_TYPE2MSG", + "AUTH_GSSAPI", + "AUTH_GSSAPI_TOKEN", + "AUTH_GSSAPI_NO_DATA", + "AUTH_XOAUTH2", + "AUTH_CANCEL", + "AUTH_FINAL", "COMMAND", "MAIL", "RCPT", @@ -347,11 +352,11 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn) CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; - smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ - smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism - used for esmtp connections */ - smtpc->tls_supported = FALSE; /* Clear the TLS capability */ - smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ + smtpc->authmechs = 0; /* No known authentication mechanisms yet */ + smtpc->authused = 0; /* Clear the authentication mechanism used + for esmtp connections */ + smtpc->tls_supported = FALSE; /* Clear the TLS capability */ + smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ /* Send the EHLO command */ result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); @@ -373,8 +378,8 @@ static CURLcode smtp_perform_helo(struct connectdata *conn) CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; - smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used - in smtp connections */ + smtpc->authused = 0; /* No authentication mechanism used in smtp + connections */ /* Send the HELO command */ result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); @@ -440,18 +445,25 @@ static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) */ static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, - const char *initresp) + const char *initresp, size_t len, + smtpstate state1, smtpstate state2) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; - if(initresp) { /* AUTH <mech> ...<crlf> */ + if(initresp && 8 + strlen(mech) + len <= 512) { /* AUTH <mech> ...<crlf> */ /* Send the AUTH command with the initial response */ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + + if(!result) + state(conn, state2); } else { /* Send the AUTH command */ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + + if(!result) + state(conn, state1); } return result; @@ -459,19 +471,6 @@ static CURLcode smtp_perform_auth(struct connectdata *conn, /*********************************************************************** * - * smtp_continue_auth() - * - * Sends SASL continuation data or cancellation. - */ -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) -{ - struct smtp_conn *smtpc = &conn->proto.smtpc; - - return Curl_pp_sendf(&smtpc->pp, "%s", resp); -} - -/*********************************************************************** - * * smtp_perform_authentication() * * Initiates the authentication sequence, with the appropriate SASL @@ -481,22 +480,31 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; - saslprogress progress; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + smtpstate state1 = SMTP_STOP; + smtpstate state2 = SMTP_STOP; - /* Check we have enough data to authenticate with, and the + /* Check we have a username and password to authenticate with, and the server supports authentiation, and end the connect phase if not */ - if(!smtpc->auth_supported || - !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { + if(!conn->bits.user_passwd || !smtpc->auth_supported) { state(conn, SMTP_STOP); + return result; } /* Calculate the SASL login details */ - result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress); + result = smtp_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); if(!result) { - if(progress == SASL_INPROGRESS) - state(conn, SMTP_AUTH); + if(mech) { + /* Perform SASL based authentication */ + result = smtp_perform_auth(conn, mech, initresp, len, state1, state2); + + Curl_safefree(initresp); + } else { /* Other mechanisms not supported */ infof(conn->data, "No known authentication mechanisms supported!\n"); @@ -563,7 +571,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; /* Calculate the optional AUTH parameter */ - if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) { + if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) { if(data->set.str[STRING_MAIL_AUTH][0] != '\0') auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); else @@ -571,7 +579,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) auth = strdup("<>"); if(!auth) { - free(from); + Curl_safefree(from); return CURLE_OUT_OF_MEMORY; } @@ -582,8 +590,8 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize); if(!size) { - free(from); - free(auth); + Curl_safefree(from); + Curl_safefree(auth); return CURLE_OUT_OF_MEMORY; } @@ -603,9 +611,9 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s SIZE=%s", from, size); - free(from); - free(auth); - free(size); + Curl_safefree(from); + Curl_safefree(auth); + Curl_safefree(size); if(!result) state(conn, SMTP_MAIL); @@ -745,9 +753,6 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, /* Loop through the data line */ for(;;) { - size_t llen; - unsigned int mechbit; - while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { @@ -766,9 +771,22 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, wordlen++; /* Test the word for a matching authentication mechanism */ - if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && - llen == wordlen) - smtpc->sasl.authmechs |= mechbit; + if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN)) + smtpc->authmechs |= SASL_MECH_LOGIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN)) + smtpc->authmechs |= SASL_MECH_PLAIN; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5)) + smtpc->authmechs |= SASL_MECH_CRAM_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5)) + smtpc->authmechs |= SASL_MECH_DIGEST_MD5; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI)) + smtpc->authmechs |= SASL_MECH_GSSAPI; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL)) + smtpc->authmechs |= SASL_MECH_EXTERNAL; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM)) + smtpc->authmechs |= SASL_MECH_NTLM; + else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) + smtpc->authmechs |= SASL_MECH_XOAUTH2; line += wordlen; len -= wordlen; @@ -817,31 +835,565 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, return result; } -/* For SASL authentication responses */ -static CURLcode smtp_state_auth_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) +/* For AUTH PLAIN (without initial response) responses */ +static CURLcode smtp_state_auth_plain_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *plainauth = NULL; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_plain_message(conn->data, conn->user, + conn->passwd, &plainauth, &len); + if(!result && plainauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + + Curl_safefree(plainauth); + + return result; +} + +/* For AUTH LOGIN (without initial response) responses */ +static CURLcode smtp_state_auth_login_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authuser = NULL; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the user message */ + result = Curl_sasl_create_login_message(conn->data, conn->user, + &authuser, &len); + if(!result && authuser) { + /* Send the user */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser); + + if(!result) + state(conn, SMTP_AUTH_LOGIN_PASSWD); + } + } + + Curl_safefree(authuser); + + return result; +} + +/* For AUTH LOGIN user entry responses */ +static CURLcode smtp_state_auth_login_password_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *authpasswd = NULL; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the password message */ + result = Curl_sasl_create_login_message(conn->data, conn->passwd, + &authpasswd, &len); + if(!result && authpasswd) { + /* Send the password */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + + Curl_safefree(authpasswd); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/* For AUTH CRAM-MD5 responses */ +static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg = NULL; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + smtp_get_message(data->state.buffer, &chlg64); + + /* Decode the challenge message */ + result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*"); + + if(!result) + state(conn, SMTP_AUTH_CANCEL); + } + else { + /* Create the response message */ + result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &rplyb64, &len); + if(!result && rplyb64) { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + + Curl_safefree(chlg); + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTH DIGEST-MD5 challenge responses */ +static CURLcode smtp_state_auth_digest_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlg64 = NULL; + char *rplyb64 = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + return CURLE_LOGIN_DENIED; + } + + /* Get the challenge message */ + smtp_get_message(data->state.buffer, &chlg64); + + /* Create the response message */ + result = Curl_sasl_create_digest_md5_message(data, chlg64, + conn->user, conn->passwd, + "smtp", &rplyb64, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*"); + + if(!result) + state(conn, SMTP_AUTH_CANCEL); + } + } + else { + /* Send the response */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); + + if(!result) + state(conn, SMTP_AUTH_DIGESTMD5_RESP); + } + + Curl_safefree(rplyb64); + + return result; +} + +/* For AUTH DIGEST-MD5 challenge-response responses */ +static CURLcode smtp_state_auth_digest_resp_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Authentication failed: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Send an empty response */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", ""); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + + return result; +} + +#endif + +#ifdef USE_NTLM +/* For AUTH NTLM (without initial response) responses */ +static CURLcode smtp_state_auth_ntlm_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *type1msg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the type-1 message */ + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + &type1msg, &len); + if(!result && type1msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type1msg); + + if(!result) + state(conn, SMTP_AUTH_NTLM_TYPE2MSG); + } + } + + Curl_safefree(type1msg); + + return result; +} + +/* For NTLM type-2 responses (sent in reponse to our type-1 message) */ +static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *type2msg = NULL; + char *type3msg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the type-2 message */ + smtp_get_message(data->state.buffer, &type2msg); + + /* Decode the type-2 message */ + result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm); + if(result) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*"); + + if(!result) + state(conn, SMTP_AUTH_CANCEL); + } + else { + /* Create the type-3 message */ + result = Curl_sasl_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &type3msg, &len); + if(!result && type3msg) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type3msg); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + } + + Curl_safefree(type3msg); + + return result; +} +#endif + +#if defined(USE_KERBEROS5) +/* For AUTH GSSAPI (without initial response) responses */ +static CURLcode smtp_state_auth_gssapi_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct smtp_conn *smtpc = &conn->proto.smtpc; - saslprogress progress; + char *respmsg = NULL; + size_t len = 0; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress); - if(!result) - switch(progress) { - case SASL_DONE: - state(conn, SMTP_STOP); /* Authenticated */ - break; - case SASL_IDLE: /* No mechanism left after cancellation */ + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the initial response message */ + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "smtp", + smtpc->mutual_auth, NULL, + &conn->krb5, + &respmsg, &len); + if(!result && respmsg) { + /* Send the message */ + result = Curl_pp_sendf(&smtpc->pp, "%s", respmsg); + + if(!result) + state(conn, SMTP_AUTH_GSSAPI_TOKEN); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTH GSSAPI user token responses */ +static CURLcode smtp_state_auth_gssapi_token_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + smtp_get_message(data->state.buffer, &chlgmsg); + + if(smtpc->mutual_auth) + /* Decode the user token challenge and create the optional response + message */ + result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL, + smtpc->mutual_auth, + chlgmsg, &conn->krb5, + &respmsg, &len); + else + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&smtpc->pp, "%s", "*"); + + if(!result) + state(conn, SMTP_AUTH_CANCEL); + } + } + else { + /* Send the response */ + if(respmsg) + result = Curl_pp_sendf(&smtpc->pp, "%s", respmsg); + else + result = Curl_pp_sendf(&smtpc->pp, "%s", ""); + + if(!result) + state(conn, (smtpc->mutual_auth ? SMTP_AUTH_GSSAPI_NO_DATA : + SMTP_AUTH_FINAL)); + } + } + + Curl_safefree(respmsg); + + return result; +} + +/* For AUTH GSSAPI no data responses */ +static CURLcode smtp_state_auth_gssapi_no_data_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *chlgmsg = NULL; + char *respmsg = NULL; + size_t len = 0; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Get the challenge message */ + smtp_get_message(data->state.buffer, &chlgmsg); + + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, chlgmsg, + &conn->krb5, + &respmsg, &len); + if(result) { + if(result == CURLE_BAD_CONTENT_ENCODING) { + /* Send the cancellation */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*"); + + if(!result) + state(conn, SMTP_AUTH_CANCEL); + } + } + else { + /* Send the response */ + if(respmsg) { + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", respmsg); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + } + + Curl_safefree(respmsg); + + return result; +} +#endif + +/* For AUTH XOAUTH2 (without initial response) responses */ +static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn, + int smtpcode, smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + size_t len = 0; + char *xoauth = NULL; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 334) { + failf(data, "Access denied: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else { + /* Create the authorisation message */ + result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, + conn->xoauth2_bearer, + &xoauth, &len); + if(!result && xoauth) { + /* Send the message */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth); + + if(!result) + state(conn, SMTP_AUTH_FINAL); + } + } + + Curl_safefree(xoauth); + + return result; +} + +/* For AUTH cancellation responses */ +static CURLcode smtp_state_auth_cancel_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *mech = NULL; + char *initresp = NULL; + size_t len = 0; + smtpstate state1 = SMTP_STOP; + smtpstate state2 = SMTP_STOP; + + (void)smtpcode; + (void)instate; /* no use for this yet */ + + /* Remove the offending mechanism from the supported list */ + smtpc->authmechs ^= smtpc->authused; + + /* Calculate alternative SASL login details */ + result = smtp_calc_sasl_details(conn, &mech, &initresp, &len, &state1, + &state2); + + if(!result) { + /* Do we have any mechanisms left? */ + if(mech) { + /* Retry SASL based authentication */ + result = smtp_perform_auth(conn, mech, initresp, len, state1, state2); + + Curl_safefree(initresp); + } + else { failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; - break; - default: - break; } + } + + return result; +} + +/* For final responses in the AUTH sequence */ +static CURLcode smtp_state_auth_final_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 235) { + failf(data, "Authentication failed: %d", smtpcode); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, SMTP_STOP); return result; } @@ -1039,8 +1591,69 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); break; - case SMTP_AUTH: - result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + case SMTP_AUTH_PLAIN: + result = smtp_state_auth_plain_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_LOGIN: + result = smtp_state_auth_login_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_LOGIN_PASSWD: + result = smtp_state_auth_login_password_resp(conn, smtpcode, + smtpc->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case SMTP_AUTH_CRAMMD5: + result = smtp_state_auth_cram_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_DIGESTMD5: + result = smtp_state_auth_digest_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_DIGESTMD5_RESP: + result = smtp_state_auth_digest_resp_resp(conn, smtpcode, smtpc->state); + break; +#endif + +#ifdef USE_NTLM + case SMTP_AUTH_NTLM: + result = smtp_state_auth_ntlm_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_NTLM_TYPE2MSG: + result = smtp_state_auth_ntlm_type2msg_resp(conn, smtpcode, + smtpc->state); + break; +#endif + +#if defined(USE_KERBEROS5) + case SMTP_AUTH_GSSAPI: + result = smtp_state_auth_gssapi_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_GSSAPI_TOKEN: + result = smtp_state_auth_gssapi_token_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_GSSAPI_NO_DATA: + result = smtp_state_auth_gssapi_no_data_resp(conn, smtpcode, + smtpc->state); + break; +#endif + + case SMTP_AUTH_XOAUTH2: + result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_CANCEL: + result = smtp_state_auth_cancel_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH_FINAL: + result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state); break; case SMTP_COMMAND: @@ -1153,8 +1766,8 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) pp->endofresp = smtp_endofresp; pp->conn = conn; - /* Initialize the SASL storage */ - Curl_sasl_init(&smtpc->sasl, &saslsmtp); + /* Set the default preferred authentication mechanism */ + smtpc->prefmech = SASL_AUTH_ANY; /* Initialise the pingpong layer */ Curl_pp_init(pp); @@ -1372,7 +1985,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) Curl_pp_disconnect(&smtpc->pp); /* Cleanup the SASL module */ - Curl_sasl_cleanup(conn, smtpc->sasl.authused); + Curl_sasl_cleanup(conn, smtpc->authused); /* Cleanup our connection based variables */ Curl_safefree(smtpc->domain); @@ -1493,30 +2106,52 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; - const char *ptr = conn->options; - - smtpc->sasl.resetprefs = TRUE; + const char *options = conn->options; + const char *ptr = options; + bool reset = TRUE; - while(!result && ptr && *ptr) { + while(ptr && *ptr) { const char *key = ptr; - const char *value; while(*ptr && *ptr != '=') ptr++; - value = ptr + 1; + if(strnequal(key, "AUTH", 4)) { + size_t len = 0; + const char *value = ++ptr; - while(*ptr && *ptr != ';') - ptr++; + if(reset) { + reset = FALSE; + smtpc->prefmech = SASL_AUTH_NONE; + } + + while(*ptr && *ptr != ';') { + ptr++; + len++; + } - if(strnequal(key, "AUTH=", 5)) - result = Curl_sasl_parse_url_auth_option(&smtpc->sasl, - value, ptr - value); + if(strnequal(value, "*", len)) + smtpc->prefmech = SASL_AUTH_ANY; + else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) + smtpc->prefmech |= SASL_MECH_LOGIN; + else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) + smtpc->prefmech |= SASL_MECH_PLAIN; + else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) + smtpc->prefmech |= SASL_MECH_CRAM_MD5; + else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) + smtpc->prefmech |= SASL_MECH_DIGEST_MD5; + else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) + smtpc->prefmech |= SASL_MECH_GSSAPI; + else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) + smtpc->prefmech |= SASL_MECH_NTLM; + else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) + smtpc->prefmech |= SASL_MECH_XOAUTH2; + + if(*ptr == ';') + ptr++; + } else result = CURLE_URL_MALFORMAT; - - if(*ptr == ';') - ptr++; } return result; @@ -1568,6 +2203,110 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn) return result; } +/*********************************************************************** + * + * smtp_calc_sasl_details() + * + * Calculate the required login details for SASL authentication. + */ +static CURLcode smtp_calc_sasl_details(struct connectdata *conn, + const char **mech, + char **initresp, size_t *len, + smtpstate *state1, smtpstate *state2) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ +#if defined(USE_KERBEROS5) + if((smtpc->authmechs & SASL_MECH_GSSAPI) && + (smtpc->prefmech & SASL_MECH_GSSAPI)) { + smtpc->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */ + + *mech = SASL_MECH_STRING_GSSAPI; + *state1 = SMTP_AUTH_GSSAPI; + *state2 = SMTP_AUTH_GSSAPI_TOKEN; + smtpc->authused = SASL_MECH_GSSAPI; + + if(data->set.sasl_ir) + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, "smtp", + smtpc->mutual_auth, + NULL, &conn->krb5, + initresp, len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) && + (smtpc->prefmech & SASL_MECH_DIGEST_MD5)) { + *mech = SASL_MECH_STRING_DIGEST_MD5; + *state1 = SMTP_AUTH_DIGESTMD5; + smtpc->authused = SASL_MECH_DIGEST_MD5; + } + else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) && + (smtpc->prefmech & SASL_MECH_CRAM_MD5)) { + *mech = SASL_MECH_STRING_CRAM_MD5; + *state1 = SMTP_AUTH_CRAMMD5; + smtpc->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if((smtpc->authmechs & SASL_MECH_NTLM) && + (smtpc->prefmech & SASL_MECH_NTLM)) { + *mech = SASL_MECH_STRING_NTLM; + *state1 = SMTP_AUTH_NTLM; + *state2 = SMTP_AUTH_NTLM_TYPE2MSG; + smtpc->authused = SASL_MECH_NTLM; + + if(data->set.sasl_ir) + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, + initresp, len); + } + else +#endif + if(((smtpc->authmechs & SASL_MECH_XOAUTH2) && + (smtpc->prefmech & SASL_MECH_XOAUTH2) && + (smtpc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) { + *mech = SASL_MECH_STRING_XOAUTH2; + *state1 = SMTP_AUTH_XOAUTH2; + *state2 = SMTP_AUTH_FINAL; + smtpc->authused = SASL_MECH_XOAUTH2; + + if(data->set.sasl_ir) + result = Curl_sasl_create_xoauth2_message(data, conn->user, + conn->xoauth2_bearer, + initresp, len); + } + else if((smtpc->authmechs & SASL_MECH_LOGIN) && + (smtpc->prefmech & SASL_MECH_LOGIN)) { + *mech = SASL_MECH_STRING_LOGIN; + *state1 = SMTP_AUTH_LOGIN; + *state2 = SMTP_AUTH_LOGIN_PASSWD; + smtpc->authused = SASL_MECH_LOGIN; + + if(data->set.sasl_ir) + result = Curl_sasl_create_login_message(data, conn->user, initresp, len); + } + else if((smtpc->authmechs & SASL_MECH_PLAIN) && + (smtpc->prefmech & SASL_MECH_PLAIN)) { + *mech = SASL_MECH_STRING_PLAIN; + *state1 = SMTP_AUTH_PLAIN; + *state2 = SMTP_AUTH_FINAL; + smtpc->authused = SASL_MECH_PLAIN; + + if(data->set.sasl_ir) + result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, + initresp, len); + } + + return result; +} + CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) { /* When sending a SMTP payload we must detect CRLF. sequences making sure @@ -1657,13 +2396,13 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) data->state.scratch = scratch; /* Free the old scratch buffer */ - free(oldscratch); + Curl_safefree(oldscratch); /* Set the new amount too */ data->req.upload_present = si; } else - free(newscratch); + Curl_safefree(newscratch); return CURLE_OK; } diff --git a/lib/smtp.h b/lib/smtp.h index 9fbe0c5bf..7a95efeaf 100644 --- a/lib/smtp.h +++ b/lib/smtp.h @@ -23,7 +23,6 @@ ***************************************************************************/ #include "pingpong.h" -#include "curl_sasl.h" /**************************************************************************** * SMTP unique setup @@ -37,7 +36,20 @@ typedef enum { SMTP_STARTTLS, SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ - SMTP_AUTH, + SMTP_AUTH_PLAIN, + SMTP_AUTH_LOGIN, + SMTP_AUTH_LOGIN_PASSWD, + SMTP_AUTH_CRAMMD5, + SMTP_AUTH_DIGESTMD5, + SMTP_AUTH_DIGESTMD5_RESP, + SMTP_AUTH_NTLM, + SMTP_AUTH_NTLM_TYPE2MSG, + SMTP_AUTH_GSSAPI, + SMTP_AUTH_GSSAPI_TOKEN, + SMTP_AUTH_GSSAPI_NO_DATA, + SMTP_AUTH_XOAUTH2, + SMTP_AUTH_CANCEL, + SMTP_AUTH_FINAL, SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */ SMTP_MAIL, /* MAIL FROM */ SMTP_RCPT, /* RCPT TO */ @@ -67,11 +79,14 @@ struct smtp_conn { smtpstate state; /* Always use smtp.c:state() to change state! */ bool ssldone; /* Is connect() over SSL done? */ char *domain; /* Client address/name to send in the EHLO */ - struct SASL sasl; /* SASL-related storage */ + unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ bool tls_supported; /* StartTLS capability supported by server */ bool size_supported; /* If server supports SIZE extension according to RFC 1870 */ bool auth_supported; /* AUTH capability supported by server */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ }; extern const struct Curl_handler Curl_handler_smtp; diff --git a/lib/socks.c b/lib/socks.c index 7d3f782b4..6c6585b05 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -382,7 +382,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ if(!socks5_resolve_local && hostname_len > 255) { - infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + infof(conn->data,"SOCKS5: server resolving disabled for hostnames of " "length > 255 [actual len=%zu]\n", hostname_len); socks5_resolve_local = TRUE; } diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 8e575c279..f195c1a0e 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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,16 @@ #include "curl_setup.h" -#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY) +#ifndef CURL_DISABLE_PROXY + +#ifdef HAVE_GSSAPI +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif +#ifndef gss_nt_service_name +#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE +#endif #include "curl_gssapi.h" #include "urldata.h" @@ -32,7 +41,10 @@ #include "timeval.h" #include "socks.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -48,7 +60,7 @@ static int check_gss_err(struct SessionHandle *data, const char* function) { if(GSS_ERROR(major_status)) { - OM_uint32 maj_stat, min_stat; + OM_uint32 maj_stat,min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char buf[1024]; @@ -92,10 +104,10 @@ static int check_gss_err(struct SessionHandle *data, gss_release_buffer(&min_stat, &status_string); } failf(data, "GSS-API error: %s failed:\n%s", function, buf); - return 1; + return(1); } - return 0; + return(0); } CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, @@ -131,7 +143,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, */ /* prepare service name */ - if(strchr(serviceptr, '/')) { + if(strchr(serviceptr,'/')) { service.value = malloc(strlen(serviceptr)); if(!service.value) return CURLE_OUT_OF_MEMORY; @@ -150,13 +162,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, serviceptr, conn->proxy.name); gss_major_status = gss_import_name(&gss_minor_status, &service, - GSS_C_NT_HOSTBASED_SERVICE, &server); + gss_nt_service_name, &server); } gss_release_buffer(&gss_status, &service); /* clear allocated memory */ - if(check_gss_err(data, gss_major_status, - gss_minor_status, "gss_import_name()")) { + if(check_gss_err(data,gss_major_status, + gss_minor_status,"gss_import_name()")) { failf(data, "Failed to create service name."); gss_release_name(&gss_status, &server); return CURLE_COULDNT_CONNECT; @@ -178,8 +190,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(gss_token != GSS_C_NO_BUFFER) gss_release_buffer(&gss_status, &gss_recv_token); - if(check_gss_err(data, gss_major_status, - gss_minor_status, "gss_init_sec_context")) { + if(check_gss_err(data,gss_major_status, + gss_minor_status,"gss_init_sec_context")) { gss_release_name(&gss_status, &server); gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_send_token); @@ -192,7 +204,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)gss_send_token.length); - memcpy(socksreq+2, &us_length, sizeof(short)); + memcpy(socksreq+2,&us_length,sizeof(short)); code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { @@ -291,8 +303,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, &gss_client_name, NULL, NULL, NULL, NULL, NULL, NULL); - if(check_gss_err(data, gss_major_status, - gss_minor_status, "gss_inquire_context")) { + if(check_gss_err(data,gss_major_status, + gss_minor_status,"gss_inquire_context")) { gss_delete_sec_context(&gss_status, &gss_context, NULL); gss_release_name(&gss_status, &gss_client_name); failf(data, "Failed to determine user name."); @@ -300,8 +312,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, &gss_send_token, NULL); - if(check_gss_err(data, gss_major_status, - gss_minor_status, "gss_display_name")) { + if(check_gss_err(data,gss_major_status, + gss_minor_status,"gss_display_name")) { gss_delete_sec_context(&gss_status, &gss_context, NULL); gss_release_name(&gss_status, &gss_client_name); gss_release_buffer(&gss_status, &gss_send_token); @@ -372,7 +384,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, */ if(data->set.socks5_gssapi_nec) { us_length = htons((short)1); - memcpy(socksreq+2, &us_length, sizeof(short)); + memcpy(socksreq+2,&us_length,sizeof(short)); } else { gss_send_token.length = 1; @@ -387,7 +399,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, GSS_C_QOP_DEFAULT, &gss_send_token, &gss_conf_state, &gss_w_token); - if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { + if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_wrap")) { gss_release_buffer(&gss_status, &gss_send_token); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -397,7 +409,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_buffer(&gss_status, &gss_send_token); us_length = htons((short)gss_w_token.length); - memcpy(socksreq+2, &us_length, sizeof(short)); + memcpy(socksreq+2,&us_length,sizeof(short)); } code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); @@ -475,7 +487,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, &gss_recv_token, &gss_w_token, 0, GSS_C_QOP_DEFAULT); - if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { + if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_unwrap")) { gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -492,7 +504,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - memcpy(socksreq, gss_w_token.value, gss_w_token.length); + memcpy(socksreq,gss_w_token.value,gss_w_token.length); gss_release_buffer(&gss_status, &gss_w_token); } else { @@ -504,7 +516,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); + memcpy(socksreq,gss_recv_token.value,gss_recv_token.length); gss_release_buffer(&gss_status, &gss_recv_token); } @@ -518,5 +530,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OK; } +#endif -#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */ +#endif /* CURL_DISABLE_PROXY */ diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index a7708b2d4..015862703 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> + * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,7 +34,10 @@ #include "curl_sspi.h" #include "curl_multibyte.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -104,8 +107,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2); if(!service_name) return CURLE_OUT_OF_MEMORY; - snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2, - "%s/%s", service, conn->proxy.name); + snprintf(service_name,strlen(service) +strlen(conn->proxy.name)+2,"%s/%s", + service,conn->proxy.name); } input_desc.cBuffers = 1; @@ -143,7 +146,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { failf(data, "Failed to acquire credentials."); - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); return CURLE_COULDNT_CONNECT; } @@ -182,7 +185,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } if(check_sspi_err(conn, status, "InitializeSecurityContext")) { - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); if(sspi_recv_token.pvBuffer) @@ -200,7 +203,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { failf(data, "Failed to send SSPI authentication request."); - free(service_name); + Curl_safefree(service_name); if(sspi_send_token.pvBuffer) s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); if(sspi_recv_token.pvBuffer) @@ -214,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, sspi_send_token.cbBuffer, &written); if(code || (sspi_send_token.cbBuffer != (size_t)written)) { failf(data, "Failed to send SSPI authentication token."); - free(service_name); + Curl_safefree(service_name); if(sspi_send_token.pvBuffer) s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); if(sspi_recv_token.pvBuffer) @@ -254,7 +257,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); if(result || (actualread != 4)) { failf(data, "Failed to receive SSPI authentication response."); - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_COULDNT_CONNECT; @@ -264,7 +267,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(socksreq[1] == 255) { /* status / message type */ failf(data, "User was rejected by the SOCKS5 server (%u %u).", (unsigned int)socksreq[0], (unsigned int)socksreq[1]); - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_COULDNT_CONNECT; @@ -273,7 +276,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(socksreq[1] != 1) { /* status / messgae type */ failf(data, "Invalid SSPI authentication response type (%u %u).", (unsigned int)socksreq[0], (unsigned int)socksreq[1]); - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_COULDNT_CONNECT; @@ -286,7 +289,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, sspi_recv_token.pvBuffer = malloc(us_length); if(!sspi_recv_token.pvBuffer) { - free(service_name); + Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_OUT_OF_MEMORY; @@ -296,7 +299,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(result || (actualread != us_length)) { failf(data, "Failed to receive SSPI authentication token."); - free(service_name); + Curl_safefree(service_name); if(sspi_recv_token.pvBuffer) s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); s_pSecFn->FreeCredentialsHandle(&cred_handle); @@ -307,7 +310,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, context_handle = &sspi_context; } - free(service_name); + Curl_safefree(service_name); /* Everything is good so far, user was authenticated! */ status = s_pSecFn->QueryCredentialsAttributes(&cred_handle, @@ -402,7 +405,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } - memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); + memcpy(sspi_w_token[1].pvBuffer,&gss_enc,1); sspi_w_token[2].BufferType = SECBUFFER_PADDING; sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); @@ -456,7 +459,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, sspi_w_token[2].cbBuffer = 0; us_length = htons((short)sspi_send_token.cbBuffer); - memcpy(socksreq+2, &us_length, sizeof(short)); + memcpy(socksreq+2,&us_length,sizeof(short)); } code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); @@ -469,7 +472,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } if(data->set.socks5_gssapi_nec) { - memcpy(socksreq, &gss_enc, 1); + memcpy(socksreq,&gss_enc,1); code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); if(code || (1 != written)) { failf(data, "Failed to send SSPI encryption type."); @@ -567,7 +570,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + memcpy(socksreq,sspi_w_token[1].pvBuffer,sspi_w_token[1].cbBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); } @@ -579,7 +582,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_COULDNT_CONNECT; } - memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); + memcpy(socksreq,sspi_w_token[0].pvBuffer,sspi_w_token[0].cbBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); } diff --git a/lib/splay.c b/lib/splay.c index b87b6cfe2..5bb7065e4 100644 --- a/lib/splay.c +++ b/lib/splay.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1997 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1997 - 2014, 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 @@ -101,13 +101,13 @@ struct Curl_tree *Curl_splayinsert(struct timeval i, struct Curl_tree *t, struct Curl_tree *node) { - static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */ + static const struct timeval KEY_NOTUSED = {-1,-1}; /* will *NEVER* appear */ if(node == NULL) return t; if(t != NULL) { - t = Curl_splay(i, t); + t = Curl_splay(i,t); if(compare(i, t->key)==0) { /* There already exists a node in the tree with the very same key. Build a linked list of nodes. We make the new 'node' struct the new master @@ -162,7 +162,7 @@ struct Curl_tree *Curl_splaygetbest(struct timeval i, return NULL; } - t = Curl_splay(i, t); + t = Curl_splay(i,t); if(compare(i, t->key) < 0) { /* too big node, try the smaller chain */ if(t->smaller) @@ -223,7 +223,7 @@ int Curl_splayremovebyaddr(struct Curl_tree *t, struct Curl_tree *removenode, struct Curl_tree **newroot) { - static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */ + static const struct timeval KEY_NOTUSED = {-1,-1}; /* will *NEVER* appear */ struct Curl_tree *x; if(!t || !removenode) @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -83,7 +83,10 @@ #include "multiif.h" #include "select.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -855,7 +858,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } if(out_of_memory || sshc->rsa == NULL) { - free(home); + Curl_safefree(home); Curl_safefree(sshc->rsa); Curl_safefree(sshc->rsa_pub); state(conn, SSH_SESSION_FREE); @@ -867,7 +870,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(!sshc->passphrase) sshc->passphrase = ""; - free(home); + Curl_safefree(home); infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); infof(data, "Using SSH private key file '%s'\n", sshc->rsa); @@ -935,7 +938,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } else { state(conn, SSH_AUTH_HOST_INIT); - rc = 0; /* clear rc and continue */ } break; @@ -1020,11 +1022,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->sshagent_identity); if(rc < 0) { - if(rc != LIBSSH2_ERROR_EAGAIN) + if(rc != LIBSSH2_ERROR_EAGAIN) { /* tried and failed? go to next identity */ sshc->sshagent_prev_identity = sshc->sshagent_identity; - else - break; + } + break; } } @@ -1038,10 +1040,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "Agent based authentication successful\n"); state(conn, SSH_AUTH_DONE); } - else { + else state(conn, SSH_AUTH_KEY_INIT); - rc = 0; /* clear rc and continue */ - } #endif break; @@ -1740,8 +1740,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) BUFSIZE : curlx_sotouz(data->state.resume_from - passed); size_t actuallyread = - data->set.fread_func(data->state.buffer, 1, readthisamountnow, - data->set.in); + conn->fread_func(data->state.buffer, 1, readthisamountnow, + conn->fread_in); passed += actuallyread; if((actuallyread == 0) || (actuallyread > readthisamountnow)) { @@ -1921,7 +1921,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } result = Curl_client_write(conn, CLIENTWRITE_BODY, tmpLine, sshc->readdir_len+1); - free(tmpLine); + Curl_safefree(tmpLine); if(result) { state(conn, SSH_STOP); @@ -2144,7 +2144,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* from is relative to end of file */ from += size; } - if(from > size) { + if(from >= size) { failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize); @@ -2245,7 +2245,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) DEBUGF(infof(data, "SFTP DONE done\n")); /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT - After nextstate is executed, the control should come back to + After nextstate is executed,the control should come back to SSH_SFTP_CLOSE to pass the correct result back */ if(sshc->nextstate != SSH_NO_STATE && sshc->nextstate != SSH_SFTP_CLOSE) { @@ -3270,8 +3270,8 @@ get_pathname(const char **cpp, char **path) return CURLE_OK; fail: - Curl_safefree(*path); - return CURLE_QUOTE_ERROR; + Curl_safefree(*path); + return CURLE_QUOTE_ERROR; } @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -44,9 +44,9 @@ typedef enum { SSH_AUTH_PKEY, SSH_AUTH_PASS_INIT, SSH_AUTH_PASS, - SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */ - SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */ - SSH_AUTH_AGENT, /* attempt one key at a time */ + SSH_AUTH_AGENT_INIT,/* initialize then wait for connection to agent */ + SSH_AUTH_AGENT_LIST,/* ask for list then wait for entire list to come */ + SSH_AUTH_AGENT, /* attempt one key at a time */ SSH_AUTH_HOST_INIT, SSH_AUTH_HOST, SSH_AUTH_KEY_INIT, diff --git a/lib/strdup.c b/lib/strdup.c index 5685b8138..a997b12f2 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -44,7 +44,7 @@ char *curlx_strdup(const char *str) if(!newstr) return (char *)NULL; - memcpy(newstr, str, (len+1)*sizeof(char)); + memcpy(newstr,str,(len+1)*sizeof(char)); return newstr; diff --git a/lib/strerror.c b/lib/strerror.c index 565714188..b85b56839 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2004 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2004 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,7 +40,10 @@ #endif #include "strerror.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -298,9 +301,6 @@ curl_easy_strerror(CURLcode error) case CURLE_SSL_PINNEDPUBKEYNOTMATCH: return "SSL public key does not match pinned public key"; - case CURLE_SSL_INVALIDCERTSTATUS: - return "SSL server certificate status verification FAILED"; - /* error codes not used by current libcurl */ case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: @@ -641,7 +641,7 @@ const char *Curl_strerror(struct connectdata *conn, int err) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); - wcstombs(buf, wbuf, max); + wcstombs(buf,wbuf,max); } #else /* 'sys_nerr' is the maximum errno number, it is not widely portable */ @@ -708,9 +708,9 @@ const char *Curl_strerror(struct connectdata *conn, int err) buf[max] = '\0'; /* make sure the string is zero terminated */ /* strip trailing '\r\n' or '\n'. */ - if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2) + if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2) *p = '\0'; - if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1) + if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1) *p = '\0'; if(old_errno != ERRNO) @@ -824,9 +824,6 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) case SEC_E_OK: txt = "No error"; break; - case CRYPT_E_REVOKED: - txt = "CRYPT_E_REVOKED"; - break; case SEC_E_ALGORITHM_MISMATCH: txt = "SEC_E_ALGORITHM_MISMATCH"; break; @@ -1070,12 +1067,6 @@ 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%04X%04X) - 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 >> 16) & 0xffff, err & 0xffff); else { str = txtbuf; snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)", @@ -1091,7 +1082,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { - wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1); + wcstombs(msgbuf,wbuf,sizeof(msgbuf)-1); msg_formatted = TRUE; } } @@ -1106,9 +1097,9 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) if(msg_formatted) { msgbuf[sizeof(msgbuf)-1] = '\0'; /* strip trailing '\r\n' or '\n' */ - if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2) + if((p = strrchr(msgbuf,'\n')) != NULL && (p - msgbuf) >= 2) *p = '\0'; - if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1) + if((p = strrchr(msgbuf,'\r')) != NULL && (p - msgbuf) >= 1) *p = '\0'; msg = msgbuf; } diff --git a/lib/telnet.c b/lib/telnet.c index aabf99d48..176e9940b 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -51,19 +51,21 @@ #include "telnet.h" #include "connect.h" #include "progress.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #define TELOPTS #define TELCMDS #include "arpa_telnet.h" +#include "curl_memory.h" #include "select.h" #include "strequal.h" #include "rawstr.h" #include "warnless.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #define SUBBUFSIZE 512 @@ -226,9 +228,9 @@ check_wsock2 ( struct SessionHandle *data ) if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { /* Our version isn't supported */ - failf(data, "insufficient winsock version to support " - "telnet"); - return CURLE_FAILED_INIT; + failf(data,"insufficient winsock version to support " + "telnet"); + return CURLE_FAILED_INIT; } /* Our version is supported */ @@ -1174,7 +1176,7 @@ CURLcode telrcv(struct connectdata *conn, if(c == CURL_IAC) tn->telrcv_state = CURL_TS_SE; else - CURL_SB_ACCUM(tn, c); + CURL_SB_ACCUM(tn,c); break; case CURL_TS_SE: @@ -1199,7 +1201,7 @@ CURLcode telrcv(struct connectdata *conn, tn->telrcv_state = CURL_TS_IAC; goto process_iac; } - CURL_SB_ACCUM(tn, c); + CURL_SB_ACCUM(tn,c); tn->telrcv_state = CURL_TS_SB; } else @@ -1280,7 +1282,7 @@ static CURLcode telnet_done(struct connectdata *conn, static CURLcode telnet_do(struct connectdata *conn, bool *done) { - CURLcode result; + CURLcode code; struct SessionHandle *data = conn->data; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; #ifdef USE_WINSOCK @@ -1313,61 +1315,65 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) *done = TRUE; /* unconditionally */ - result = init_telnet(conn); - if(result) - return result; + code = init_telnet(conn); + if(code) + return code; tn = (struct TELNET *)data->req.protop; - result = check_telnet_options(conn); - if(result) - return result; + code = check_telnet_options(conn); + if(code) + return code; #ifdef USE_WINSOCK /* ** This functionality only works with WinSock >= 2.0. So, ** make sure have it. */ - result = check_wsock2(data); - if(result) - return result; + code = check_wsock2(data); + if(code) + return code; /* OK, so we have WinSock 2.0. We need to dynamically */ /* load ws2_32.dll and get the function pointers we need. */ wsock2 = LoadLibrary(TEXT("WS2_32.DLL")); if(wsock2 == NULL) { - failf(data, "failed to load WS2_32.DLL (%d)", ERRNO); + failf(data,"failed to load WS2_32.DLL (%d)", ERRNO); return CURLE_FAILED_INIT; } /* Grab a pointer to WSACreateEvent */ - create_event_func = GetProcAddress(wsock2, "WSACreateEvent"); + create_event_func = GetProcAddress(wsock2,"WSACreateEvent"); if(create_event_func == NULL) { - failf(data, "failed to find WSACreateEvent function (%d)", ERRNO); + failf(data,"failed to find WSACreateEvent function (%d)", + ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSACloseEvent */ - close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); + close_event_func = GetProcAddress(wsock2,"WSACloseEvent"); if(close_event_func == NULL) { - failf(data, "failed to find WSACloseEvent function (%d)", ERRNO); + failf(data,"failed to find WSACloseEvent function (%d)", + ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSAEventSelect */ - event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); + event_select_func = GetProcAddress(wsock2,"WSAEventSelect"); if(event_select_func == NULL) { - failf(data, "failed to find WSAEventSelect function (%d)", ERRNO); + failf(data,"failed to find WSAEventSelect function (%d)", + ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSAEnumNetworkEvents */ - enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); + enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents"); if(enum_netevents_func == NULL) { - failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO); + failf(data,"failed to find WSAEnumNetworkEvents function (%d)", + ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } @@ -1380,7 +1386,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* First, create a sockets event object */ event_handle = (WSAEVENT)create_event_func(); if(event_handle == WSA_INVALID_EVENT) { - failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); + failf(data,"WSACreateEvent failed (%d)", SOCKERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } @@ -1421,30 +1427,29 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) case WAIT_TIMEOUT: { for(;;) { - if(data->set.is_fread_set) { + if(obj_count == 1) { /* read from user-supplied method */ - result = (int)data->set.fread_func(buf, 1, BUFSIZE - 1, - data->set.in); - if(result == CURL_READFUNC_ABORT) { + code = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); + if(code == CURL_READFUNC_ABORT) { keepon = FALSE; - result = CURLE_READ_ERROR; + code = CURLE_READ_ERROR; break; } - if(result == CURL_READFUNC_PAUSE) + if(code == CURL_READFUNC_PAUSE) break; - if(result == 0) /* no bytes */ + if(code == 0) /* no bytes */ break; - readfile_read = result; /* fall thru with number of bytes read */ + readfile_read = code; /* fall thru with number of bytes read */ } else { /* read from stdin */ if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) { keepon = FALSE; - result = CURLE_READ_ERROR; + code = CURLE_READ_ERROR; break; } @@ -1454,13 +1459,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; - result = CURLE_READ_ERROR; + code = CURLE_READ_ERROR; break; } } - result = send_telnet_data(conn, buf, readfile_read); - if(result) { + code = send_telnet_data(conn, buf, readfile_read); + if(code) { keepon = FALSE; break; } @@ -1473,12 +1478,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; - result = CURLE_READ_ERROR; + code = CURLE_READ_ERROR; break; } - result = send_telnet_data(conn, buf, readfile_read); - if(result) { + code = send_telnet_data(conn, buf, readfile_read); + if(code) { keepon = FALSE; break; } @@ -1490,20 +1495,20 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) events.lNetworkEvents = 0; if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { if((err = SOCKERRNO) != EINPROGRESS) { - infof(data, "WSAEnumNetworkEvents failed (%d)", err); + infof(data,"WSAEnumNetworkEvents failed (%d)", err); keepon = FALSE; - result = CURLE_READ_ERROR; + code = CURLE_READ_ERROR; } break; } if(events.lNetworkEvents & FD_READ) { /* read data from network */ - result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); + code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); /* read would've blocked. Loop again */ - if(result == CURLE_AGAIN) + if(code == CURLE_AGAIN) break; /* returned not-zero, this an error */ - else if(result) { + else if(code) { keepon = FALSE; break; } @@ -1514,8 +1519,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) break; } - result = telrcv(conn, (unsigned char *) buf, nread); - if(result) { + code = telrcv(conn, (unsigned char *)buf, nread); + if(code) { keepon = FALSE; break; } @@ -1539,7 +1544,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { failf(data, "Time-out"); - result = CURLE_OPERATION_TIMEDOUT; + code = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; } } @@ -1547,7 +1552,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* We called WSACreateEvent, so call WSACloseEvent */ if(!close_event_func(event_handle)) { - infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); + infof(data,"WSACloseEvent failed (%d)", SOCKERRNO); } /* "Forget" pointers into the library we're about to free */ @@ -1558,18 +1563,18 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* We called LoadLibrary, so call FreeLibrary */ if(!FreeLibrary(wsock2)) - infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO); + infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO); #else pfd[0].fd = sockfd; pfd[0].events = POLLIN; - if(data->set.fread_func != (curl_read_callback)fread) { + if(conn->fread_func != (curl_read_callback)fread) { poll_cnt = 1; interval_ms = 100; /* poll user-supplied read function */ } else { /* really using fread, so infile is a FILE* */ - pfd[1].fd = fileno((FILE *)data->set.in); + pfd[1].fd = fileno((FILE *)conn->fread_in); pfd[1].events = POLLIN; poll_cnt = 2; interval_ms = 1 * 1000; @@ -1587,12 +1592,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) default: /* read! */ if(pfd[0].revents & POLLIN) { /* read data from network */ - result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); + code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); /* read would've blocked. Loop again */ - if(result == CURLE_AGAIN) + if(code == CURLE_AGAIN) break; /* returned not-zero, this an error */ - else if(result) { + else if(code) { keepon = FALSE; break; } @@ -1605,8 +1610,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) total_dl += nread; Curl_pgrsSetDownloadCounter(data, total_dl); - result = telrcv(conn, (unsigned char *)buf, nread); - if(result) { + code = telrcv(conn, (unsigned char *)buf, nread); + if(code) { keepon = FALSE; break; } @@ -1628,7 +1633,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } else { /* read from user-supplied method */ - nread = (int)data->set.fread_func(buf, 1, BUFSIZE - 1, data->set.in); + nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); if(nread == CURL_READFUNC_ABORT) { keepon = FALSE; break; @@ -1638,8 +1643,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } if(nread > 0) { - result = send_telnet_data(conn, buf, nread); - if(result) { + code = send_telnet_data(conn, buf, nread); + if(code) { keepon = FALSE; break; } @@ -1656,13 +1661,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { failf(data, "Time-out"); - result = CURLE_OPERATION_TIMEDOUT; + code = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; } } if(Curl_pgrsUpdate(conn)) { - result = CURLE_ABORTED_BY_CALLBACK; + code = CURLE_ABORTED_BY_CALLBACK; break; } } @@ -1670,6 +1675,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* mark this as "no further transfer wanted" */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - return result; + return code; } #endif diff --git a/lib/tftp.c b/lib/tftp.c index 4c5796f55..b9723c000 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -57,11 +57,14 @@ #include "url.h" #include "rawstr.h" #include "speedcheck.h" -#include "curl_printf.h" -#include "select.h" -/* The last #include files should be: */ +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" +#include "select.h" + +/* The last #include file should be: */ #include "memdebug.h" /* RFC2348 allows the block size to be negotiated */ @@ -145,8 +148,8 @@ typedef struct tftp_state_data { /* Forward declarations */ -static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event); -static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ; +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ; static CURLcode tftp_connect(struct connectdata *conn, bool *done); static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection); @@ -218,7 +221,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state) state->max_time = state->start_time+maxtime; /* Set per-block timeout to total */ - timeout = maxtime; + timeout = maxtime ; /* Average restart after 5 seconds */ state->retry_max = (int)timeout/5; @@ -408,7 +411,7 @@ static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, if(( strlen(option) + csize + 1 ) > (size_t)state->blksize) return 0; strcpy(buf, option); - return strlen(option) + 1; + return( strlen(option) + 1 ); } static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, @@ -423,7 +426,7 @@ static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, state->state = TFTP_STATE_TX; result = tftp_set_timeouts(state); if(result) - return result; + return(result); return tftp_tx(state, event); } @@ -439,7 +442,7 @@ static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, state->state = TFTP_STATE_RX; result = tftp_set_timeouts(state); if(result) - return result; + return(result); return tftp_rx(state, event); } @@ -451,7 +454,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) char *filename; char buf[64]; struct SessionHandle *data = state->conn->data; - CURLcode result = CURLE_OK; + CURLcode res = CURLE_OK; /* Set ascii mode if -B flag was used */ if(data->set.prefer_ascii) @@ -466,7 +469,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) if(state->retries>state->retry_max) { state->error = TFTP_ERR_NORESPONSE; state->state = TFTP_STATE_FIN; - return result; + return res; } if(data->set.upload) { @@ -531,24 +534,24 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) if(senddata != (ssize_t)sbytes) { failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); } - free(filename); + Curl_safefree(filename); break; case TFTP_EVENT_OACK: if(data->set.upload) { - result = tftp_connect_for_tx(state, event); + res = tftp_connect_for_tx(state, event); } else { - result = tftp_connect_for_rx(state, event); + res = tftp_connect_for_rx(state, event); } break; case TFTP_EVENT_ACK: /* Connected for transmit */ - result = tftp_connect_for_tx(state, event); + res = tftp_connect_for_tx(state, event); break; case TFTP_EVENT_DATA: /* Connected for receive */ - result = tftp_connect_for_rx(state, event); + res = tftp_connect_for_rx(state, event); break; case TFTP_EVENT_ERROR: @@ -559,8 +562,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) failf(state->conn->data, "tftp_send_first: internal error"); break; } - - return result; + return res; } /* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit @@ -700,7 +702,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) struct SessionHandle *data = state->conn->data; ssize_t sbytes; int rblock; - CURLcode result = CURLE_OK; + CURLcode res = CURLE_OK; struct SingleRequest *k = &data->req; switch(event) { @@ -726,7 +728,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) if(state->retries>state->retry_max) { failf(data, "tftp_tx: giving up waiting for block %d ack", state->block); - result = CURLE_SEND_ERROR; + res = CURLE_SEND_ERROR; } else { /* Re-send the data packet */ @@ -737,11 +739,10 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) /* Check all sbytes were sent */ if(sbytes<0) { failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - result = CURLE_SEND_ERROR; + res = CURLE_SEND_ERROR; } } - - return result; + return res; } /* This is the expected packet. Reset the counters and send the next block */ @@ -758,13 +759,11 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->state = TFTP_STATE_FIN; return CURLE_OK; } - - result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes); - if(result) - return result; - - sbytes = sendto(state->sockfd, (void *) state->spacket.data, - 4 + state->sbytes, SEND_4TH_ARG, + res = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes); + if(res) + return res; + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4+state->sbytes, SEND_4TH_ARG, (struct sockaddr *)&state->remote_addr, state->remote_addrlen); /* Check all sbytes were sent */ @@ -820,7 +819,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) break; } - return result; + return res; } /********************************************************** @@ -832,47 +831,48 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) **********************************************************/ static CURLcode tftp_translate_code(tftp_error_t error) { - CURLcode result = CURLE_OK; + CURLcode code = CURLE_OK; if(error != TFTP_ERR_NONE) { switch(error) { case TFTP_ERR_NOTFOUND: - result = CURLE_TFTP_NOTFOUND; + code = CURLE_TFTP_NOTFOUND; break; case TFTP_ERR_PERM: - result = CURLE_TFTP_PERM; + code = CURLE_TFTP_PERM; break; case TFTP_ERR_DISKFULL: - result = CURLE_REMOTE_DISK_FULL; + code = CURLE_REMOTE_DISK_FULL; break; case TFTP_ERR_UNDEF: case TFTP_ERR_ILLEGAL: - result = CURLE_TFTP_ILLEGAL; + code = CURLE_TFTP_ILLEGAL; break; case TFTP_ERR_UNKNOWNID: - result = CURLE_TFTP_UNKNOWNID; + code = CURLE_TFTP_UNKNOWNID; break; case TFTP_ERR_EXISTS: - result = CURLE_REMOTE_FILE_EXISTS; + code = CURLE_REMOTE_FILE_EXISTS; break; case TFTP_ERR_NOSUCHUSER: - result = CURLE_TFTP_NOSUCHUSER; + code = CURLE_TFTP_NOSUCHUSER; break; case TFTP_ERR_TIMEOUT: - result = CURLE_OPERATION_TIMEDOUT; + code = CURLE_OPERATION_TIMEDOUT; break; case TFTP_ERR_NORESPONSE: - result = CURLE_COULDNT_CONNECT; + code = CURLE_COULDNT_CONNECT; break; default: - result = CURLE_ABORTED_BY_CALLBACK; + code= CURLE_ABORTED_BY_CALLBACK; break; } } - else - result = CURLE_OK; + else { + code = CURLE_OK; + } - return result; + return(code); } /********************************************************** @@ -885,21 +885,20 @@ static CURLcode tftp_translate_code(tftp_error_t error) static CURLcode tftp_state_machine(tftp_state_data_t *state, tftp_event_t event) { - CURLcode result = CURLE_OK; + CURLcode res = CURLE_OK; struct SessionHandle *data = state->conn->data; - switch(state->state) { case TFTP_STATE_START: DEBUGF(infof(data, "TFTP_STATE_START\n")); - result = tftp_send_first(state, event); + res = tftp_send_first(state, event); break; case TFTP_STATE_RX: DEBUGF(infof(data, "TFTP_STATE_RX\n")); - result = tftp_rx(state, event); + res = tftp_rx(state, event); break; case TFTP_STATE_TX: DEBUGF(infof(data, "TFTP_STATE_TX\n")); - result = tftp_tx(state, event); + res = tftp_tx(state, event); break; case TFTP_STATE_FIN: infof(data, "%s\n", "TFTP finished"); @@ -907,11 +906,10 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state, default: DEBUGF(infof(data, "STATE: %d\n", state->state)); failf(data, "%s", "Internal state machine error"); - result = CURLE_TFTP_ILLEGAL; + res = CURLE_TFTP_ILLEGAL; break; } - - return result; + return res; } /********************************************************** @@ -945,6 +943,7 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) **********************************************************/ static CURLcode tftp_connect(struct connectdata *conn, bool *done) { + CURLcode code; tftp_state_data_t *state; int blksize, rc; @@ -1018,8 +1017,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) Curl_pgrsStartNow(conn->data); *done = TRUE; - - return CURLE_OK; + code = CURLE_OK; + return(code); } /********************************************************** @@ -1032,7 +1031,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) static CURLcode tftp_done(struct connectdata *conn, CURLcode status, bool premature) { - CURLcode result = CURLE_OK; + CURLcode code = CURLE_OK; tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; (void)status; /* unused */ @@ -1043,9 +1042,9 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status, /* If we have encountered an error */ if(state) - result = tftp_translate_code(state->error); + code = tftp_translate_code(state->error); - return result; + return code; } /********************************************************** @@ -1210,7 +1209,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) else if(event != TFTP_EVENT_NONE) { result = tftp_state_machine(state, event); if(result) - return result; + return(result); *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ @@ -1229,10 +1228,10 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) else if(rc != 0) { result = tftp_receive_packet(conn); if(result) - return result; + return(result); result = tftp_state_machine(state, state->event); if(result) - return result; + return(result); *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ diff --git a/lib/timeval.c b/lib/timeval.c index 45731ac59..769eb3c49 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -118,7 +118,7 @@ struct timeval curlx_tvnow(void) long curlx_tvdiff(struct timeval newer, struct timeval older) { return (newer.tv_sec-older.tv_sec)*1000+ - (long)(newer.tv_usec-older.tv_usec)/1000; + (newer.tv_usec-older.tv_usec)/1000; } /* diff --git a/lib/transfer.c b/lib/transfer.c index 718139b32..a7ab08ecf 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -75,14 +75,16 @@ #include "curl_ntlm.h" #include "http_negotiate.h" #include "share.h" +#include "curl_memory.h" #include "select.h" #include "multiif.h" #include "connect.h" #include "non-ascii.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* @@ -115,8 +117,8 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) /* this function returns a size_t, so we typecast to int to prevent warnings with picky compilers */ - nread = (int)data->set.fread_func(data->req.upload_fromhere, 1, - buffersize, data->set.in); + nread = (int)conn->fread_func(data->req.upload_fromhere, 1, + buffersize, conn->fread_in); if(nread == CURL_READFUNC_ABORT) { failf(data, "operation aborted by callback"); @@ -214,7 +216,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) result = Curl_convert_to_network(data, data->req.upload_fromhere, length); /* Curl_convert_to_network calls failf if unsuccessful */ if(result) - return result; + return(result); #endif /* CURL_DOES_CONVERSIONS */ if((nread - hexlen) == 0) @@ -317,7 +319,8 @@ static int data_pending(const struct connectdata *conn) TRUE. The thing is if we read everything, then http2_recv won't be called and we cannot signal the HTTP/2 stream has closed. As a workaround, we return nonzero here to call http2_recv. */ - ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20); + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 && + conn->proto.httpc.closed); #else Curl_ssl_data_pending(conn, FIRSTSOCKET); #endif @@ -432,7 +435,6 @@ static CURLcode readwrite_data(struct SessionHandle *data, else { /* read nothing but since we wanted nothing we consider this an OK situation to proceed from */ - DEBUGF(infof(data, "readwrite_data: we're done!\n")); nread = 0; } @@ -494,7 +496,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, /* We've stopped dealing with input, get out of the do-while loop */ if(nread > 0) { - if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) { + if(Curl_multi_pipeline_enabled(conn->data->multi)) { infof(data, "Rewinding stream by : %zd" " bytes on url %s (zero-length body)\n", @@ -639,7 +641,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, if(dataleft != 0) { infof(conn->data, "Leftovers after chunking: %zu bytes\n", dataleft); - if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) { + if(Curl_multi_pipeline_enabled(conn->data->multi)) { /* only attempt the rewind if we truly are pipelining */ infof(conn->data, "Rewinding %zu bytes\n",dataleft); read_rewind(conn, dataleft); @@ -662,7 +664,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, excess = (size_t)(k->bytecount + nread - k->maxdownload); if(excess > 0 && !k->ignorebody) { - if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) { + if(Curl_multi_pipeline_enabled(conn->data->multi)) { /* The 'excess' amount below can't be more than BUFSIZE which always will fit in a size_t */ infof(data, @@ -756,6 +758,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, result = Curl_unencode_gzip_write(conn, k, nread); break; + case COMPRESS: default: failf (data, "Unrecognized content encoding type. " "libcurl understands `identity', `deflate' and `gzip' " @@ -827,6 +830,13 @@ static CURLcode readwrite_upload(struct SessionHandle *data, *didwhat |= KEEP_SEND; + /* + * We loop here to do the READ and SEND loop until we run out of + * data to send or until we get EWOULDBLOCK back + * + * FIXME: above comment is misleading. Currently no looping is + * actually done in do-while loop below. + */ do { /* only read more data if there's no upload data already @@ -1012,9 +1022,9 @@ static CURLcode readwrite_upload(struct SessionHandle *data, * be read and written to/from the connection. */ CURLcode Curl_readwrite(struct connectdata *conn, - struct SessionHandle *data, bool *done) { + struct SessionHandle *data = conn->data; struct SingleRequest *k = &data->req; CURLcode result; int didwhat=0; @@ -1038,11 +1048,6 @@ CURLcode Curl_readwrite(struct connectdata *conn, else fd_write = CURL_SOCKET_BAD; - if(conn->data->state.drain) { - select_res |= CURL_CSELECT_IN; - DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); - } - if(!select_res) /* Call for select()/poll() only, if read/write/error status is not known. */ select_res = Curl_socket_ready(fd_read, fd_write, 0); @@ -1267,7 +1272,7 @@ long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps, * the next packet at the adjusted rate. We should wait * longer when using larger packets, for instance. */ - rv = ((curl_off_t)(pkt_size * 1000) / rate_bps); + rv = ((curl_off_t)((pkt_size * 8) * 1000) / rate_bps); /* Catch rounding errors and always slow down at least 1ms if * we are running too fast. @@ -1314,11 +1319,6 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) Curl_safefree(data->info.wouldredirect); data->info.wouldredirect = NULL; - if(data->set.httpreq == HTTPREQ_PUT) - data->state.infilesize = data->set.filesize; - else - data->state.infilesize = data->set.postfieldsize; - /* If there is a list of cookie files to read, do it now! */ if(data->change.cookielist) Curl_cookie_loadfiles(data); @@ -1342,7 +1342,6 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) #endif Curl_initinfo(data); /* reset session-specific information "variables" */ - Curl_pgrsResetTimesSizes(data); Curl_pgrsStartNow(data); if(data->set.timeout) @@ -1634,7 +1633,7 @@ CURLcode Curl_follow(struct SessionHandle *data, if(type == FOLLOW_REDIR) { if((data->set.maxredirs != -1) && (data->set.followlocation >= data->set.maxredirs)) { - failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); + failf(data,"Maximum (%ld) redirects followed", data->set.maxredirs); return CURLE_TOO_MANY_REDIRECTS; } diff --git a/lib/transfer.h b/lib/transfer.h index 316aeaebc..ad4a3acd6 100644 --- a/lib/transfer.h +++ b/lib/transfer.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,8 +40,7 @@ CURLcode Curl_follow(struct SessionHandle *data, char *newurl, followtype type); -CURLcode Curl_readwrite(struct connectdata *conn, - struct SessionHandle *data, bool *done); +CURLcode Curl_readwrite(struct connectdata *conn, bool *done); int Curl_single_getsock(const struct connectdata *conn, curl_socket_t *socks, int numsocks); @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -124,12 +124,16 @@ int curl_win32_idn_to_ascii(const char *in, char **out); #include "curl_rtmp.h" #include "gopher.h" #include "http_proxy.h" +#include "bundles.h" #include "conncache.h" #include "multihandle.h" #include "pipeline.h" #include "dotdot.h" #include "strdup.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -142,6 +146,7 @@ find_oldest_idle_connection_in_bundle(struct SessionHandle *data, struct connectbundle *bundle); static void conn_free(struct connectdata *conn); static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); +static CURLcode do_init(struct connectdata *conn); static CURLcode parse_url_login(struct SessionHandle *data, struct connectdata *conn, char **userptr, char **passwdptr, @@ -446,8 +451,10 @@ CURLcode Curl_close(struct SessionHandle *data) Curl_ssl_free_certinfo(data); /* Cleanup possible redirect junk */ - free(data->req.newurl); - data->req.newurl = NULL; + if(data->req.newurl) { + free(data->req.newurl); + data->req.newurl = NULL; + } if(data->change.referer_alloc) { Curl_safefree(data->change.referer); @@ -574,30 +581,13 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) (char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE); if(result) return result; - - /* set default negotiate proxy service name */ - result = setstropt(&set->str[STRING_PROXY_SERVICE_NAME], - (char *) CURL_DEFAULT_PROXY_SERVICE_NAME); - if(result) - return result; - - /* set default negotiate service name */ - result = setstropt(&set->str[STRING_SERVICE_NAME], - (char *) CURL_DEFAULT_SERVICE_NAME); - if(result) - return result; #endif /* This is our preferred CA cert bundle/path since install time */ #if defined(CURL_CA_BUNDLE) result = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE); - if(result) - return result; -#endif -#if defined(CURL_CA_PATH) +#elif defined(CURL_CA_PATH) result = setstropt(&set->str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH); - if(result) - return result; #endif set->wildcardmatch = FALSE; @@ -615,7 +605,6 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->ssl_enable_alpn = TRUE; set->expect_100_timeout = 1000L; /* Wait for a second by default. */ - set->sep_headers = TRUE; /* separated header lists by default */ return result; } @@ -677,7 +666,8 @@ CURLcode Curl_open(struct SessionHandle **curl) if(result) { Curl_resolver_cleanup(data->state.resolver); - free(data->state.headerbuff); + if(data->state.headerbuff) + free(data->state.headerbuff); Curl_freeset(data); free(data); data = NULL; @@ -903,11 +893,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, * Set explicit SSL version to try to connect with, as some SSL * implementations are lame. */ -#ifdef USE_SSL data->set.ssl.version = va_arg(param, long); -#else - result = CURLE_UNKNOWN_OPTION; -#endif break; #ifndef CURL_DISABLE_HTTP @@ -1250,7 +1236,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, argptr = strdup(argptr); if(!argptr || !data->cookies) { result = CURLE_OUT_OF_MEMORY; - free(argptr); + Curl_safefree(argptr); } else { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); @@ -1483,29 +1469,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, va_arg(param, char *)); break; - case CURLOPT_PROXY_SERVICE_NAME: - /* - * Set negotiate proxy service name - */ - result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], - va_arg(param, char *)); - break; - case CURLOPT_SOCKS5_GSSAPI_NEC: /* * set flag for nec socks5 support */ data->set.socks5_gssapi_nec = (0 != va_arg(param, long))?TRUE:FALSE; break; - - case CURLOPT_SERVICE_NAME: - /* - * Set negotiate service identity - */ - result = setstropt(&data->set.str[STRING_SERVICE_NAME], - va_arg(param, char *)); - break; - #endif case CURLOPT_HEADERDATA: @@ -2028,17 +1997,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.ssl.verifyhost = (0 != arg)?TRUE:FALSE; break; - case CURLOPT_SSL_VERIFYSTATUS: - /* - * Enable certificate status verifying. - */ - if(!Curl_ssl_cert_status_request()) { - result = CURLE_NOT_BUILT_IN; - break; - } - - data->set.ssl.verifystatus = (0 != va_arg(param, long))?TRUE:FALSE; - break; case CURLOPT_SSL_CTX_FUNCTION: #ifdef have_curlssl_ssl_ctx /* @@ -2059,17 +2017,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, result = CURLE_NOT_BUILT_IN; #endif break; - case CURLOPT_SSL_FALSESTART: - /* - * Enable TLS false start. - */ - if(!Curl_ssl_false_start()) { - result = CURLE_NOT_BUILT_IN; - break; - } - - data->set.ssl.falsestart = (0 != va_arg(param, long))?TRUE:FALSE; - break; case CURLOPT_CERTINFO: #ifdef have_curlssl_certinfo data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE; @@ -2185,15 +2132,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->share->dirty++; - if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) { + if(data->share->hostcache) { /* use shared host cache */ - data->dns.hostcache = &data->share->hostcache; + data->dns.hostcache = data->share->hostcache; data->dns.hostcachetype = HCACHE_SHARED; } #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(data->share->cookies) { /* use shared cookie list, first free own one if any */ - Curl_cookie_cleanup(data->cookies); + if(data->cookies) + Curl_cookie_cleanup(data->cookies); /* enable cookies since we now use a share that uses cookies! */ data->cookies = data->share->cookies; } @@ -2234,8 +2182,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); - data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + data->set.ssl_enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; break; #endif @@ -2646,12 +2593,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, break; #endif - case CURLOPT_PATH_AS_IS: - data->set.path_as_is = (0 != va_arg(param, long))?TRUE:FALSE; - break; - case CURLOPT_PIPEWAIT: - data->set.pipewait = (0 != va_arg(param, long))?TRUE:FALSE; - break; default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; @@ -2777,15 +2718,16 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) free(conn->host.encalloc); /* encoded host name buffer, must be freed with idn_free() since this was allocated by curl_win32_idn_to_ascii */ - free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed - with idn_free() since this was allocated by - curl_win32_idn_to_ascii */ + if(conn->proxy.encalloc) + free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed + with idn_free() since this was allocated by + curl_win32_idn_to_ascii */ #endif Curl_ssl_close(conn, FIRSTSOCKET); /* Indicate to all handles on the pipe that we're dead */ - if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) { + if(Curl_multi_pipeline_enabled(data->multi)) { signalPipeClose(conn->send_pipe, TRUE); signalPipeClose(conn->recv_pipe, TRUE); } @@ -2813,31 +2755,32 @@ static bool SocketIsDead(curl_socket_t sock) return ret_val; } -/* - * IsPipeliningPossible() returns TRUE if the options set would allow - * pipelining/multiplexing and the connection is using a HTTP protocol. - */ static bool IsPipeliningPossible(const struct SessionHandle *handle, const struct connectdata *conn) { - /* If a HTTP protocol and pipelining is enabled */ - if(conn->handler->protocol & PROTO_FAMILY_HTTP) { - - if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) && - (handle->set.httpversion != CURL_HTTP_VERSION_1_0) && - (handle->set.httpreq == HTTPREQ_GET || - handle->set.httpreq == HTTPREQ_HEAD)) - /* didn't ask for HTTP/1.0 and a GET or HEAD */ - return TRUE; + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + Curl_multi_pipeline_enabled(handle->multi) && + (handle->set.httpreq == HTTPREQ_GET || + handle->set.httpreq == HTTPREQ_HEAD) && + handle->set.httpversion != CURL_HTTP_VERSION_1_0) + return TRUE; - if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) && - (handle->set.httpversion == CURL_HTTP_VERSION_2_0)) - /* allows HTTP/2 */ - return TRUE; - } return FALSE; } +bool Curl_isPipeliningEnabled(const struct SessionHandle *handle) +{ + return Curl_multi_pipeline_enabled(handle->multi); +} + +CURLcode Curl_addHandleToPipeline(struct SessionHandle *data, + struct curl_llist *pipeline) +{ + if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + int Curl_removeHandleFromPipeline(struct SessionHandle *handle, struct curl_llist *pipeline) { @@ -2885,14 +2828,15 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data, struct connectdata *conn) { bool recv_head = (conn->readchannel_inuse && - Curl_recvpipe_head(data, conn)); + (gethandleathead(conn->recv_pipe) == data)) ? TRUE : FALSE; + bool send_head = (conn->writechannel_inuse && - Curl_sendpipe_head(data, conn)); + (gethandleathead(conn->send_pipe) == data)) ? TRUE : FALSE; if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head) - Curl_pipeline_leave_read(conn); + conn->readchannel_inuse = FALSE; if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head) - Curl_pipeline_leave_write(conn); + conn->writechannel_inuse = FALSE; } static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke) @@ -2944,7 +2888,7 @@ find_oldest_idle_connection(struct SessionHandle *data) now = Curl_tvnow(); - Curl_hash_start_iterate(&bc->hash, &iter); + Curl_hash_start_iterate(bc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { @@ -3078,13 +3022,6 @@ static void prune_dead_connections(struct SessionHandle *data) } } - -static size_t max_pipeline_length(struct Curl_multi *multi) -{ - return multi ? multi->max_pipeline_length : 0; -} - - /* * Given one filled in connection struct (named needle), this function should * detect if there already is one that has all the significant details @@ -3101,21 +3038,17 @@ static bool ConnectionExists(struct SessionHandle *data, struct connectdata *needle, struct connectdata **usethis, - bool *force_reuse, - bool *waitpipe) + bool *force_reuse) { struct connectdata *check; struct connectdata *chosen = 0; bool canPipeline = IsPipeliningPossible(data, needle); -#ifdef USE_NTLM bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) || (data->state.authhost.want & CURLAUTH_NTLM_WB)) && (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE; -#endif struct connectbundle *bundle; *force_reuse = FALSE; - *waitpipe = FALSE; /* We can't pipe if the site is blacklisted */ if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) { @@ -3124,11 +3057,10 @@ ConnectionExists(struct SessionHandle *data, /* Look up the bundle with all the connections to this particular host */ - bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache); + bundle = Curl_conncache_find_bundle(data->state.conn_cache, + needle->host.name); if(bundle) { - /* Max pipe length is zero (unlimited) for multiplexed connections */ - size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)? - max_pipeline_length(data->multi):0; + size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi); size_t best_pipe_len = max_pipe_len; struct curl_llist_element *curr; @@ -3136,17 +3068,9 @@ ConnectionExists(struct SessionHandle *data, needle->host.name, (void *)bundle); /* We can't pipe if we don't know anything about the server */ - if(canPipeline) { - if(bundle->multiuse <= BUNDLE_UNKNOWN) { - if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) { - infof(data, "Server doesn't support multi-use yet, wait\n"); - *waitpipe = TRUE; - return FALSE; /* no re-use */ - } - - infof(data, "Server doesn't support multi-use (yet)\n"); - canPipeline = FALSE; - } + if(canPipeline && !bundle->server_supports_pipelining) { + infof(data, "Server doesn't support pipelining\n"); + canPipeline = FALSE; } curr = bundle->conn_list->head; @@ -3170,19 +3094,16 @@ ConnectionExists(struct SessionHandle *data, pipeLen = check->send_pipe->size + check->recv_pipe->size; if(canPipeline) { - - if(!check->bits.multiplex) { - /* If not multiplexing, make sure the pipe has only GET requests */ - struct SessionHandle* sh = gethandleathead(check->send_pipe); - struct SessionHandle* rh = gethandleathead(check->recv_pipe); - if(sh) { - if(!IsPipeliningPossible(sh, check)) - continue; - } - else if(rh) { - if(!IsPipeliningPossible(rh, check)) - continue; - } + /* Make sure the pipe has only GET requests */ + struct SessionHandle* sh = gethandleathead(check->send_pipe); + struct SessionHandle* rh = gethandleathead(check->recv_pipe); + if(sh) { + if(!IsPipeliningPossible(sh, check)) + continue; + } + else if(rh) { + if(!IsPipeliningPossible(rh, check)) + continue; } } else { @@ -3262,11 +3183,8 @@ ConnectionExists(struct SessionHandle *data, continue; } - if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) -#ifdef USE_NTLM - || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE) -#endif - ) { + if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) || + wantNTLMhttp) { /* This protocol requires credentials per connection or is HTTP+NTLM, so verify that we're using the same name and password as well */ if(!strequal(needle->user, check->user) || @@ -3361,42 +3279,19 @@ ConnectionExists(struct SessionHandle *data, } /* We can't use the connection if the pipe is full */ - if(max_pipe_len && (pipeLen >= max_pipe_len)) { - infof(data, "Pipe is full, skip (%zu)\n", pipeLen); + if(pipeLen >= max_pipe_len) continue; - } -#ifdef USE_NGHTTP2 - /* If multiplexed, make sure we don't go over concurrency limit */ - if(check->bits.multiplex) { - /* Multiplexed connections can only be HTTP/2 for now */ - struct http_conn *httpc = &check->proto.httpc; - if(pipeLen >= httpc->settings.max_concurrent_streams) { - infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n", - pipeLen); - continue; - } - } -#endif + /* We can't use the connection if the pipe is penalized */ - if(Curl_pipeline_penalized(data, check)) { - infof(data, "Penalized, skip\n"); + if(Curl_pipeline_penalized(data, check)) continue; - } - if(max_pipe_len) { - if(pipeLen < best_pipe_len) { - /* This connection has a shorter pipe so far. We'll pick this - and continue searching */ - chosen = check; - best_pipe_len = pipeLen; - continue; - } - } - else { - /* When not pipelining (== multiplexed), we have a match here! */ + if(pipeLen < best_pipe_len) { + /* This connection has a shorter pipe so far. We'll pick this + and continue searching */ chosen = check; - infof(data, "Multiplexed connection found!\n"); - break; + best_pipe_len = pipeLen; + continue; } } else { @@ -3448,6 +3343,20 @@ ConnectionDone(struct SessionHandle *data, struct connectdata *conn) return (conn_candidate == conn) ? FALSE : TRUE; } +/* + * The given input connection struct pointer is to be stored in the connection + * cache. If the cache is already full, least interesting existing connection + * (if any) gets closed. + * + * The given connection should be unique. That must've been checked prior to + * this call. + */ +static CURLcode ConnectionStore(struct SessionHandle *data, + struct connectdata *conn) +{ + return Curl_conncache_add_conn(data->state.conn_cache, conn); +} + /* after a TCP connection to the proxy has been verified, this function does the next magic step. @@ -3693,7 +3602,7 @@ static void fix_hostname(struct SessionHandle *data, host->dispname = host->name; len = strlen(host->name); - if(len && (host->name[len-1] == '.')) + if(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; @@ -3710,7 +3619,7 @@ static void fix_hostname(struct SessionHandle *data, stringprep_locale_charset ()); if(rc != IDNA_SUCCESS) infof(data, "Failed to convert %s to ACE; %s\n", - host->name, Curl_idn_strerror(conn, rc)); + host->name, Curl_idn_strerror(conn,rc)); else { /* tld_check_name() displays a warning if the host name contains "illegal" characters for this TLD */ @@ -3823,9 +3732,9 @@ static struct connectdata *allocate_conn(struct SessionHandle *data) conn->response_header = NULL; #endif - if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) && - !conn->master_buffer) { - /* Allocate master_buffer to be used for HTTP/1 pipelining */ + if(Curl_multi_pipeline_enabled(data->multi) && + !conn->master_buffer) { + /* Allocate master_buffer to be used for pipelining */ conn->master_buffer = calloc(BUFSIZE, sizeof (char)); if(!conn->master_buffer) goto error; @@ -3864,9 +3773,9 @@ static struct connectdata *allocate_conn(struct SessionHandle *data) conn->send_pipe = NULL; conn->recv_pipe = NULL; - free(conn->master_buffer); - free(conn->localdev); - free(conn); + Curl_safefree(conn->master_buffer); + Curl_safefree(conn->localdev); + Curl_safefree(conn); return NULL; } @@ -4109,7 +4018,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, path[0] = '/'; rebuild_url = TRUE; } - else if(!data->set.path_as_is) { + else { /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */ char *newp = Curl_dedotdotify(path); if(!newp) @@ -4504,7 +4413,8 @@ static char *detect_proxy(struct connectdata *conn) } } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified non-proxy */ - free(no_proxy); + if(no_proxy) + free(no_proxy); #else /* !CURL_DISABLE_HTTP */ @@ -4518,6 +4428,7 @@ static char *detect_proxy(struct connectdata *conn) * If this is supposed to use a proxy, we need to figure out the proxy * host name, so that we can re-use an existing connection * that may exist registered to the same proxy host. + * proxy will be freed before this function returns. */ static CURLcode parse_proxy(struct SessionHandle *data, struct connectdata *conn, char *proxy) @@ -4591,8 +4502,8 @@ static CURLcode parse_proxy(struct SessionHandle *data, } } - free(proxyuser); - free(proxypasswd); + Curl_safefree(proxyuser); + Curl_safefree(proxypasswd); if(result) return result; @@ -4804,9 +4715,9 @@ static CURLcode parse_url_login(struct SessionHandle *data, out: - free(userp); - free(passwdp); - free(optionsp); + Curl_safefree(userp); + Curl_safefree(passwdp); + Curl_safefree(optionsp); return result; } @@ -4894,7 +4805,7 @@ static CURLcode parse_login_details(const char *login, const size_t len, if(!result && passwdp && plen) { pbuf = malloc(plen + 1); if(!pbuf) { - free(ubuf); + Curl_safefree(ubuf); result = CURLE_OUT_OF_MEMORY; } } @@ -4903,8 +4814,8 @@ static CURLcode parse_login_details(const char *login, const size_t len, if(!result && optionsp && olen) { obuf = malloc(olen + 1); if(!obuf) { - free(pbuf); - free(ubuf); + Curl_safefree(pbuf); + Curl_safefree(ubuf); result = CURLE_OUT_OF_MEMORY; } } @@ -5266,7 +5177,8 @@ static CURLcode resolve_server(struct SessionHandle *data, static void reuse_conn(struct connectdata *old_conn, struct connectdata *conn) { - free(old_conn->proxy.rawalloc); + if(old_conn->proxy.rawalloc) + free(old_conn->proxy.rawalloc); /* free the SSL config struct from this connection struct as this was allocated in vain and is targeted for destruction */ @@ -5354,9 +5266,8 @@ static CURLcode create_conn(struct SessionHandle *data, bool reuse; char *proxy = NULL; bool prot_missing = FALSE; - bool connections_available = TRUE; + bool no_connections_available = FALSE; bool force_reuse = FALSE; - bool waitpipe = FALSE; size_t max_host_connections = Curl_multi_max_host_connections(data->multi); size_t max_total_connections = Curl_multi_max_total_connections(data->multi); @@ -5516,8 +5427,10 @@ static CURLcode create_conn(struct SessionHandle *data, if(data->set.str[STRING_NOPROXY] && check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) { - free(proxy); /* proxy is in exception list */ - proxy = NULL; + if(proxy) { + free(proxy); /* proxy is in exception list */ + proxy = NULL; + } } else if(!proxy) proxy = detect_proxy(conn); @@ -5543,8 +5456,7 @@ static CURLcode create_conn(struct SessionHandle *data, if(proxy) { result = parse_proxy(data, conn, proxy); - free(proxy); /* parse_proxy copies the proxy string */ - proxy = NULL; + Curl_safefree(proxy); /* parse_proxy copies the proxy string */ if(result) goto out; @@ -5565,10 +5477,8 @@ static CURLcode create_conn(struct SessionHandle *data, conn->bits.httpproxy = TRUE; #endif } - else { + else conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ - conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ - } conn->bits.proxy = TRUE; } else { @@ -5633,7 +5543,7 @@ static CURLcode create_conn(struct SessionHandle *data, conn->data = data; conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ - Curl_conncache_add_conn(data->state.conn_cache, conn); + ConnectionStore(data, conn); /* * Setup whatever necessary for a resumed transfer @@ -5651,7 +5561,7 @@ static CURLcode create_conn(struct SessionHandle *data, } /* since we skip do_init() */ - Curl_init_do(data, conn); + do_init(conn); goto out; } @@ -5698,7 +5608,7 @@ static CURLcode create_conn(struct SessionHandle *data, if(data->set.reuse_fresh && !data->state.this_is_a_follow) reuse = FALSE; else - reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe); + reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse); /* If we found a reusable connection, we may still want to open a new connection if we are pipelining. */ @@ -5735,24 +5645,18 @@ static CURLcode create_conn(struct SessionHandle *data, /* set a pointer to the hostname we display */ fix_hostname(data, conn, &conn->host); - infof(data, "Re-using existing connection! (#%ld) with %s %s\n", + infof(data, "Re-using existing connection! (#%ld) with host %s\n", conn->connection_id, - conn->bits.proxy?"proxy":"host", conn->proxy.name?conn->proxy.dispname:conn->host.dispname); } else { /* We have decided that we want a new connection. However, we may not be able to do that if we have reached the limit of how many connections we are allowed to open. */ - struct connectbundle *bundle = NULL; - - if(waitpipe) - /* There is a connection that *might* become usable for pipelining - "soon", and we wait for that */ - connections_available = FALSE; - else - bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); + struct connectbundle *bundle; + bundle = Curl_conncache_find_bundle(data->state.conn_cache, + conn->host.name); if(max_host_connections > 0 && bundle && (bundle->num_connections >= max_host_connections)) { struct connectdata *conn_candidate; @@ -5765,15 +5669,11 @@ static CURLcode create_conn(struct SessionHandle *data, conn_candidate->data = data; (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE); } - else { - infof(data, "No more connections allowed to host: %d\n", - max_host_connections); - connections_available = FALSE; - } + else + no_connections_available = TRUE; } - if(connections_available && - (max_total_connections > 0) && + if(max_total_connections > 0 && (data->state.conn_cache->num_connections >= max_total_connections)) { struct connectdata *conn_candidate; @@ -5785,13 +5685,12 @@ static CURLcode create_conn(struct SessionHandle *data, conn_candidate->data = data; (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE); } - else { - infof(data, "No connections available in cache\n"); - connections_available = FALSE; - } + else + no_connections_available = TRUE; } - if(!connections_available) { + + if(no_connections_available) { infof(data, "No connections available.\n"); conn_free(conn); @@ -5805,7 +5704,7 @@ static CURLcode create_conn(struct SessionHandle *data, * This is a brand new connection, so let's store it in the connection * cache of ours! */ - Curl_conncache_add_conn(data->state.conn_cache, conn); + ConnectionStore(data, conn); } #if defined(USE_NTLM) @@ -5830,7 +5729,7 @@ static CURLcode create_conn(struct SessionHandle *data, conn->inuse = TRUE; /* Setup and init stuff before DO starts, in preparing for the transfer. */ - Curl_init_do(data, conn); + do_init(conn); /* * Setup whatever necessary for a resumed transfer @@ -5845,6 +5744,8 @@ static CURLcode create_conn(struct SessionHandle *data, * Inherit the proper values from the urldata struct AFTER we have arranged * the persistent connection stuff */ + conn->fread_func = data->set.fread_func; + conn->fread_in = data->set.in; conn->seek_func = data->set.seek_func; conn->seek_client = data->set.seek_client; @@ -5855,10 +5756,10 @@ static CURLcode create_conn(struct SessionHandle *data, out: - free(options); - free(passwd); - free(user); - free(proxy); + Curl_safefree(options); + Curl_safefree(passwd); + Curl_safefree(user); + Curl_safefree(proxy); return result; } @@ -6002,19 +5903,37 @@ CURLcode Curl_done(struct connectdata **connp, conn = *connp; data = conn->data; - DEBUGF(infof(data, "Curl_done\n")); - - if(data->state.done) + if(conn->bits.done) /* Stop if Curl_done() has already been called */ return CURLE_OK; Curl_getoff_all_pipelines(data, conn); + if((conn->send_pipe->size + conn->recv_pipe->size != 0 && + !data->set.reuse_forbid && + !conn->bits.close)) + /* Stop if pipeline is not empty and we do not have to close + connection. */ + return CURLE_OK; + + conn->bits.done = TRUE; /* called just now! */ + /* Cleanup possible redirect junk */ - free(data->req.newurl); - data->req.newurl = NULL; - free(data->req.location); - data->req.location = NULL; + if(data->req.newurl) { + free(data->req.newurl); + data->req.newurl = NULL; + } + if(data->req.location) { + free(data->req.location); + data->req.location = NULL; + } + + Curl_resolver_cancel(conn); + + if(conn->dns_entry) { + Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ + conn->dns_entry = NULL; + } switch(status) { case CURLE_ABORTED_BY_CALLBACK: @@ -6038,27 +5957,12 @@ CURLcode Curl_done(struct connectdata **connp, if(!result && Curl_pgrsDone(conn)) result = CURLE_ABORTED_BY_CALLBACK; - if((conn->send_pipe->size + conn->recv_pipe->size != 0 && - !data->set.reuse_forbid && - !conn->bits.close)) { - /* Stop if pipeline is not empty and we do not have to close - connection. */ - DEBUGF(infof(data, "Connection still in use, no more Curl_done now!\n")); - return CURLE_OK; - } - - data->state.done = TRUE; /* called just now! */ - Curl_resolver_cancel(conn); - - if(conn->dns_entry) { - Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ - conn->dns_entry = NULL; - } - /* if the transfer was completed in a paused state there can be buffered data left to write and then kill */ - free(data->state.tempwrite); - data->state.tempwrite = NULL; + if(data->state.tempwrite) { + free(data->state.tempwrite); + data->state.tempwrite = NULL; + } /* if data->set.reuse_forbid is TRUE, it means the libcurl client has forced us to close this connection. This is ignored for requests taking @@ -6112,24 +6016,20 @@ CURLcode Curl_done(struct connectdata **connp, } /* - * Curl_init_do() inits the readwrite session. This is inited each time (in - * the DO function before the protocol-specific DO functions are invoked) for - * a transfer, sometimes multiple times on the same SessionHandle. Make sure + * do_init() inits the readwrite session. This is inited each time (in the DO + * function before the protocol-specific DO functions are invoked) for a + * transfer, sometimes multiple times on the same SessionHandle. Make sure * nothing in here depends on stuff that are setup dynamically for the * transfer. - * - * Allow this function to get called with 'conn' set to NULL. */ -CURLcode Curl_init_do(struct SessionHandle *data, struct connectdata *conn) +static CURLcode do_init(struct connectdata *conn) { + struct SessionHandle *data = conn->data; struct SingleRequest *k = &data->req; - if(conn) - conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to - * use */ - - data->state.done = FALSE; /* Curl_done() is not called yet */ + conn->bits.done = FALSE; /* Curl_done() is not called yet */ + conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */ data->state.expect100header = FALSE; if(data->set.opt_no_body) @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,7 +27,6 @@ * Prototypes for library-wide functions provided by url.c */ -CURLcode Curl_init_do(struct SessionHandle *data, struct connectdata *conn); CURLcode Curl_open(struct SessionHandle **curl); CURLcode Curl_init_userdefined(struct UserDefined *set); CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, @@ -70,9 +69,6 @@ void Curl_close_connections(struct SessionHandle *data); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi service */ -#define CURL_DEFAULT_PROXY_SERVICE_NAME "HTTP" /* default negotiate proxy - service */ -#define CURL_DEFAULT_SERVICE_NAME "HTTP" /* default negotiate service */ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); diff --git a/lib/urldata.h b/lib/urldata.h index b1c2056c5..5f774704a 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -82,12 +82,38 @@ #include "cookie.h" #include "formdata.h" +#ifdef USE_SSLEAY #ifdef USE_OPENSSL +#include <openssl/rsa.h> +#include <openssl/crypto.h> +#include <openssl/x509.h> +#include <openssl/pem.h> #include <openssl/ssl.h> +#include <openssl/err.h> #ifdef HAVE_OPENSSL_ENGINE_H #include <openssl/engine.h> #endif +#ifdef HAVE_OPENSSL_PKCS12_H +#include <openssl/pkcs12.h> +#endif +#else /* SSLeay-style includes */ +#include <rsa.h> +#include <crypto.h> +#include <x509.h> +#include <pem.h> +#include <ssl.h> +#include <err.h> +#ifdef HAVE_OPENSSL_ENGINE_H +#include <engine.h> +#endif +#ifdef HAVE_OPENSSL_PKCS12_H +#include <pkcs12.h> +#endif #endif /* USE_OPENSSL */ +#ifdef USE_GNUTLS +#error Configuration error; cannot use GnuTLS *and* OpenSSL. +#endif +#endif /* USE_SSLEAY */ #ifdef USE_GNUTLS #include <gnutls/gnutls.h> @@ -120,7 +146,6 @@ #endif #ifdef USE_AXTLS -#include <axTLS/config.h> #include <axTLS/ssl.h> #undef malloc #undef calloc @@ -198,8 +223,6 @@ #define HEADERSIZE 256 #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU -#define GOOD_EASY_HANDLE(x) \ - ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)) /* Some convenience macros to get the larger/smaller value out of two given. We prefix with CURL to prevent name collisions. */ @@ -265,13 +288,16 @@ struct ssl_connect_data { current state of the connection. */ bool use; ssl_connection_state state; -#ifdef USE_OPENSSL +#ifdef USE_NGHTTP2 + bool asked_for_h2; +#endif +#ifdef USE_SSLEAY /* these ones requires specific SSL-types */ SSL_CTX* ctx; SSL* handle; X509* server_cert; ssl_connect_state connecting_state; -#endif /* USE_OPENSSL */ +#endif /* USE_SSLEAY */ #ifdef USE_GNUTLS gnutls_session_t session; gnutls_certificate_credentials_t cred; @@ -324,9 +350,6 @@ struct ssl_connect_data { size_t encdata_offset, decdata_offset; unsigned char *encdata_buffer, *decdata_buffer; unsigned long req_flags, ret_flags; - CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ - bool recv_sspi_close_notify; /* true if connection closed by close_notify */ - bool recv_connection_closed; /* true if connection closed, regardless how */ #endif /* USE_SCHANNEL */ #ifdef USE_DARWINSSL SSLContextRef ssl_ctx; @@ -343,7 +366,6 @@ struct ssl_config_data { bool verifypeer; /* set TRUE if this is desired */ bool verifyhost; /* set TRUE if CN/SAN must match hostname */ - bool verifystatus; /* set TRUE if certificate status must be checked */ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ const char *CRLfile; /* CRL to check certificate revocation */ @@ -356,7 +378,6 @@ struct ssl_config_data { void *fsslctxp; /* parameter for call back */ bool sessionid; /* cache session IDs or not */ bool certinfo; /* gather lots of certificate info */ - bool falsestart; #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ @@ -521,6 +542,11 @@ struct ConnectBits { requests */ bool netrc; /* name+password provided by netrc */ bool userpwd_in_url; /* name+password found in url */ + + bool done; /* set to FALSE when Curl_do() is called and set to TRUE + when Curl_done() is called, to prevent Curl_done() to + get invoked twice when the multi interface is + used. */ bool stream_was_rewound; /* Indicates that the stream was rewound after a request read past the end of its response byte boundary */ @@ -530,7 +556,6 @@ struct ConnectBits { bool bound; /* set true if bind() has already been done on this socket/ connection */ bool type_set; /* type= was used in the URL */ - bool multiplex; /* connection is multiplexed */ }; struct hostname { @@ -603,6 +628,12 @@ enum upgrade101 { UPGR101_WORKING /* talking upgraded protocol */ }; +enum negotiatenpn { + NPN_INIT, /* default state */ + NPN_HTTP1_1, /* HTTP/1.1 negotiated */ + NPN_HTTP2 /* HTTP2 (draft-xx) negotiated */ +}; + /* * Request specific data in the easy handle (SessionHandle). Previously, * these members were on the connectdata struct but since a conn struct may @@ -660,6 +691,7 @@ struct SingleRequest { #define IDENTITY 0 /* No encoding */ #define DEFLATE 1 /* zlib deflate [RFC 1950 & 1951] */ #define GZIP 2 /* gzip algorithm [RFC 1952] */ +#define COMPRESS 3 /* Not handled, added for completeness */ #ifdef HAVE_LIBZ zlibInitState zlib_init; /* possible zlib init state; @@ -992,6 +1024,10 @@ struct connectdata { /*************** Request - specific items ************/ + /* previously this was in the urldata struct */ + curl_read_callback fread_func; /* function that reads the input */ + void *fread_in; /* pointer to pass to the fread() above */ + #if defined(USE_NTLM) struct ntlmdata ntlm; /* NTLM differs from other authentication schemes because it authenticates connections, not @@ -1059,7 +1095,7 @@ struct connectdata { } tunnel_state[2]; /* two separate ones to allow FTP */ struct connectbundle *bundle; /* The bundle we are member of */ - int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + enum negotiatenpn negnpn; }; /* The end of connectdata. */ @@ -1257,9 +1293,9 @@ struct UrlState { void *resolver; /* resolver state, if it is used in the URL state - ares_channel f.e. */ -#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) +#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) ENGINE *engine; -#endif /* USE_OPENSSL */ +#endif /* USE_SSLEAY */ struct timeval expiretime; /* set this with Curl_expire() only */ struct Curl_tree timenode; /* for the splay stuff */ struct curl_llist *timeoutlist; /* list of pending timeouts */ @@ -1305,13 +1341,6 @@ struct UrlState { curl_off_t infilesize; /* size of file to upload, -1 means unknown. Copied from set.filesize at start of operation */ - - int drain; /* Increased when this stream has data to read, even if its - socket not necessarily is readable. Decreased when - checked. */ - bool done; /* set to FALSE when Curl_do() is called and set to TRUE when - Curl_done() is called, to prevent Curl_done() to get invoked - twice when the multi interface is used. */ }; @@ -1392,8 +1421,6 @@ enum dupstring { #endif #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */ - STRING_PROXY_SERVICE_NAME, /* Proxy service name */ - STRING_SERVICE_NAME, /* Service name */ #endif STRING_MAIL_FROM, STRING_MAIL_AUTH, @@ -1426,8 +1453,8 @@ struct UserDefined { long proxyport; /* If non-zero, use this port number by default. If the proxy string features a ":[port]" that one will override this. */ - void *out; /* CURLOPT_WRITEDATA */ - void *in; /* CURLOPT_READDATA */ + void *out; /* the fetched file goes here */ + void *in; /* the uploaded file is read from here */ void *writeheader; /* write the header to this if non-NULL */ void *rtp_out; /* write RTP to this if non-NULL */ long use_port; /* which port to use (when not using default) */ @@ -1581,7 +1608,6 @@ struct UserDefined { bool connect_only; /* make connection, let application use the socket */ bool ssl_enable_beast; /* especially allow this flaw for interoperability's sake*/ - bool ssl_no_revoke; /* disable SSL certificate revocation checks */ long ssh_auth_types; /* allowed SSH auth types */ bool http_te_skip; /* pass the raw body data to the user, even when transfer-encoded (chunked, compressed) */ @@ -1623,9 +1649,7 @@ struct UserDefined { bool ssl_enable_npn; /* TLS NPN extension? */ bool ssl_enable_alpn; /* TLS ALPN extension? */ - bool path_as_is; /* allow dotdots? */ - bool pipewait; /* wait for pipe/multiplex status before starting a - new connection */ + long expect_100_timeout; /* in milliseconds */ }; diff --git a/lib/version.c b/lib/version.c index 1727c5a7d..9ac922665 100644 --- a/lib/version.c +++ b/lib/version.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,7 +26,9 @@ #include "urldata.h" #include "vtls/vtls.h" #include "http2.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include <curl/mprintf.h> #ifdef USE_ARES # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c index 1038432b9..1b577b152 100644 --- a/lib/vtls/axtls.c +++ b/lib/vtls/axtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>. - * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,7 +29,6 @@ #include "curl_setup.h" #ifdef USE_AXTLS -#include <axTLS/config.h> #include <axTLS/ssl.h> #include "axtls.h" @@ -39,13 +38,13 @@ #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: */ +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" +#include <unistd.h> +/* The last #include file should be: */ #include "memdebug.h" +#include "hostcheck.h" /* Global axTLS init, called from Curl_ssl_init() */ @@ -464,11 +463,9 @@ Curl_axtls_connect(struct connectdata *conn, int sockindex) { - struct SessionHandle *data = conn->data; CURLcode conn_step = connect_prep(conn, sockindex); int ssl_fcn_return; SSL *ssl = conn->ssl[sockindex].ssl; - long timeout_ms; if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); @@ -477,23 +474,14 @@ Curl_axtls_connect(struct connectdata *conn, /* 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 */ usleep(10000); + /* TODO: check for timeout as this could hang indefinitely otherwise */ } infof (conn->data, "handshake completed successfully\n"); @@ -527,6 +515,12 @@ static ssize_t axtls_send(struct connectdata *conn, return rc; } +void Curl_axtls_close_all(struct SessionHandle *data) +{ + (void)data; + infof(data, " Curl_axtls_close_all\n"); +} + void Curl_axtls_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -683,7 +677,7 @@ int Curl_axtls_random(struct SessionHandle *data, * race condition is that some global resources will leak. */ RNG_initialize(); } - get_random((int)length, entropy); + get_random(length, entropy); return 0; } diff --git a/lib/vtls/axtls.h b/lib/vtls/axtls.h index 223ecb8c9..62b4ab0e6 100644 --- a/lib/vtls/axtls.h +++ b/lib/vtls/axtls.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu@directv.com> - * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2010 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,10 @@ CURLcode Curl_axtls_connect_nonblocking( int sockindex, bool *done); +/* tell axTLS to close down all open information regarding connections (and + thus session ID caching etc) */ +void Curl_axtls_close_all(struct SessionHandle *data); + /* close a SSL connection */ void Curl_axtls_close(struct connectdata *conn, int sockindex); @@ -46,16 +50,13 @@ int Curl_axtls_random(struct SessionHandle *data, unsigned char *entropy, size_t length); -/* Set the API backend definition to axTLS */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS - /* API setup for axTLS */ #define curlssl_init Curl_axtls_init #define curlssl_cleanup Curl_axtls_cleanup #define curlssl_connect Curl_axtls_connect #define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking #define curlssl_session_free(x) Curl_axtls_session_free(x) -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_axtls_close_all #define curlssl_close Curl_axtls_close #define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y) #define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) @@ -65,6 +66,7 @@ int Curl_axtls_random(struct SessionHandle *data, #define curlssl_check_cxn(x) Curl_axtls_check_cxn(x) #define curlssl_data_pending(x,y) ((void)x, (void)y, 0) #define curlssl_random(x,y,z) Curl_axtls_random(x,y,z) +#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS #endif /* USE_AXTLS */ #endif /* HEADER_CURL_AXTLS_H */ diff --git a/lib/vtls/darwinssl.c b/lib/vtls/curl_darwinssl.c index 03adcef28..c056198bb 100644 --- a/lib/vtls/darwinssl.c +++ b/lib/vtls/curl_darwinssl.c @@ -102,8 +102,10 @@ #include "connect.h" #include "select.h" #include "vtls.h" -#include "darwinssl.h" -#include "curl_printf.h" +#include "curl_darwinssl.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -1459,12 +1461,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 /* We want to enable 1/n-1 when using a CBC cipher unless the user specifically doesn't want us doing that: */ - if(SSLSetSessionOption != NULL) { + if(SSLSetSessionOption != NULL) SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, !data->set.ssl_enable_beast); - SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, - data->set.ssl.falsestart); /* false start support */ - } #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ /* Check if there's a cached ID we can/should use here! */ @@ -2230,6 +2229,12 @@ void Curl_darwinssl_close(struct connectdata *conn, int sockindex) connssl->ssl_sockfd = 0; } +void Curl_darwinssl_close_all(struct SessionHandle *data) +{ + /* SecureTransport doesn't separate sessions from contexts, so... */ + (void)data; +} + int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2367,14 +2372,6 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); } -bool Curl_darwinssl_false_start(void) { -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - if(SSLSetSessionOption != NULL) - return TRUE; -#endif - return FALSE; -} - static ssize_t darwinssl_send(struct connectdata *conn, int sockindex, const void *mem, diff --git a/lib/vtls/darwinssl.h b/lib/vtls/curl_darwinssl.h index 3bb69c01a..7c80edfc6 100644 --- a/lib/vtls/darwinssl.h +++ b/lib/vtls/curl_darwinssl.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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 @@ -32,6 +32,9 @@ CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); +/* this function doesn't actually do anything */ +void Curl_darwinssl_close_all(struct SessionHandle *data); + /* close a SSL connection */ void Curl_darwinssl_close(struct connectdata *conn, int sockindex); @@ -48,10 +51,6 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len); -bool Curl_darwinssl_false_start(void); - -/* Set the API backend definition to SecureTransport */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL /* API setup for SecureTransport */ #define curlssl_init() (1) @@ -59,7 +58,7 @@ bool Curl_darwinssl_false_start(void); #define curlssl_connect Curl_darwinssl_connect #define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking #define curlssl_session_free(x) Curl_darwinssl_session_free(x) -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_darwinssl_close_all #define curlssl_close Curl_darwinssl_close #define curlssl_shutdown(x,y) 0 #define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) @@ -70,7 +69,7 @@ bool Curl_darwinssl_false_start(void); #define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y) #define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z)) #define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d) -#define curlssl_false_start() Curl_darwinssl_false_start() +#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL #endif /* USE_DARWINSSL */ #endif /* HEADER_CURL_DARWINSSL_H */ diff --git a/lib/vtls/schannel.c b/lib/vtls/curl_schannel.c index 2174e21a3..b3fe52695 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/curl_schannel.c @@ -5,9 +5,9 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Marc Hoersken, <info@marc-hoersken.de> + * Copyright (C) 2012 - 2014, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -38,6 +38,19 @@ * Thanks for code and inspiration! */ +/* + * TODO list for TLS/SSL implementation: + * - implement client certificate authentication + * - implement custom server certificate validation + * - implement cipher/algorithm option + * + * Related articles on MSDN: + * - Getting a Certificate for Schannel + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375447.aspx + * - Specifying Schannel Ciphers and Cipher Strengths + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx + */ + #include "curl_setup.h" #ifdef USE_SCHANNEL @@ -47,7 +60,7 @@ #endif #include "curl_sspi.h" -#include "schannel.h" +#include "curl_schannel.h" #include "vtls.h" #include "sendf.h" #include "connect.h" /* for the connect timeout */ @@ -56,7 +69,10 @@ #include "inet_pton.h" /* for IP addr SNI check */ #include "curl_multibyte.h" #include "warnless.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -105,7 +121,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) struct in6_addr addr6; #endif TCHAR *host_name; - CURLcode result; + CURLcode code; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", conn->host.name, conn->remote_port); @@ -125,64 +141,56 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) /* certificate validation on CE doesn't seem to work right; we'll do it following a more manual process. */ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | - SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; #else - schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - if(data->set.ssl_no_revoke) - schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; - else - schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | + SCH_CRED_REVOCATION_CHECK_CHAIN; #endif - if(data->set.ssl_no_revoke) - infof(data, "schannel: disabled server certificate revocation " - "checks\n"); - else - infof(data, "schannel: checking server certificate revocation\n"); + infof(data, "schannel: checking server certificate revocation\n"); } else { schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | - SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation checks\n"); + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + infof(data, "schannel: disable server certificate revocation checks\n"); } if(!data->set.ssl.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates. Also disables SNI.\n"); + "comparing the supplied target name with the subject " + "names in server certificates. Also disables SNI.\n"); } switch(data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | - SP_PROT_TLS1_1_CLIENT | - SP_PROT_TLS1_2_CLIENT; - break; - case CURL_SSLVERSION_TLSv1_0: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; - break; - case CURL_SSLVERSION_TLSv1_1: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; - break; - case CURL_SSLVERSION_TLSv1_2: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; - break; - case CURL_SSLVERSION_SSLv3: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; - break; - case CURL_SSLVERSION_SSLv2: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; - break; + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | + SP_PROT_TLS1_1_CLIENT | + SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_0: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_SSLv3: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; + break; + case CURL_SSLVERSION_SSLv2: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; + break; } /* allocate memory for the re-usable credential handle */ connssl->cred = (struct curl_schannel_cred *) - malloc(sizeof(struct curl_schannel_cred)); + malloc(sizeof(struct curl_schannel_cred)); if(!connssl->cred) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; @@ -190,12 +198,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) memset(connssl->cred, 0, sizeof(struct curl_schannel_cred)); /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */ - sspi_status = - s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, - SECPKG_CRED_OUTBOUND, NULL, - &schannel_cred, NULL, NULL, - &connssl->cred->cred_handle, - &connssl->cred->time_stamp); + sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, + SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL, + &connssl->cred->cred_handle, &connssl->cred->time_stamp); if(sspi_status != SEC_E_OK) { if(sspi_status == SEC_E_WRONG_PRINCIPAL) @@ -224,12 +229,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) /* setup request flags */ connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_STREAM; + ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_STREAM; /* allocate memory for the security context handle */ connssl->ctxt = (struct curl_schannel_ctxt *) - malloc(sizeof(struct curl_schannel_ctxt)); + malloc(sizeof(struct curl_schannel_ctxt)); if(!connssl->ctxt) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; @@ -264,10 +269,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) "sending %lu bytes...\n", outbuf.cbBuffer); /* send initial handshake data which is now stored in output buffer */ - result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, - outbuf.cbBuffer, &written); + code = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); - if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + if((code != CURLE_OK) || (outbuf.cbBuffer != (size_t)written)) { failf(data, "schannel: failed to send initial handshake data: " "sent %zd of %lu bytes", written, outbuf.cbBuffer); return CURLE_SSL_CONNECT_ERROR; @@ -276,10 +281,6 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) infof(data, "schannel: sent initial handshake data: " "sent %zd bytes\n", written); - connssl->recv_unrecoverable_err = CURLE_OK; - connssl->recv_sspi_close_notify = false; - connssl->recv_connection_closed = false; - /* continue to second handshake step */ connssl->connecting_state = ssl_connect_2; @@ -295,13 +296,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; unsigned char *reallocated_buffer; size_t reallocated_length; - SecBuffer outbuf[3]; + SecBuffer outbuf[2]; SecBufferDesc outbuf_desc; SecBuffer inbuf[2]; SecBufferDesc inbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; TCHAR *host_name; - CURLcode result; + CURLcode code; bool doread; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; @@ -312,17 +313,6 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(!connssl->cred || !connssl->ctxt) return CURLE_SSL_CONNECT_ERROR; - /* buffer to store previously received and decrypted data */ - if(connssl->decdata_buffer == NULL) { - connssl->decdata_offset = 0; - connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; - connssl->decdata_buffer = malloc(connssl->decdata_length); - if(connssl->decdata_buffer == NULL) { - failf(data, "schannel: unable to allocate memory"); - return CURLE_OUT_OF_MEMORY; - } - } - /* buffer to store previously received and encrypted data */ if(connssl->encdata_buffer == NULL) { connssl->encdata_offset = 0; @@ -339,7 +329,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) CURL_SCHANNEL_BUFFER_FREE_SIZE) { /* increase internal encrypted data buffer */ reallocated_length = connssl->encdata_offset + - CURL_SCHANNEL_BUFFER_FREE_SIZE; + CURL_SCHANNEL_BUFFER_FREE_SIZE; reallocated_buffer = realloc(connssl->encdata_buffer, reallocated_length); @@ -356,20 +346,18 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) for(;;) { if(doread) { /* read encrypted handshake data from socket */ - result = Curl_read_plain(conn->sock[sockindex], - (char *) (connssl->encdata_buffer + - connssl->encdata_offset), - connssl->encdata_length - - connssl->encdata_offset, - &nread); - if(result == CURLE_AGAIN) { + code = Curl_read_plain(conn->sock[sockindex], + (char *) (connssl->encdata_buffer + connssl->encdata_offset), + connssl->encdata_length - connssl->encdata_offset, + &nread); + if(code == CURLE_AGAIN) { if(connssl->connecting_state != ssl_connect_2_writing) connssl->connecting_state = ssl_connect_2_reading; infof(data, "schannel: failed to receive handshake, " "need more data\n"); return CURLE_OK; } - else if((result != CURLE_OK) || (nread == 0)) { + else if((code != CURLE_OK) || (nread == 0)) { failf(data, "schannel: failed to receive handshake, " "SSL/TLS connection failed"); return CURLE_SSL_CONNECT_ERROR; @@ -380,7 +368,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) } infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - connssl->encdata_offset, connssl->encdata_length); + connssl->encdata_offset, connssl->encdata_length); /* setup input buffers */ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset), @@ -391,8 +379,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* setup output buffers */ InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); - InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); - InitSecBufferDesc(&outbuf_desc, outbuf, 3); + InitSecBufferDesc(&outbuf_desc, outbuf, 2); if(inbuf[0].pvBuffer == NULL) { failf(data, "schannel: unable to allocate memory"); @@ -426,31 +413,19 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) return CURLE_OK; } - /* If the server has requested a client certificate, attempt to continue - the handshake without one. This will allow connections to servers which - request a client certificate but do not require it. */ - if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && - !(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { - connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; - connssl->connecting_state = ssl_connect_2_writing; - infof(data, "schannel: a client certificate has been requested\n"); - return CURLE_OK; - } - /* check if the handshake needs to be continued */ if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { - for(i = 0; i < 3; i++) { + for(i = 0; i < 2; i++) { /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { infof(data, "schannel: sending next handshake data: " "sending %lu bytes...\n", outbuf[i].cbBuffer); /* send handshake token to server */ - result = Curl_write_plain(conn, conn->sock[sockindex], - outbuf[i].pvBuffer, outbuf[i].cbBuffer, - &written); - if((result != CURLE_OK) || - (outbuf[i].cbBuffer != (size_t) written)) { + code = Curl_write_plain(conn, conn->sock[sockindex], + outbuf[i].pvBuffer, outbuf[i].cbBuffer, + &written); + if((code != CURLE_OK) || (outbuf[i].cbBuffer != (size_t)written)) { failf(data, "schannel: failed to send next handshake data: " "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); return CURLE_SSL_CONNECT_ERROR; @@ -477,21 +452,21 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); /* - There are two cases where we could be getting extra data here: - 1) If we're renegotiating a connection and the handshake is already - complete (from the server perspective), it can encrypted app data - (not handshake data) in an extra buffer at this point. - 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a - connection and this extra data is part of the handshake. - We should process the data immediately; waiting for the socket to - be ready may fail since the server is done sending handshake data. - */ + There are two cases where we could be getting extra data here: + 1) If we're renegotiating a connection and the handshake is already + complete (from the server perspective), it can encrypted app data + (not handshake data) in an extra buffer at this point. + 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a + connection and this extra data is part of the handshake. + We should process the data immediately; waiting for the socket to + be ready may fail since the server is done sending handshake data. + */ /* check if the remaining data is less than the total amount and therefore begins after the already processed data */ if(connssl->encdata_offset > inbuf[1].cbBuffer) { memmove(connssl->encdata_buffer, (connssl->encdata_buffer + connssl->encdata_offset) - - inbuf[1].cbBuffer, inbuf[1].cbBuffer); + inbuf[1].cbBuffer, inbuf[1].cbBuffer); connssl->encdata_offset = inbuf[1].cbBuffer; if(sspi_status == SEC_I_CONTINUE_NEEDED) { doread = FALSE; @@ -716,14 +691,14 @@ schannel_send(struct connectdata *conn, int sockindex, SecBuffer outbuf[4]; SecBufferDesc outbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; - CURLcode result; + CURLcode code; /* check if the maximum stream sizes were queried */ if(connssl->stream_sizes.cbMaximumMessage == 0) { sspi_status = s_pSecFn->QueryContextAttributes( - &connssl->ctxt->ctxt_handle, - SECPKG_ATTR_STREAM_SIZES, - &connssl->stream_sizes); + &connssl->ctxt->ctxt_handle, + SECPKG_ATTR_STREAM_SIZES, + &connssl->stream_sizes); if(sspi_status != SEC_E_OK) { *err = CURLE_SEND_ERROR; return -1; @@ -738,7 +713,7 @@ schannel_send(struct connectdata *conn, int sockindex, /* calculate the complete message length and allocate a buffer for it */ data_len = connssl->stream_sizes.cbHeader + len + - connssl->stream_sizes.cbTrailer; + connssl->stream_sizes.cbTrailer; data = (unsigned char *) malloc(data_len); if(data == NULL) { *err = CURLE_OUT_OF_MEMORY; @@ -771,19 +746,19 @@ schannel_send(struct connectdata *conn, int sockindex, len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; /* - It's important to send the full message which includes the header, - encrypted payload, and trailer. Until the client receives all the - data a coherent message has not been delivered and the client - can't read any of it. - - If we wanted to buffer the unwritten encrypted bytes, we would - tell the client that all data it has requested to be sent has been - sent. The unwritten encrypted bytes would be the first bytes to - send on the next invocation. - Here's the catch with this - if we tell the client that all the - bytes have been sent, will the client call this method again to - send the buffered data? Looking at who calls this function, it - seems the answer is NO. + It's important to send the full message which includes the header, + encrypted payload, and trailer. Until the client receives all the + data a coherent message has not been delivered and the client + can't read any of it. + + If we wanted to buffer the unwritten encrypted bytes, we would + tell the client that all data it has requested to be sent has been + sent. The unwritten encrypted bytes would be the first bytes to + send on the next invocation. + Here's the catch with this - if we tell the client that all the + bytes have been sent, will the client call this method again to + send the buffered data? Looking at who calls this function, it + seems the answer is NO. */ /* send entire message or fail */ @@ -822,12 +797,12 @@ schannel_send(struct connectdata *conn, int sockindex, } /* socket is writable */ - result = Curl_write_plain(conn, conn->sock[sockindex], data + written, - len - written, &this_write); - if(result == CURLE_AGAIN) + code = Curl_write_plain(conn, conn->sock[sockindex], data + written, + len - written, &this_write); + if(code == CURLE_AGAIN) continue; - else if(result != CURLE_OK) { - *err = result; + else if(code != CURLE_OK) { + *err = code; written = -1; break; } @@ -857,7 +832,8 @@ schannel_recv(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err) { size_t size = 0; - ssize_t nread = -1; + ssize_t nread = 0, ret = -1; + CURLcode result; struct SessionHandle *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; unsigned char *reallocated_buffer; @@ -866,103 +842,72 @@ schannel_recv(struct connectdata *conn, int sockindex, SecBuffer inbuf[4]; SecBufferDesc inbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; - /* we want the length of the encrypted buffer to be at least large enough - that it can hold all the bytes requested and some TLS record overhead. */ - size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; - - /**************************************************************************** - * Don't return or set connssl->recv_unrecoverable_err unless in the cleanup. - * The pattern for return error is set *err, optional infof, goto cleanup. - * - * Our priority is to always return as much decrypted data to the caller as - * possible, even if an error occurs. The state of the decrypted buffer must - * always be valid. Transfer of decrypted data to the caller's buffer is - * handled in the cleanup. - */ infof(data, "schannel: client wants to read %zu bytes\n", len); *err = CURLE_OK; - if(len && len <= connssl->decdata_offset) { - infof(data, "schannel: enough decrypted data is already available\n"); - goto cleanup; - } - else if(connssl->recv_unrecoverable_err) { - *err = connssl->recv_unrecoverable_err; - infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); - goto cleanup; - } - else if(connssl->recv_sspi_close_notify) { - /* once a server has indicated shutdown there is no more encrypted data */ - infof(data, "schannel: server indicated shutdown in a prior call\n"); - goto cleanup; - } - else if(!len) { - /* It's debatable what to return when !len. Regardless we can't return - immediately because there may be data to decrypt (in the case we want to - decrypt all encrypted cached data) so handle !len later in cleanup. - */ - ; /* do nothing */ + /* buffer to store previously received and decrypted data */ + if(connssl->decdata_buffer == NULL) { + connssl->decdata_offset = 0; + connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + connssl->decdata_buffer = malloc(connssl->decdata_length); + if(connssl->decdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + *err = CURLE_OUT_OF_MEMORY; + return -1; + } } - else if(!connssl->recv_connection_closed) { - /* increase enc buffer in order to fit the requested amount of data */ - size = connssl->encdata_length - connssl->encdata_offset; - if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || - connssl->encdata_length < min_encdata_length) { - reallocated_length = connssl->encdata_offset + - CURL_SCHANNEL_BUFFER_FREE_SIZE; - if(reallocated_length < min_encdata_length) { - reallocated_length = min_encdata_length; - } - reallocated_buffer = realloc(connssl->encdata_buffer, - reallocated_length); - if(reallocated_buffer == NULL) { - *err = CURLE_OUT_OF_MEMORY; - failf(data, "schannel: unable to re-allocate memory"); - goto cleanup; - } + /* increase buffer in order to fit the requested amount of data */ + if(connssl->encdata_length - connssl->encdata_offset < + CURL_SCHANNEL_BUFFER_FREE_SIZE || connssl->encdata_length < len) { + /* increase internal encrypted data buffer */ + reallocated_length = connssl->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + /* make sure that the requested amount of data fits */ + if(reallocated_length < len) { + reallocated_length = len; + } + reallocated_buffer = realloc(connssl->encdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + else { connssl->encdata_buffer = reallocated_buffer; connssl->encdata_length = reallocated_length; - size = connssl->encdata_length - connssl->encdata_offset; - infof(data, "schannel: encdata_buffer resized %zu\n", - connssl->encdata_length); } + } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - connssl->encdata_offset, connssl->encdata_length); - - /* read encrypted data from socket */ + /* read encrypted data from socket */ + infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", + connssl->encdata_offset, connssl->encdata_length); + size = connssl->encdata_length - connssl->encdata_offset; + if(size > 0) { *err = Curl_read_plain(conn->sock[sockindex], - (char *)(connssl->encdata_buffer + - connssl->encdata_offset), + (char *) (connssl->encdata_buffer + connssl->encdata_offset), size, &nread); - if(*err) { - nread = -1; - if(*err == CURLE_AGAIN) - infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n"); - else if(*err == CURLE_RECV_ERROR) - infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); - else - infof(data, "schannel: Curl_read_plain returned error %d\n", *err); - } - else if(nread == 0) { - connssl->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); - } - else if(nread > 0) { - connssl->encdata_offset += (size_t)nread; - infof(data, "schannel: encrypted data got %zd\n", nread); + /* check for received data */ + if(*err != CURLE_OK) + ret = -1; + else { + if(nread > 0) + /* increase encrypted data buffer offset */ + connssl->encdata_offset += nread; + ret = nread; } + infof(data, "schannel: encrypted data got %zd\n", ret); } infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", connssl->encdata_offset, connssl->encdata_length); - /* decrypt loop */ + /* check if we still have some data in our buffers */ while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK && - (!len || connssl->decdata_offset < len || - connssl->recv_connection_closed)) { + connssl->decdata_offset < len) { /* prepare data buffer for DecryptMessage call */ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer, curlx_uztoul(connssl->encdata_offset)); @@ -971,16 +916,24 @@ schannel_recv(struct connectdata *conn, int sockindex, InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 4); /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx */ sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle, &inbuf_desc, 0, NULL); + /* check if we need more data */ + if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + infof(data, "schannel: failed to decrypt data, need more data\n"); + *err = CURLE_AGAIN; + return -1; + } + /* check if everything went fine (server may want to renegotiate or shutdown the connection context) */ if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || - sspi_status == SEC_I_CONTEXT_EXPIRED) { + sspi_status == SEC_I_CONTEXT_EXPIRED) { /* check for successfully decrypted data, even before actual renegotiation or shutdown of the connection context */ if(inbuf[1].BufferType == SECBUFFER_DATA) { @@ -1000,18 +953,21 @@ schannel_recv(struct connectdata *conn, int sockindex, } reallocated_buffer = realloc(connssl->decdata_buffer, reallocated_length); + if(reallocated_buffer == NULL) { - *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); - goto cleanup; + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + else { + connssl->decdata_buffer = reallocated_buffer; + connssl->decdata_length = reallocated_length; } - connssl->decdata_buffer = reallocated_buffer; - connssl->decdata_length = reallocated_length; } /* copy decrypted data to internal buffer */ size = inbuf[1].cbBuffer; - if(size) { + if(size > 0) { memcpy(connssl->decdata_buffer + connssl->decdata_offset, inbuf[1].pvBuffer, size); connssl->decdata_offset += size; @@ -1029,151 +985,83 @@ schannel_recv(struct connectdata *conn, int sockindex, /* check if the remaining data is less than the total amount * and therefore begins after the already processed data - */ + */ if(connssl->encdata_offset > inbuf[3].cbBuffer) { /* move remaining encrypted data forward to the beginning of buffer */ memmove(connssl->encdata_buffer, (connssl->encdata_buffer + connssl->encdata_offset) - - inbuf[3].cbBuffer, inbuf[3].cbBuffer); + inbuf[3].cbBuffer, inbuf[3].cbBuffer); connssl->encdata_offset = inbuf[3].cbBuffer; } infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", connssl->encdata_offset, connssl->encdata_length); } - else { + else{ /* reset encrypted buffer offset, because there is no data remaining */ connssl->encdata_offset = 0; } + } - /* check if server wants to renegotiate the connection context */ - if(sspi_status == SEC_I_RENEGOTIATE) { - infof(data, "schannel: remote party requests renegotiation\n"); - if(*err && *err != CURLE_AGAIN) { - infof(data, "schannel: can't renogotiate, an error is pending\n"); - goto cleanup; - } - if(connssl->encdata_offset) { - *err = CURLE_RECV_ERROR; - infof(data, "schannel: can't renogotiate, " - "encrypted data available\n"); - goto cleanup; - } - /* begin renegotiation */ - infof(data, "schannel: renegotiating SSL/TLS connection\n"); - connssl->state = ssl_connection_negotiating; - connssl->connecting_state = ssl_connect_2_writing; - *err = schannel_connect_common(conn, sockindex, FALSE, &done); - if(*err) { - infof(data, "schannel: renegotiation failed\n"); - goto cleanup; - } - /* now retry receiving data */ - sspi_status = SEC_E_OK; + /* check if server wants to renegotiate the connection context */ + if(sspi_status == SEC_I_RENEGOTIATE) { + infof(data, "schannel: remote party requests SSL/TLS renegotiation\n"); + + /* begin renegotiation */ + infof(data, "schannel: renegotiating SSL/TLS connection\n"); + connssl->state = ssl_connection_negotiating; + connssl->connecting_state = ssl_connect_2_writing; + result = schannel_connect_common(conn, sockindex, FALSE, &done); + if(result) + *err = result; + else { infof(data, "schannel: SSL/TLS connection renegotiated\n"); - continue; - } - /* check if the server closed the connection */ - else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { - /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not - returned so we have to work around that in cleanup. */ - connssl->recv_sspi_close_notify = true; - if(!connssl->recv_connection_closed) { - connssl->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); - } - goto cleanup; + /* now retry receiving data */ + return schannel_recv(conn, sockindex, buf, len, err); } } - else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { - if(!*err) - *err = CURLE_AGAIN; - infof(data, "schannel: failed to decrypt data, need more data\n"); - goto cleanup; - } - else { - *err = CURLE_RECV_ERROR; - infof(data, "schannel: failed to read data from server: %s\n", - Curl_sspi_strerror(conn, sspi_status)); - goto cleanup; - } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - connssl->encdata_offset, connssl->encdata_length); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", connssl->decdata_offset, connssl->decdata_length); -cleanup: - /* Warning- there is no guarantee the encdata state is valid at this point */ - infof(data, "schannel: schannel_recv cleanup\n"); - - /* Error if the connection has closed without a close_notify. - Behavior here is a matter of debate. We don't want to be vulnerable to a - truncation attack however there's some browser precedent for ignoring the - close_notify for compatibility reasons. - Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't - return close_notify. In that case if the connection was closed we assume it - was graceful (close_notify) since there doesn't seem to be a way to tell. - */ - if(len && !connssl->decdata_offset && connssl->recv_connection_closed && - !connssl->recv_sspi_close_notify) { - BOOL isWin2k; - ULONGLONG cm; - OSVERSIONINFOEX osver; - - memset(&osver, 0, sizeof(osver)); - osver.dwOSVersionInfoSize = sizeof(osver); - osver.dwMajorVersion = 5; - - cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); - - isWin2k = VerifyVersionInfo(&osver, - (VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), - cm); - - if(isWin2k && sspi_status == SEC_E_OK) - connssl->recv_sspi_close_notify = true; - else { - *err = CURLE_RECV_ERROR; - infof(data, "schannel: server closed abruptly (missing close_notify)\n"); - } - } - - /* Any error other than CURLE_AGAIN is an unrecoverable error. */ - if(*err && *err != CURLE_AGAIN) - connssl->recv_unrecoverable_err = *err; - + /* copy requested decrypted data to supplied buffer */ size = len < connssl->decdata_offset ? len : connssl->decdata_offset; - if(size) { + if(size > 0) { memcpy(buf, connssl->decdata_buffer, size); + ret = size; + + /* move remaining decrypted data forward to the beginning of buffer */ memmove(connssl->decdata_buffer, connssl->decdata_buffer + size, connssl->decdata_offset - size); connssl->decdata_offset -= size; - infof(data, "schannel: decrypted data returned %zu\n", size); + infof(data, "schannel: decrypted data returned %zd\n", size); infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", connssl->decdata_offset, connssl->decdata_length); - *err = CURLE_OK; - return (ssize_t)size; } + else + ret = 0; - if(!*err && !connssl->recv_connection_closed) - *err = CURLE_AGAIN; - - /* It's debatable what to return when !len. We could return whatever error we - got from decryption but instead we override here so the return is consistent. - */ - if(!len) + /* check if the server closed the connection */ + if(ret <= 0 && ( /* special check for Windows 2000 Professional */ + sspi_status == SEC_I_CONTEXT_EXPIRED || (sspi_status == SEC_E_OK && + connssl->encdata_offset > 0 && connssl->encdata_buffer[0] == 0x15))) { + infof(data, "schannel: server closed the connection\n"); *err = CURLE_OK; + return 0; + } - return *err ? -1 : 0; + /* check if something went wrong and we need to return an error */ + if(ret < 0 && sspi_status != SEC_E_OK) { + infof(data, "schannel: failed to read data from server: %s\n", + Curl_sspi_strerror(conn, sspi_status)); + *err = CURLE_RECV_ERROR; + return -1; + } + + return ret; } CURLcode @@ -1233,7 +1121,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) SECURITY_STATUS sspi_status; SecBuffer outbuf; SecBufferDesc outbuf_desc; - CURLcode result; + CURLcode code; TCHAR *host_name; DWORD dwshut = SCHANNEL_SHUTDOWN; @@ -1256,31 +1144,31 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) InitSecBufferDesc(&outbuf_desc, &outbuf, 1); sspi_status = s_pSecFn->InitializeSecurityContext( - &connssl->cred->cred_handle, - &connssl->ctxt->ctxt_handle, - host_name, - connssl->req_flags, - 0, - 0, - NULL, - 0, - &connssl->ctxt->ctxt_handle, - &outbuf_desc, - &connssl->ret_flags, - &connssl->ctxt->time_stamp); + &connssl->cred->cred_handle, + &connssl->ctxt->ctxt_handle, + host_name, + connssl->req_flags, + 0, + 0, + NULL, + 0, + &connssl->ctxt->ctxt_handle, + &outbuf_desc, + &connssl->ret_flags, + &connssl->ctxt->time_stamp); Curl_unicodefree(host_name); if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { /* send close message which is in output buffer */ ssize_t written; - result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, - outbuf.cbBuffer, &written); + code = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); - if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + if((code != CURLE_OK) || (outbuf.cbBuffer != (size_t)written)) { infof(data, "schannel: failed to send close msg: %s" - " (bytes written: %zd)\n", curl_easy_strerror(result), written); + " (bytes written: %zd)\n", curl_easy_strerror(code), written); } } } @@ -1330,14 +1218,9 @@ void Curl_schannel_session_free(void *ptr) { struct curl_schannel_cred *cred = ptr; - if(cred && cred->cached) { - if(cred->refcount == 0) { - s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); - Curl_safefree(cred); - } - else { - cred->cached = FALSE; - } + if(cred && cred->cached && cred->refcount == 0) { + s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); + Curl_safefree(cred); } } @@ -1405,8 +1288,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) NULL, pCertContextServer->hCertStore, &ChainPara, - (data->set.ssl_no_revoke ? 0 : - CERT_CHAIN_REVOCATION_CHECK_CHAIN), + 0, NULL, &pChainContext)) { failf(data, "schannel: CertGetCertificateChain failed: %s", @@ -1417,24 +1299,21 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) if(result == CURLE_OK) { CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; - DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED); + DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED| + CERT_TRUST_REVOCATION_STATUS_UNKNOWN); dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; if(dwTrustErrorMask) { - if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED) - failf(data, "schannel: CertGetCertificateChain trust error" - " CERT_TRUST_IS_REVOKED"); - else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) + if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) failf(data, "schannel: CertGetCertificateChain trust error" - " CERT_TRUST_IS_PARTIAL_CHAIN"); - else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) + " CERT_TRUST_IS_PARTIAL_CHAIN"); + if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) failf(data, "schannel: CertGetCertificateChain trust error" - " CERT_TRUST_IS_UNTRUSTED_ROOT"); - else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) + " CERT_TRUST_IS_UNTRUSTED_ROOT"); + if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) failf(data, "schannel: CertGetCertificateChain trust error" - " CERT_TRUST_IS_NOT_TIME_VALID"); - else - failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", - dwTrustErrorMask); + " CERT_TRUST_IS_NOT_TIME_VALID"); + failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", + dwTrustErrorMask); result = CURLE_PEER_FAILED_VERIFICATION; } } @@ -1450,14 +1329,6 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) cert_hostname.const_tchar_ptr = cert_hostname_buff; hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name); - /* TODO: Fix this for certificates with multiple alternative names. - Right now we're only asking for the first preferred alternative name. - Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG - (if WinCE supports that?) and run this section in a loop for each. - https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx - curl: (51) schannel: CertGetNameString() certificate hostname - (.google.com) did not match connection (google.com) - */ len = CertGetNameString(pCertContextServer, CERT_NAME_DNS_TYPE, 0, diff --git a/lib/vtls/schannel.h b/lib/vtls/curl_schannel.h index 532958483..11e83f9e5 100644 --- a/lib/vtls/schannel.h +++ b/lib/vtls/curl_schannel.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al. - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, 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 @@ -72,7 +72,6 @@ #define SECBUFFER_ALERT 17 #endif -/* Both schannel buffer sizes must be > 0 */ #define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 #define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 @@ -94,9 +93,6 @@ size_t Curl_schannel_version(char *buffer, size_t size); int Curl_schannel_random(unsigned char *entropy, size_t length); -/* Set the API backend definition to Schannel */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL - /* API setup for Schannel */ #define curlssl_init Curl_schannel_init #define curlssl_cleanup Curl_schannel_cleanup @@ -112,6 +108,7 @@ int Curl_schannel_random(unsigned char *entropy, size_t length); #define curlssl_version Curl_schannel_version #define curlssl_check_cxn(x) ((void)x, -1) #define curlssl_data_pending Curl_schannel_data_pending +#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL #define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z)) #endif /* USE_SCHANNEL */ diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c index 3ded7f11d..3333fc3a0 100644 --- a/lib/vtls/cyassl.c +++ b/lib/vtls/cyassl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,20 +30,6 @@ #ifdef USE_CYASSL -#define WOLFSSL_OPTIONS_IGNORE_SYS -/* CyaSSL's version.h, which should contain only the version, should come -before all other CyaSSL includes and be immediately followed by build config -aka options.h. http://curl.haxx.se/mail/lib-2015-04/0069.html */ -#include <cyassl/version.h> -#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008) -#if defined(CYASSL_API) || defined(WOLFSSL_API) -/* Safety measure. If either is defined some API include was already included -and that's a problem since options.h hasn't been included yet. */ -#error "CyaSSL API was included before the CyaSSL build options." -#endif -#include <cyassl/options.h> -#endif - #ifdef HAVE_LIMITS_H #include <limits.h> #endif @@ -57,8 +43,10 @@ and that's a problem since options.h hasn't been included yet. */ #include "connect.h" /* for the connect timeout */ #include "select.h" #include "rawstr.h" -#include "x509asn1.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> +#include "curl_memory.h" #include <cyassl/ssl.h> #ifdef HAVE_CYASSL_ERROR_SSL_H @@ -67,16 +55,10 @@ and that's a problem since options.h hasn't been included yet. */ #include <cyassl/error.h> #endif #include <cyassl/ctaocrypt/random.h> -#include <cyassl/ctaocrypt/sha256.h> -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" -#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */ -#define CYASSL_MAX_ERROR_SZ 80 -#endif - static Curl_recv cyassl_recv; static Curl_send cyassl_send; @@ -100,58 +82,42 @@ static CURLcode cyassl_connect_step1(struct connectdata *conn, int sockindex) { - char error_buffer[CYASSL_MAX_ERROR_SZ]; struct SessionHandle *data = conn->data; struct ssl_connect_data* conssl = &conn->ssl[sockindex]; SSL_METHOD* req_method = NULL; void* ssl_sessionid = NULL; curl_socket_t sockfd = conn->sock[sockindex]; -#ifdef HAVE_SNI - bool sni = FALSE; -#define use_sni(x) sni = (x) -#else -#define use_sni(x) Curl_nop_stmt -#endif if(conssl->state == ssl_connection_complete) return CURLE_OK; + /* CyaSSL doesn't support SSLv2 */ + if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + failf(data, "CyaSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + /* check to see if we've been told to use an explicit SSL/TLS version */ switch(data->set.ssl.version) { + default: case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: -#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ - /* minimum protocol version is set later after the CTX object is created */ - req_method = SSLv23_client_method(); -#else - infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " + infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, " "TLS 1.0 is used exclusively\n"); req_method = TLSv1_client_method(); -#endif - use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_0: req_method = TLSv1_client_method(); - use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_1: req_method = TLSv1_1_client_method(); - use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_2: req_method = TLSv1_2_client_method(); - use_sni(TRUE); break; case CURL_SSLVERSION_SSLv3: req_method = SSLv3_client_method(); - use_sni(FALSE); break; - case CURL_SSLVERSION_SSLv2: - failf(data, "CyaSSL does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; } if(!req_method) { @@ -168,36 +134,15 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } - switch(data->set.ssl.version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: -#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ - /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever - minimum version of TLS was built in and at least TLS 1.0. For later library - versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so - we have this short circuit evaluation to find the minimum supported TLS - version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion - because only the former will work before the user's CTX callback is called. - */ - if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) && - (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) && - (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) { - failf(data, "SSL: couldn't set the minimum protocol version"); - return CURLE_SSL_CONNECT_ERROR; - } -#endif - break; - } - #ifndef NO_FILESYSTEM /* load trusted cacert */ if(data->set.str[STRING_SSL_CAFILE]) { - if(1 != SSL_CTX_load_verify_locations(conssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { + if(!SSL_CTX_load_verify_locations(conssl->ctx, + data->set.str[STRING_SSL_CAFILE], + data->set.str[STRING_SSL_CAPATH])) { if(data->set.ssl.verifypeer) { /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate verify locations:\n" + failf(data,"error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", data->set.str[STRING_SSL_CAFILE]? data->set.str[STRING_SSL_CAFILE]: "none", @@ -243,7 +188,11 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } } -#endif /* !NO_FILESYSTEM */ +#else + if(CyaSSL_no_filesystem_verify(conssl->ctx)!= SSL_SUCCESS) { + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* NO_FILESYSTEM */ /* 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 @@ -253,46 +202,6 @@ cyassl_connect_step1(struct connectdata *conn, data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, NULL); -#ifdef HAVE_SNI - if(sni) { - struct in_addr addr4; -#ifdef ENABLE_IPV6 - struct in6_addr addr6; -#endif - size_t hostname_len = strlen(conn->host.name); - if((hostname_len < USHRT_MAX) && - (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) && -#ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) && -#endif - (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name, - (unsigned short)hostname_len) != 1)) { - infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); - } - } -#endif - - /* give application a chance to interfere with SSL set up. */ - if(data->set.ssl.fsslctx) { - CURLcode result = CURLE_OK; - result = (*data->set.ssl.fsslctx)(data, conssl->ctx, - data->set.ssl.fsslctxp); - if(result) { - failf(data, "error signaled by ssl ctx callback"); - return result; - } - } -#ifdef NO_FILESYSTEM - else if(data->set.ssl.verifypeer) { - failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" - " with \"no filesystem\". Either disable peer verification" - " (insecure) or if you are building an application with libcurl you" - " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); - return CURLE_SSL_CONNECT_ERROR; - } -#endif - /* Let's make an SSL structure */ if(conssl->handle) SSL_free(conssl->handle); @@ -307,7 +216,7 @@ cyassl_connect_step1(struct connectdata *conn, /* we got a session id, use it! */ if(!SSL_set_session(conssl->handle, ssl_sessionid)) { failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(SSL_get_error(conssl->handle, 0), error_buffer)); + ERR_error_string(SSL_get_error(conssl->handle, 0),NULL)); return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ @@ -333,6 +242,9 @@ cyassl_connect_step2(struct connectdata *conn, struct SessionHandle *data = conn->data; struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + infof(data, "CyaSSL: Connecting to %s:%d\n", + conn->host.name, conn->remote_port); + conn->recv[sockindex] = cyassl_recv; conn->send[sockindex] = cyassl_send; @@ -345,7 +257,7 @@ cyassl_connect_step2(struct connectdata *conn, ret = SSL_connect(conssl->handle); if(ret != 1) { - char error_buffer[CYASSL_MAX_ERROR_SZ]; + char error_buffer[80]; int detail = SSL_get_error(conssl->handle, ret); if(SSL_ERROR_WANT_READ == detail) { @@ -405,44 +317,6 @@ cyassl_connect_step2(struct connectdata *conn, } } - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { - X509 *x509; - const char *x509_der; - int x509_der_len; - curl_X509certificate x509_parsed; - curl_asn1Element *pubkey; - CURLcode result; - - x509 = SSL_get_peer_certificate(conssl->handle); - if(!x509) { - failf(data, "SSL: failed retrieving server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; - } - - x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len); - if(!x509_der) { - failf(data, "SSL: failed retrieving ASN.1 server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; - } - - memset(&x509_parsed, 0, sizeof x509_parsed); - Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len); - - pubkey = &x509_parsed.subjectPublicKeyInfo; - if(!pubkey->header || pubkey->end <= pubkey->header) { - failf(data, "SSL: failed retrieving public key from server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; - } - - result = Curl_pin_peer_pubkey(data->set.str[STRING_SSL_PINNEDPUBLICKEY], - (const unsigned char *)pubkey->header, - (size_t)(pubkey->end - pubkey->header)); - if(result) { - failf(data, "SSL: public key does not match pinned public key!"); - return result; - } - } - conssl->connecting_state = ssl_connect_3; infof(data, "SSL connected\n"); @@ -495,7 +369,7 @@ static ssize_t cyassl_send(struct connectdata *conn, size_t len, CURLcode *curlcode) { - char error_buffer[CYASSL_MAX_ERROR_SZ]; + char error_buffer[80]; int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); @@ -519,6 +393,11 @@ static ssize_t cyassl_send(struct connectdata *conn, return rc; } +void Curl_cyassl_close_all(struct SessionHandle *data) +{ + (void)data; +} + void Curl_cyassl_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *conssl = &conn->ssl[sockindex]; @@ -540,7 +419,7 @@ static ssize_t cyassl_recv(struct connectdata *conn, size_t buffersize, CURLcode *curlcode) { - char error_buffer[CYASSL_MAX_ERROR_SZ]; + char error_buffer[80]; int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; int nread = SSL_read(conn->ssl[num].handle, buf, buffsize); @@ -576,9 +455,7 @@ void Curl_cyassl_session_free(void *ptr) size_t Curl_cyassl_version(char *buffer, size_t size) { -#ifdef WOLFSSL_VERSION - return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); -#elif defined(CYASSL_VERSION) +#ifdef CYASSL_VERSION return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); #else return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); @@ -588,7 +465,10 @@ size_t Curl_cyassl_version(char *buffer, size_t size) int Curl_cyassl_init(void) { - return (CyaSSL_Init() == SSL_SUCCESS); + if(CyaSSL_Init() == 0) + return 1; + + return -1; } @@ -764,23 +644,9 @@ int Curl_cyassl_random(struct SessionHandle *data, (void)data; if(InitRng(&rng)) return 1; - if(length > UINT_MAX) - return 1; - if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) + if(RNG_GenerateBlock(&rng, entropy, length)) return 1; return 0; } -void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused) -{ - Sha256 SHA256pw; - (void)unused; - InitSha256(&SHA256pw); - Sha256Update(&SHA256pw, tmp, tmplen); - Sha256Final(&SHA256pw, sha256sum); -} - #endif diff --git a/lib/vtls/cyassl.h b/lib/vtls/cyassl.h index 167de74f3..a691e16c3 100644 --- a/lib/vtls/cyassl.h +++ b/lib/vtls/cyassl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,9 +26,13 @@ #ifdef USE_CYASSL CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex); -bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex); +bool Curl_cyassl_data_pending(const struct connectdata* conn,int connindex); int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex); +/* tell CyaSSL to close down all open information regarding connections (and + thus session ID caching etc) */ +void Curl_cyassl_close_all(struct SessionHandle *data); + /* close a SSL connection */ void Curl_cyassl_close(struct connectdata *conn, int sockindex); @@ -42,16 +46,6 @@ CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, int Curl_cyassl_random(struct SessionHandle *data, unsigned char *entropy, size_t length); -void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t unused); - -/* Set the API backend definition to Schannel */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL - -/* this backend supports CURLOPT_SSL_CTX_* */ -#define have_curlssl_ssl_ctx 1 /* API setup for CyaSSL */ #define curlssl_init Curl_cyassl_init @@ -59,7 +53,7 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ #define curlssl_connect Curl_cyassl_connect #define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking #define curlssl_session_free(x) Curl_cyassl_session_free(x) -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_cyassl_close_all #define curlssl_close Curl_cyassl_close #define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y) #define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) @@ -69,7 +63,7 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ #define curlssl_check_cxn(x) ((void)x, -1) #define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y) #define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z) -#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d) +#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL #endif /* USE_CYASSL */ #endif /* HEADER_CURL_CYASSL_H */ diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c index d884bd4c4..ac05f05bb 100644 --- a/lib/vtls/gskit.c +++ b/lib/vtls/gskit.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -74,7 +74,9 @@ #include "select.h" #include "strequal.h" #include "x509asn1.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -623,7 +625,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) sni = (char *) NULL; break; case CURL_SSLVERSION_SSLv3: - protoflags = CURL_GSKPROTO_SSLV3_MASK; + protoflags = CURL_GSKPROTO_SSLV2_MASK; sni = (char *) NULL; break; case CURL_SSLVERSION_TLSv1: @@ -984,6 +986,13 @@ void Curl_gskit_close(struct connectdata *conn, int sockindex) } +void Curl_gskit_close_all(struct SessionHandle *data) +{ + /* Unimplemented. */ + (void) data; +} + + int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h index af31fafad..baec82323 100644 --- a/lib/vtls/gskit.h +++ b/lib/vtls/gskit.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -32,17 +32,15 @@ #ifdef USE_GSKIT int Curl_gskit_init(void); void Curl_gskit_cleanup(void); -CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done); +CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex); +CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn, + int sockindex, bool * done); void Curl_gskit_close(struct connectdata *conn, int sockindex); -int Curl_gskit_shutdown(struct connectdata *conn, int sockindex); +void Curl_gskit_close_all(struct SessionHandle * data); +int Curl_gskit_shutdown(struct connectdata * conn, int sockindex); -size_t Curl_gskit_version(char *buffer, size_t size); -int Curl_gskit_check_cxn(struct connectdata *cxn); - -/* Set the API backend definition to GSKit */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT +size_t Curl_gskit_version(char * buffer, size_t size); +int Curl_gskit_check_cxn(struct connectdata * cxn); /* this backend supports CURLOPT_CERTINFO */ #define have_curlssl_certinfo 1 @@ -55,7 +53,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn); /* No session handling for GSKit */ #define curlssl_session_free(x) Curl_nop_stmt -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_gskit_close_all #define curlssl_close Curl_gskit_close #define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y) #define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN @@ -65,7 +63,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn); #define curlssl_check_cxn(x) Curl_gskit_check_cxn(x) #define curlssl_data_pending(x,y) 0 #define curlssl_random(x,y,z) -1 - +#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT #endif /* USE_GSKIT */ #endif /* HEADER_CURL_GSKIT_H */ diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index c54dfc1d2..5d4e48a25 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -39,7 +39,6 @@ #ifdef USE_GNUTLS_NETTLE #include <gnutls/crypto.h> #include <nettle/md5.h> -#include <nettle/sha2.h> #else #include <gcrypt.h> #endif @@ -54,8 +53,9 @@ #include "select.h" #include "rawstr.h" #include "warnless.h" -#include "x509asn1.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -92,23 +92,14 @@ static bool gtls_inited = FALSE; # define GNUTLS_MAPS_WINSOCK_ERRORS 1 # endif -# if (GNUTLS_VERSION_NUMBER >= 0x030200) -# define HAS_ALPN -# endif - -# if (GNUTLS_VERSION_NUMBER >= 0x03020d) -# define HAS_OCSP -# endif - -# if (GNUTLS_VERSION_NUMBER >= 0x030306) -# define HAS_CAPATH +# ifdef USE_NGHTTP2 +# undef HAS_ALPN +# if (GNUTLS_VERSION_NUMBER >= 0x030200) +# define HAS_ALPN +# endif # endif #endif -#ifdef HAS_OCSP -# include <gnutls/ocsp.h> -#endif - /* * Custom push and pull callback functions used by GNU TLS to read and write * to the socket. These functions are simple wrappers to send() and recv() @@ -213,7 +204,7 @@ static void showtime(struct SessionHandle *data, snprintf(data->state.buffer, BUFSIZE, - "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n", text, Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -232,7 +223,7 @@ static gnutls_datum_t load_file (const char *file) long filelen; void *ptr; - if(!(f = fopen(file, "rb"))) + if(!(f = fopen(file, "r"))) return loaded_file; if(fseek(f, 0, SEEK_END) != 0 || (filelen = ftell(f)) < 0 @@ -328,8 +319,7 @@ static CURLcode handshake(struct connectdata *conn, if(strerr == NULL) strerr = gnutls_strerror(rc); - infof(data, "gnutls_handshake() warning: %s\n", strerr); - continue; + failf(data, "gnutls_handshake() warning: %s", strerr); } else if(rc < 0) { const char *strerr = NULL; @@ -402,6 +392,10 @@ gtls_connect_step1(struct connectdata *conn, const char* prioritylist; const char *err = NULL; #endif +#ifdef HAS_ALPN + int protocols_size = 2; + gnutls_datum_t protocols[2]; +#endif if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -469,24 +463,6 @@ gtls_connect_step1(struct connectdata *conn, rc, data->set.ssl.CAfile); } -#ifdef HAS_CAPATH - if(data->set.ssl.CApath) { - /* set the trusted CA cert directory */ - rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, - data->set.ssl.CApath, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) - return CURLE_SSL_CACERT_BADFILE; - } - else - infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CApath); - } -#endif - if(data->set.ssl.CRLfile) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, @@ -633,25 +609,20 @@ gtls_connect_step1(struct connectdata *conn, #endif #ifdef HAS_ALPN - if(data->set.ssl_enable_alpn) { - int cur = 0; - gnutls_datum_t protocols[2]; - -#ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { - protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; - protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; - cur++; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.ssl_enable_alpn) { + protocols[0].data = NGHTTP2_PROTO_VERSION_ID; + protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[1].data = ALPN_HTTP_1_1; + protocols[1].size = ALPN_HTTP_1_1_LENGTH; + gnutls_alpn_set_protocols(session, protocols, protocols_size, 0); + infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID, + ALPN_HTTP_1_1); + connssl->asked_for_h2 = TRUE; + } + else { + infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n"); } -#endif - - protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; - protocols[cur].size = ALPN_HTTP_1_1_LENGTH; - cur++; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); - - gnutls_alpn_set_protocols(session, protocols, cur, 0); } #endif @@ -673,21 +644,13 @@ gtls_connect_step1(struct connectdata *conn, if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); - if(rc != GNUTLS_E_SUCCESS) { + if(rc != GNUTLS_E_SUCCESS) failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); - return CURLE_SSL_CONNECT_ERROR; - } } else #endif - { rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, conn->ssl[sockindex].cred); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); - return CURLE_SSL_CONNECT_ERROR; - } - } /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, @@ -700,16 +663,6 @@ gtls_connect_step1(struct connectdata *conn, /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); -#ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { - rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); - return CURLE_SSL_CONNECT_ERROR; - } - } -#endif - /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ @@ -789,8 +742,8 @@ gtls_connect_step3(struct connectdata *conn, { unsigned int cert_list_size; const gnutls_datum_t *chainp; - unsigned int verify_status = 0; - gnutls_x509_crt_t x509_cert, x509_issuer; + unsigned int verify_status; + gnutls_x509_crt_t x509_cert,x509_issuer; gnutls_datum_t issuerp; char certbuf[256] = ""; /* big enough? */ size_t size; @@ -808,16 +761,6 @@ gtls_connect_step3(struct connectdata *conn, #endif CURLcode result = CURLE_OK; - gnutls_protocol_t version = gnutls_protocol_get_version(session); - - /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ - ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), - gnutls_cipher_get(session), - gnutls_mac_get(session)); - - infof(data, "SSL connection using %s / %s\n", - gnutls_protocol_get_name(version), ptr); - /* This function will return the peer's raw certificate (chain) as sent by the peer. These certificates are in raw format (DER encoded for X.509). In case of a X.509 then a certificate list may be present. The @@ -848,23 +791,6 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "\t common name: WARNING couldn't obtain\n"); } - if(data->set.ssl.certinfo && chainp) { - unsigned int i; - - result = Curl_ssl_init_certinfo(data, cert_list_size); - if(result) - return result; - - for(i = 0; i < cert_list_size; i++) { - const char *beg = (const char *) chainp[i].data; - const char *end = beg + chainp[i].size; - - result = Curl_extract_certinfo(conn, i, beg, end); - if(result) - return result; - } - } - if(data->set.ssl.verifypeer) { /* This function will try to verify the peer's certificate and return its status (trusted, invalid etc.). The value of status should be one or @@ -896,111 +822,6 @@ gtls_connect_step3(struct connectdata *conn, else infof(data, "\t server certificate verification SKIPPED\n"); -#ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { - if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { - gnutls_datum_t status_request; - gnutls_ocsp_resp_t ocsp_resp; - - gnutls_ocsp_cert_status_t status; - gnutls_x509_crl_reason_t reason; - - rc = gnutls_ocsp_status_request_get(session, &status_request); - - infof(data, "\t server certificate status verification FAILED\n"); - - if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { - failf(data, "No OCSP response received"); - return CURLE_SSL_INVALIDCERTSTATUS; - } - - if(rc < 0) { - failf(data, "Invalid OCSP response received"); - return CURLE_SSL_INVALIDCERTSTATUS; - } - - gnutls_ocsp_resp_init(&ocsp_resp); - - rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request); - if(rc < 0) { - failf(data, "Invalid OCSP response received"); - return CURLE_SSL_INVALIDCERTSTATUS; - } - - rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL, - &status, NULL, NULL, NULL, &reason); - - switch(status) { - case GNUTLS_OCSP_CERT_GOOD: - break; - - case GNUTLS_OCSP_CERT_REVOKED: { - const char *crl_reason; - - switch(reason) { - default: - case GNUTLS_X509_CRLREASON_UNSPECIFIED: - crl_reason = "unspecified reason"; - break; - - case GNUTLS_X509_CRLREASON_KEYCOMPROMISE: - crl_reason = "private key compromised"; - break; - - case GNUTLS_X509_CRLREASON_CACOMPROMISE: - crl_reason = "CA compromised"; - break; - - case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED: - crl_reason = "affiliation has changed"; - break; - - case GNUTLS_X509_CRLREASON_SUPERSEDED: - crl_reason = "certificate superseded"; - break; - - case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION: - crl_reason = "operation has ceased"; - break; - - case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD: - crl_reason = "certificate is on hold"; - break; - - case GNUTLS_X509_CRLREASON_REMOVEFROMCRL: - crl_reason = "will be removed from delta CRL"; - break; - - case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN: - crl_reason = "privilege withdrawn"; - break; - - case GNUTLS_X509_CRLREASON_AACOMPROMISE: - crl_reason = "AA compromised"; - break; - } - - failf(data, "Server certificate was revoked: %s", crl_reason); - break; - } - - default: - case GNUTLS_OCSP_CERT_UNKNOWN: - failf(data, "Server certificate status is unknown"); - break; - } - - gnutls_ocsp_resp_deinit(ocsp_resp); - - return CURLE_SSL_INVALIDCERTSTATUS; - } - else - infof(data, "\t server certificate status verification OK\n"); - } - else - infof(data, "\t server certificate status verification SKIPPED\n"); -#endif - /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init(&x509_cert); @@ -1013,7 +834,7 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_init(&x509_issuer); issuerp = load_file(data->set.ssl.issuercert); gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); - rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); + rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer); gnutls_x509_crt_deinit(x509_issuer); unload_file(issuerp); if(rc <= 0) { @@ -1022,7 +843,7 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_ISSUER_ERROR; } - infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", + infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n", data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); } @@ -1162,6 +983,7 @@ gtls_connect_step3(struct connectdata *conn, /* Show: + - ciphers used - subject - start date - expire date @@ -1201,6 +1023,14 @@ gtls_connect_step3(struct connectdata *conn, /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ infof(data, "\t compression: %s\n", ptr); + /* the name of the cipher used. ie 3DES. */ + ptr = gnutls_cipher_get_name(gnutls_cipher_get(session)); + infof(data, "\t cipher: %s\n", ptr); + + /* the MAC algorithms name. ie SHA1 */ + ptr = gnutls_mac_get_name(gnutls_mac_get(session)); + infof(data, "\t MAC: %s\n", ptr); + #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { rc = gnutls_alpn_get_selected_protocol(session, &proto); @@ -1208,21 +1038,19 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "ALPN, server accepted to use %.*s\n", proto.size, proto.data); -#ifdef USE_NGHTTP2 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, - NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, + NGHTTP2_PROTO_VERSION_ID_LEN) == 0) { + conn->negnpn = NPN_HTTP2; } - else -#endif - if(proto.size == ALPN_HTTP_1_1_LENGTH && - !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) { - conn->negnpn = CURL_HTTP_VERSION_1_1; + else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, + proto.data, ALPN_HTTP_1_1_LENGTH) == 0) { + conn->negnpn = NPN_HTTP1_1; } } - else + else if(connssl->asked_for_h2) { infof(data, "ALPN, server did not agree to a protocol\n"); + } } #endif @@ -1354,6 +1182,12 @@ static ssize_t gtls_send(struct connectdata *conn, return rc; } +void Curl_gtls_close_all(struct SessionHandle *data) +{ + /* FIX: make the OpenSSL code more generic and use parts of it here */ + (void)data; +} + static void close_one(struct connectdata *conn, int idx) { @@ -1558,32 +1392,4 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */ #endif } -void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) -{ -#if defined(USE_GNUTLS_NETTLE) - struct sha256_ctx SHA256pw; - sha256_init(&SHA256pw); - sha256_update(&SHA256pw, (unsigned int)tmplen, tmp); - sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum); -#elif defined(USE_GNUTLS) - gcry_md_hd_t SHA256pw; - gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); - gcry_md_write(SHA256pw, tmp, tmplen); - memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len); - gcry_md_close(SHA256pw); -#endif -} - -bool Curl_gtls_cert_status_request(void) -{ -#ifdef HAS_OCSP - return TRUE; -#else - return FALSE; -#endif -} - #endif /* USE_GNUTLS */ diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h index 0afd9b94a..12460beda 100644 --- a/lib/vtls/gtls.h +++ b/lib/vtls/gtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,10 @@ CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); +/* tell GnuTLS to close down all open information regarding connections (and + thus session ID caching etc) */ +void Curl_gtls_close_all(struct SessionHandle *data); + /* close a SSL connection */ void Curl_gtls_close(struct connectdata *conn, int sockindex); @@ -48,21 +52,6 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len); -void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len); - -bool Curl_gtls_cert_status_request(void); - -/* Set the API backend definition to GnuTLS */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS - -/* this backend supports the CAPATH option */ -#define have_curlssl_ca_path 1 - -/* this backend supports CURLOPT_CERTINFO */ -#define have_curlssl_certinfo 1 /* API setup for GnuTLS */ #define curlssl_init Curl_gtls_init @@ -70,7 +59,7 @@ bool Curl_gtls_cert_status_request(void); #define curlssl_connect Curl_gtls_connect #define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking #define curlssl_session_free(x) Curl_gtls_session_free(x) -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_gtls_close_all #define curlssl_close Curl_gtls_close #define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y) #define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) @@ -81,8 +70,7 @@ bool Curl_gtls_cert_status_request(void); #define curlssl_data_pending(x,y) ((void)x, (void)y, 0) #define curlssl_random(x,y,z) Curl_gtls_random(x,y,z) #define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d) -#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d) -#define curlssl_cert_status_request() Curl_gtls_cert_status_request() +#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS #endif /* USE_GNUTLS */ #endif /* HEADER_CURL_GTLS_H */ diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 91727c7c3..dd83a9d68 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -38,7 +38,10 @@ #include "select.h" #include "vtls.h" #include "llist.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include <curl/mprintf.h> + #include "nssg.h" #include <nspr.h> #include <nss.h> @@ -56,20 +59,13 @@ #include <base64.h> #include <cert.h> #include <prerror.h> -#include <keyhi.h> /* for SECKEY_DestroyPublicKey() */ - -#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) - -#if NSSVERNUM >= 0x030f00 /* 3.15.0 */ -#include <ocsp.h> -#endif +#include "curl_memory.h" #include "rawstr.h" #include "warnless.h" #include "x509asn1.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #define SSL_DIR "/etc/pki/nssdb" @@ -643,34 +639,6 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isServer) { struct connectdata *conn = (struct connectdata *)arg; - -#ifdef SSL_ENABLE_OCSP_STAPLING - if(conn->data->set.ssl.verifystatus) { - SECStatus cacheResult; - - const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); - if(!csa) { - failf(conn->data, "Invalid OCSP response"); - return SECFailure; - } - - if(csa->len == 0) { - failf(conn->data, "No OCSP response received"); - return SECFailure; - } - - cacheResult = CERT_CacheOCSPResponseFromSideChannel( - CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd), - PR_Now(), &csa->items[0], arg - ); - - if(cacheResult != SECSuccess) { - failf(conn->data, "Invalid OCSP response"); - return cacheResult; - } - } -#endif - if(!conn->data->set.ssl.verifypeer) { infof(conn->data, "skipping SSL peer certificate verification\n"); return SECSuccess; @@ -684,6 +652,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, */ static void HandshakeCallback(PRFileDesc *sock, void *arg) { +#ifdef USE_NGHTTP2 struct connectdata *conn = (struct connectdata*) arg; unsigned int buflenmax = 50; unsigned char buf[50]; @@ -699,7 +668,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) switch(state) { case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: - infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + if(connssl->asked_for_h2) + infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n"); return; #ifdef SSL_ENABLE_ALPN case SSL_NEXT_PROTO_SELECTED: @@ -711,79 +681,21 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) break; } -#ifdef USE_NGHTTP2 if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN) + == 0) { + conn->negnpn = NPN_HTTP2; } - else -#endif - if(buflen == ALPN_HTTP_1_1_LENGTH && - !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { - conn->negnpn = CURL_HTTP_VERSION_1_1; + else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf, + ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = NPN_HTTP1_1; } } -} - -#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ -static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, - PRBool *canFalseStart) -{ - struct connectdata *conn = client_data; - struct SessionHandle *data = conn->data; - - SSLChannelInfo channelInfo; - SSLCipherSuiteInfo cipherInfo; - - SECStatus rv; - PRBool negotiatedExtension; - - *canFalseStart = PR_FALSE; - - if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess) - return SECFailure; - - if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, - sizeof(cipherInfo)) != SECSuccess) - return SECFailure; - - /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for - * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310 - */ - if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) - goto end; - - /* Only allow ECDHE key exchange algorithm. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */ - if(cipherInfo.keaType != ssl_kea_ecdh) - goto end; - - /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC - * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt - * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */ - if(cipherInfo.symCipher != ssl_calg_aes_gcm) - goto end; - - /* Enforce ALPN or NPN to do False Start, as an indicator of server - * compatibility. */ - rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn, - &negotiatedExtension); - if(rv != SECSuccess || !negotiatedExtension) { - rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn, - &negotiatedExtension); - } - - if(rv != SECSuccess || !negotiatedExtension) - goto end; - - *canFalseStart = PR_TRUE; - - infof(data, "Trying TLS False Start\n"); - -end: - return SECSuccess; -} +#else + (void)sock; + (void)arg; #endif +} static void display_cert_info(struct SessionHandle *data, CERTCertificate *cert) @@ -918,7 +830,7 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) static SECStatus check_issuer_cert(PRFileDesc *sock, char *issuer_nickname) { - CERTCertificate *cert, *cert_issuer, *issuer; + CERTCertificate *cert,*cert_issuer,*issuer; SECStatus res=SECSuccess; void *proto_win = NULL; @@ -929,7 +841,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, */ cert = SSL_PeerCertificate(sock); - cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner); + cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); proto_win = SSL_RevealPinArg(sock); issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); @@ -946,53 +858,6 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, return res; } -static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, - const char *pinnedpubkey) -{ - CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - struct SessionHandle *data = connssl->data; - CERTCertificate *cert; - - if(!pinnedpubkey) - /* no pinned public key specified */ - return CURLE_OK; - - /* get peer certificate */ - cert = SSL_PeerCertificate(connssl->handle); - if(cert) { - /* extract public key from peer certificate */ - SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); - if(pubkey) { - /* encode the public key as DER */ - SECItem *cert_der = PK11_DEREncodePublicKey(pubkey); - if(cert_der) { - /* compare the public key with the pinned public key */ - result = Curl_pin_peer_pubkey(pinnedpubkey, - cert_der->data, - cert_der->len); - SECITEM_FreeItem(cert_der, PR_TRUE); - } - SECKEY_DestroyPublicKey(pubkey); - } - CERT_DestroyCertificate(cert); - } - - /* report the resulting status */ - switch(result) { - case CURLE_OK: - infof(data, "pinned public key verified successfully!\n"); - break; - case CURLE_SSL_PINNEDPUBKEYNOTMATCH: - failf(data, "failed to verify pinned public key"); - break; - default: - /* OOM, etc. */ - break; - } - - return result; -} - /** * * Callback to pick the SSL client certificate. @@ -1134,7 +999,6 @@ static PRStatus nspr_io_close(PRFileDesc *fd) return close_fn(fd); } -/* data might be NULL */ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) { NSSInitParameters initparams; @@ -1172,7 +1036,6 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) return CURLE_SSL_CACERT_BADFILE; } -/* data might be NULL */ static CURLcode nss_init(struct SessionHandle *data) { char *cert_dir; @@ -1251,14 +1114,12 @@ int Curl_nss_init(void) return 1; } -/* data might be NULL */ CURLcode Curl_nss_force_init(struct SessionHandle *data) { CURLcode result; if(!nss_initlock) { - if(data) - failf(data, "unable to initialize NSS, curl_global_init() should have " - "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); + failf(data, "unable to initialize NSS, curl_global_init() should have " + "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); return CURLE_FAILED_INIT; } @@ -1349,8 +1210,10 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) * authentication data from a previous connection. */ SSL_InvalidateSession(connssl->handle); - free(connssl->client_nickname); - connssl->client_nickname = NULL; + if(connssl->client_nickname != NULL) { + free(connssl->client_nickname); + connssl->client_nickname = NULL; + } /* destroy all NSS objects in order to avoid failure of NSS shutdown */ Curl_llist_destroy(connssl->obj_list, NULL); connssl->obj_list = NULL; @@ -1361,6 +1224,15 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) } } +/* + * This function is called when the 'data' struct is going away. Close + * down everything and free all resources! + */ +void Curl_nss_close_all(struct SessionHandle *data) +{ + (void)data; +} + /* return true if NSS can provide error code (and possibly msg) for the error */ static bool is_nss_error(CURLcode err) @@ -1557,6 +1429,16 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) SSL_LIBRARY_VERSION_TLS_1_0 /* max */ }; +#ifdef USE_NGHTTP2 +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) + unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN + + ALPN_HTTP_1_1_LENGTH + 2; + unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH + + 2]; + int cur = 0; +#endif +#endif + connssl->data = data; /* list of all NSS objects we need to destroy in Curl_nss_close() */ @@ -1736,57 +1618,43 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); } -#ifdef SSL_ENABLE_OCSP_STAPLING - if(data->set.ssl.verifystatus) { - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) - != SECSuccess) - goto error; - } -#endif - +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { #ifdef SSL_ENABLE_NPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, data->set.ssl_enable_npn - ? PR_TRUE : PR_FALSE) != SECSuccess) - goto error; + if(data->set.ssl_enable_npn) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess) + goto error; + } #endif #ifdef SSL_ENABLE_ALPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, data->set.ssl_enable_alpn - ? PR_TRUE : PR_FALSE) != SECSuccess) - goto error; -#endif - -#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ - if(data->set.ssl.falsestart) { - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE) - != SECSuccess) - goto error; - - if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback, - conn) != SECSuccess) - goto error; - } + if(data->set.ssl_enable_alpn) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE) + != SECSuccess) + goto error; + } #endif #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) - if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { - int cur = 0; - unsigned char protocols[128]; - -#ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { + alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN; + cur++; + memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN); cur += NGHTTP2_PROTO_VERSION_ID_LEN; + alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH; + cur++; + memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + + if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len) + != SECSuccess) + goto error; + connssl->asked_for_h2 = TRUE; + } + else { + infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n"); } #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; - - if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess) - goto error; } #endif @@ -1847,7 +1715,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } if(SECFailure == ret) { - infof(data, "SSL certificate issuer check failed\n"); + infof(data,"SSL certificate issuer check failed\n"); result = CURLE_SSL_ISSUER_ERROR; goto error; } @@ -1856,11 +1724,6 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } - result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); - if(result) - /* status already printed */ - goto error; - return CURLE_OK; error: @@ -2007,7 +1870,6 @@ size_t Curl_nss_version(char *buffer, size_t size) return snprintf(buffer, size, "NSS/%s", NSS_VERSION); } -/* data might be NULL */ int Curl_nss_seed(struct SessionHandle *data) { /* make sure that NSS is initialized */ @@ -2019,11 +1881,14 @@ int Curl_nss_random(struct SessionHandle *data, unsigned char *entropy, size_t length) { - Curl_nss_seed(data); /* Initiate the seed if not already done */ + if(data) + Curl_nss_seed(data); /* Initiate the seed if not already done */ - if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) - /* signal a failure */ - return -1; + if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) { + /* no way to signal a failure from here, we have to abort */ + failf(data, "PK11_GenerateRandom() failed, calling abort()..."); + abort(); + } return 0; } @@ -2041,34 +1906,4 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */ PK11_DestroyContext(MD5pw, PR_TRUE); } -void Curl_nss_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) -{ - PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); - unsigned int SHA256out; - - PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen)); - PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len)); - PK11_DestroyContext(SHA256pw, PR_TRUE); -} - -bool Curl_nss_cert_status_request(void) -{ -#ifdef SSL_ENABLE_OCSP_STAPLING - return TRUE; -#else - return FALSE; -#endif -} - -bool Curl_nss_false_start(void) { -#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ - return TRUE; -#else - return FALSE; -#endif -} - #endif /* USE_NSS */ diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h index 5fd72751d..74840e831 100644 --- a/lib/vtls/nssg.h +++ b/lib/vtls/nssg.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,6 +37,10 @@ CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, /* close a SSL connection */ void Curl_nss_close(struct connectdata *conn, int sockindex); +/* tell NSS to close down all open information regarding connections (and + thus session ID caching etc) */ +void Curl_nss_close_all(struct SessionHandle *data); + int Curl_nss_init(void); void Curl_nss_cleanup(void); @@ -56,18 +60,6 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */ unsigned char *md5sum, /* output */ size_t md5len); -void Curl_nss_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len); - -bool Curl_nss_cert_status_request(void); - -bool Curl_nss_false_start(void); - -/* Set the API backend definition to NSS */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS - /* this backend supports the CAPATH option */ #define have_curlssl_ca_path 1 @@ -82,7 +74,7 @@ bool Curl_nss_false_start(void); /* NSS has its own session ID cache */ #define curlssl_session_free(x) Curl_nop_stmt -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_nss_close_all #define curlssl_close Curl_nss_close /* NSS has no shutdown function provided and thus always fail */ #define curlssl_shutdown(x,y) ((void)x, (void)y, 1) @@ -94,9 +86,7 @@ bool Curl_nss_false_start(void); #define curlssl_data_pending(x,y) ((void)x, (void)y, 0) #define curlssl_random(x,y,z) Curl_nss_random(x,y,z) #define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d) -#define curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d) -#define curlssl_cert_status_request() Curl_nss_cert_status_request() -#define curlssl_false_start() Curl_nss_false_start() +#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS #endif /* USE_NSS */ #endif /* HEADER_CURL_NSSG_H */ diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 90e4c2b32..a68d88eae 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -32,8 +32,6 @@ #include "curl_setup.h" -#ifdef USE_OPENSSL - #ifdef HAVE_LIMITS_H #include <limits.h> #endif @@ -51,9 +49,13 @@ #include "vtls.h" #include "rawstr.h" #include "hostcheck.h" -#include "curl_printf.h" -#include <openssl/ssl.h> +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include <curl/mprintf.h> + +#ifdef USE_SSLEAY + +#ifdef USE_OPENSSL #include <openssl/rand.h> #include <openssl/x509v3.h> #include <openssl/dsa.h> @@ -62,28 +64,36 @@ #include <openssl/md5.h> #include <openssl/conf.h> #include <openssl/bn.h> -#include <openssl/rsa.h> - -#ifdef HAVE_OPENSSL_PKCS12_H -#include <openssl/pkcs12.h> -#endif - -#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_IS_BORINGSSL) -#include <openssl/ocsp.h> +#else +#include <rand.h> +#include <x509v3.h> +#include <md5.h> #endif #include "warnless.h" +#include "curl_memory.h" #include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */ -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #ifndef OPENSSL_VERSION_NUMBER #error "OPENSSL_VERSION_NUMBER not defined" #endif -#if OPENSSL_VERSION_NUMBER >= 0x00907001L && !defined(OPENSSL_IS_BORINGSSL) +#if OPENSSL_VERSION_NUMBER >= 0x0090581fL +#define HAVE_SSL_GET1_SESSION 1 +#else +#undef HAVE_SSL_GET1_SESSION +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00904100L +#define HAVE_USERDATA_IN_PWD_CALLBACK 1 +#else +#undef HAVE_USERDATA_IN_PWD_CALLBACK +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00907001L /* ENGINE_load_private_key() takes four arguments */ #define HAVE_ENGINE_LOAD_FOUR_ARGS #include <openssl/ui.h> @@ -92,16 +102,18 @@ #undef HAVE_ENGINE_LOAD_FOUR_ARGS #endif -#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && \ - defined(HAVE_OPENSSL_PKCS12_H) && \ - !defined(OPENSSL_IS_BORINGSSL) -/* OpenSSL has PKCS 12 support, BoringSSL does not */ +#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && defined(HAVE_OPENSSL_PKCS12_H) +/* OpenSSL has PKCS 12 support */ #define HAVE_PKCS12_SUPPORT #else -/* OpenSSL does not have PKCS12 support */ +/* OpenSSL/SSLEay does not have PKCS12 support */ #undef HAVE_PKCS12_SUPPORT #endif +#if OPENSSL_VERSION_NUMBER >= 0x00906001L +#define HAVE_ERR_ERROR_STRING_N 1 +#endif + #if OPENSSL_VERSION_NUMBER >= 0x00909000L #define SSL_METHOD_QUAL const #else @@ -115,10 +127,7 @@ #define X509_STORE_set_flags(x,y) Curl_nop_stmt #endif -#ifdef OPENSSL_IS_BORINGSSL -/* BoringSSL has no ERR_remove_state() */ -#define ERR_remove_state(x) -#elif (OPENSSL_VERSION_NUMBER >= 0x10000000L) +#if OPENSSL_VERSION_NUMBER >= 0x10000000L #define HAVE_ERR_REMOVE_THREAD_STATE 1 #endif @@ -128,19 +137,6 @@ #define OPENSSL_NO_SSL2 #endif -#if defined(OPENSSL_IS_BORINGSSL) -#define NO_RAND_SEED 1 -/* In BoringSSL OpenSSL_add_all_algorithms does nothing */ -#define OpenSSL_add_all_algorithms() -/* BoringSSL does not have CONF_modules_load_file */ -#define CONF_modules_load_file(a,b,c) -#endif - -#if (OPENSSL_VERSION_NUMBER < 0x0090808fL) || defined(OPENSSL_IS_BORINGSSL) -/* not present in BoringSSL or older OpenSSL */ -#define OPENSSL_load_builtin_modules(x) -#endif - /* * 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 @@ -149,8 +145,18 @@ */ #define RAND_LOAD_LENGTH 1024 -static int passwd_callback(char *buf, int num, int encrypting, - void *global_passwd) +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK +static char global_passwd[64]; +#endif + +static int passwd_callback(char *buf, int num, int encrypting +#ifdef HAVE_USERDATA_IN_PWD_CALLBACK + /* This was introduced in 0.9.4, we can set this + using SSL_CTX_set_default_passwd_cb_userdata() + */ + , void *global_passwd +#endif + ) { DEBUGASSERT(0 == encrypting); @@ -171,7 +177,6 @@ static int passwd_callback(char *buf, int num, int encrypting, * pass in an argument that is never used. */ -#ifndef NO_RAND_SEED #ifdef HAVE_RAND_STATUS #define seed_enough(x) rand_enough() static bool rand_enough(void) @@ -256,7 +261,7 @@ static int ossl_seed(struct SessionHandle *data) return nread; } -static void Curl_ossl_seed(struct SessionHandle *data) +static int Curl_ossl_seed(struct SessionHandle *data) { /* we have the "SSL is seeded" boolean static to prevent multiple time-consuming seedings in vain */ @@ -267,11 +272,8 @@ static void Curl_ossl_seed(struct SessionHandle *data) ossl_seed(data); ssl_seeded = TRUE; } + return 0; } -#else -/* BoringSSL needs no seeding */ -#define Curl_ossl_seed(x) -#endif #ifndef SSL_FILETYPE_ENGINE @@ -355,23 +357,37 @@ int cert_stuff(struct connectdata *conn, int cert_done = 0; if(data->set.str[STRING_KEY_PASSWD]) { - /* set the password in the callback userdata */ +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK + /* + * If password has been given, we store that in the global + * area (*shudder*) for a while: + */ + size_t len = strlen(data->set.str[STRING_KEY_PASSWD]); + if(len < sizeof(global_passwd)) + memcpy(global_passwd, data->set.str[STRING_KEY_PASSWD], len+1); + else + global_passwd[0] = '\0'; +#else + /* + * We set the password in the callback userdata + */ SSL_CTX_set_default_passwd_cb_userdata(ctx, data->set.str[STRING_KEY_PASSWD]); +#endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } +#define SSL_CLIENT_CERT_ERR \ + "unable to use client certificate (no key found or wrong pass phrase?)" + 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, OpenSSL error %s, " - "(no key found, wrong pass phrase, or wrong file format?)", - ERR_error_string(ERR_get_error(), NULL) ); + failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; @@ -383,10 +399,7 @@ int cert_stuff(struct connectdata *conn, if(SSL_CTX_use_certificate_file(ctx, cert_file, file_type) != 1) { - failf(data, - "could not load ASN1 client certificate, OpenSSL error %s, " - "(no key found, wrong pass phrase, or wrong file format?)", - ERR_error_string(ERR_get_error(), NULL) ); + failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; @@ -452,7 +465,7 @@ int cert_stuff(struct connectdata *conn, STACK_OF(X509) *ca = NULL; int i; - f = fopen(cert_file, "rb"); + f = fopen(cert_file,"rb"); if(!f) { failf(data, "could not open PKCS12 file '%s'", cert_file); return 0; @@ -461,7 +474,7 @@ int cert_stuff(struct connectdata *conn, fclose(f); if(!p12) { - failf(data, "error reading PKCS12 file '%s'", cert_file); + failf(data, "error reading PKCS12 file '%s'", cert_file ); return 0; } @@ -479,9 +492,7 @@ int cert_stuff(struct connectdata *conn, PKCS12_free(p12); if(SSL_CTX_use_certificate(ctx, x509) != 1) { - failf(data, - "could not load PKCS12 client certificate, OpenSSL error %s", - ERR_error_string(ERR_get_error(), NULL) ); + failf(data, SSL_CLIENT_CERT_ERR); goto fail; } @@ -575,7 +586,7 @@ int cert_stuff(struct connectdata *conn, #endif /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) - ENGINE_load_private_key(data->state.engine, key_file, + ENGINE_load_private_key(data->state.engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif @@ -617,7 +628,7 @@ int cert_stuff(struct connectdata *conn, ssl=SSL_new(ctx); if(!ssl) { - failf(data, "unable to create an SSL structure"); + failf(data,"unable to create an SSL structure"); return 0; } @@ -627,7 +638,7 @@ int cert_stuff(struct connectdata *conn, 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_copy_parameters(pktmp,SSL_get_privatekey(ssl)); EVP_PKEY_free(pktmp); } @@ -643,6 +654,10 @@ int cert_stuff(struct connectdata *conn, failf(data, "Private key does not match the certificate public key"); return 0; } +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK + /* erase it now */ + memset(global_passwd, 0, sizeof(global_passwd)); +#endif } return 1; } @@ -677,17 +692,36 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) #endif } +static +int cert_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *err_cert; + char buf[256]; + + err_cert=X509_STORE_CTX_get_current_cert(ctx); + (void)x509_name_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + return ok; +} + /* Return error string for last OpenSSL error */ static char *SSL_strerror(unsigned long error, char *buf, size_t size) { +#ifdef HAVE_ERR_ERROR_STRING_N /* OpenSSL 0.9.6 and later has a function named - ERR_error_string_n() that takes the size of the buffer as a + ERRO_error_string_n() that takes the size of the buffer as a third argument */ ERR_error_string_n(error, buf, size); +#else + (void) size; + ERR_error_string(error, buf); +#endif return buf; } +#endif /* USE_SSLEAY */ + +#ifdef USE_SSLEAY /** * Global SSL init * @@ -696,8 +730,6 @@ static char *SSL_strerror(unsigned long error, char *buf, size_t size) */ int Curl_ossl_init(void) { - OPENSSL_load_builtin_modules(); - #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES ENGINE_load_builtin_engines(); #endif @@ -724,13 +756,17 @@ int Curl_ossl_init(void) #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif - CONF_modules_load_file(NULL, NULL, - CONF_MFLAGS_DEFAULT_SECTION| - CONF_MFLAGS_IGNORE_MISSING_FILE); + (void)CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_DEFAULT_SECTION| + CONF_MFLAGS_IGNORE_MISSING_FILE); return 1; } +#endif /* USE_SSLEAY */ + +#ifdef USE_SSLEAY + /* Global cleanup */ void Curl_ossl_cleanup(void) { @@ -785,7 +821,7 @@ int Curl_ossl_check_cxn(struct connectdata *conn) */ CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine) { -#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) +#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) ENGINE *e; #if OPENSSL_VERSION_NUMBER >= 0x00909000L @@ -833,7 +869,7 @@ CURLcode Curl_ossl_set_engine_default(struct SessionHandle *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", + infof(data,"set default crypto engine '%s'\n", ENGINE_get_id(data->state.engine)); } else { @@ -853,7 +889,7 @@ CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data) struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data) { struct curl_slist *list = NULL; -#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) +#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) struct curl_slist *beg; ENGINE *e; @@ -1022,7 +1058,7 @@ static int asn1_output(const ASN1_UTCTIME *tm, const char *asn1_string; int gmt=FALSE; int i; - int year=0, month=0, day=0, hour=0, minute=0, second=0; + int year=0,month=0,day=0,hour=0,minute=0,second=0; i=tm->length; asn1_string=(const char *)tm->data; @@ -1181,14 +1217,14 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) 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; + 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); + 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; @@ -1198,8 +1234,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) UTF8 etc. */ if(i>=0) { - ASN1_STRING *tmp = - X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + 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 @@ -1263,135 +1298,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) return result; } - -#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ - !defined(OPENSSL_IS_BORINGSSL) -static CURLcode verifystatus(struct connectdata *conn, - struct ssl_connect_data *connssl) -{ - int i, ocsp_status; - const unsigned char *p; - CURLcode result = CURLE_OK; - struct SessionHandle *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(connssl->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(connssl->handle); - st = SSL_CTX_get_cert_store(connssl->ctx); - -#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ - defined(LIBRESSL_VERSION_NUMBER)) - /* 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; - - if(!(single = OCSP_resp_get0(br, i))) - 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 */ +#endif /* USE_SSLEAY */ /* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions and thus this cannot be done there. */ @@ -1432,12 +1339,8 @@ static const char *ssl_msg_type(int ssl_ver, int msg) 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"; + return "CERT"; case SSL3_MT_SERVER_KEY_EXCHANGE: return "Server key exchange"; case SSL3_MT_CLIENT_KEY_EXCHANGE: @@ -1450,10 +1353,6 @@ static const char *ssl_msg_type(int ssl_ver, int msg) 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"; @@ -1461,22 +1360,12 @@ static const char *ssl_msg_type(int ssl_ver, int msg) 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"; - } + return ( + type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " : + type == SSL3_RT_ALERT ? "TLS alert, " : + type == SSL3_RT_HANDSHAKE ? "TLS handshake, " : + type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " : + "TLS Unknown, "); } @@ -1484,16 +1373,15 @@ static const char *tls_rt_type(int type) * 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) + const void *buf, size_t len, const SSL *ssl, + struct connectdata *conn) { struct SessionHandle *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; + const char *verstr; if(!conn || !conn->data || !conn->data->set.fdebug || (direction != 0 && direction != 1)) @@ -1502,8 +1390,8 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, data = conn->data; switch(ssl_ver) { -#ifdef SSL2_VERSION /* removed in recent versions */ - case SSL2_VERSION: +#ifdef SSL2_VERSION_MAJOR /* removed in recent versions */ + case SSL2_VERSION_MAJOR: verstr = "SSLv2"; break; #endif @@ -1525,36 +1413,29 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, verstr = "TLSv1.2"; 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 */ - 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 = ""; + /* 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 != 0) + 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); + 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); - } + txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s, %s%s (%d):\n", + verstr, 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); @@ -1562,7 +1443,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, } #endif -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY /* ====================================================== */ #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -1571,6 +1452,8 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, # define use_sni(x) Curl_nop_stmt #endif +#ifdef USE_NGHTTP2 + /* Check for OpenSSL 1.0.2 which has ALPN support. */ #undef HAS_ALPN #if OPENSSL_VERSION_NUMBER >= 0x10002000L \ @@ -1592,23 +1475,6 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, * in is a list of lenght 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, @@ -1616,43 +1482,40 @@ select_next_proto_cb(SSL *ssl, void *arg) { struct connectdata *conn = (struct connectdata*) arg; + int retval = nghttp2_select_next_protocol(out, outlen, in, inlen); (void)ssl; -#ifdef USE_NGHTTP2 - if(conn->data->set.httpversion == CURL_HTTP_VERSION_2_0 && - !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN)) { + if(retval == 1) { infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", NGHTTP2_PROTO_VERSION_ID); - conn->negnpn = CURL_HTTP_VERSION_2_0; - return SSL_TLSEXT_ERR_OK; + conn->negnpn = NPN_HTTP2; } -#endif - - if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, - ALPN_HTTP_1_1_LENGTH)) { + else if(retval == 0) { infof(conn->data, "NPN, negotiated HTTP1.1\n"); - conn->negnpn = CURL_HTTP_VERSION_1_1; - return SSL_TLSEXT_ERR_OK; + conn->negnpn = NPN_HTTP1_1; + } + else { + infof(conn->data, "NPN, no overlap, use HTTP1.1\n", + NGHTTP2_PROTO_VERSION_ID); + *out = (unsigned char*)"http/1.1"; + *outlen = sizeof("http/1.1") - 1; + conn->negnpn = NPN_HTTP1_1; } - - 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 */ +#endif /* USE_NGHTTP2 */ + static const char * -get_ssl_version_txt(SSL *ssl) +get_ssl_version_txt(SSL_SESSION *session) { - if(!ssl) + if(!session) return ""; - switch(SSL_version(ssl)) { + switch(session->ssl_version) { #if OPENSSL_VERSION_NUMBER >= 0x1000100FL case TLS1_2_VERSION: return "TLSv1.2"; @@ -1688,6 +1551,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) struct in_addr addr; #endif #endif +#ifdef HAS_ALPN + unsigned char protocols[128]; +#endif DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); @@ -1706,12 +1572,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: /* it will be handled later with the context options */ -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ - !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) - req_method = TLS_client_method(); -#else req_method = SSLv23_client_method(); -#endif use_sni(TRUE); break; case CURL_SSLVERSION_SSLv2: @@ -1728,10 +1589,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) break; #endif case CURL_SSLVERSION_SSLv3: -#ifdef OPENSSL_NO_SSL3_METHOD - failf(data, "OpenSSL was built without SSLv3 support"); - return CURLE_NOT_BUILT_IN; -#else #ifdef USE_TLS_SRP if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; @@ -1739,7 +1596,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) req_method = SSLv3_client_method(); use_sni(FALSE); break; -#endif } if(connssl->ctx) @@ -1758,9 +1614,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #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(connssl->ctx, ssl_tls_trace); - SSL_CTX_set_msg_callback_arg(connssl->ctx, conn); + /* the SSL trace callback is only used for verbose logging so we only + inform about failures of setting it */ + if(!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK, + (void (*)(void))ssl_tls_trace)) { + infof(data, "SSL: couldn't set callback!\n"); + } + else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, + conn)) { + infof(data, "SSL: couldn't set callback argument!\n"); + } } #endif @@ -1773,7 +1636,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) 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 + into the proper RFC5077 it seems: http://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 @@ -1793,7 +1656,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) 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 + (http://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 @@ -1886,36 +1749,36 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) SSL_CTX_set_options(connssl->ctx, ctx_options); +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { #ifdef HAS_NPN - if(data->set.ssl_enable_npn) - SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn); + if(data->set.ssl_enable_npn) { + SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, + conn); + } #endif #ifdef HAS_ALPN - if(data->set.ssl_enable_alpn) { - int cur = 0; - unsigned char protocols[128]; + if(data->set.ssl_enable_alpn) { + protocols[0] = NGHTTP2_PROTO_VERSION_ID_LEN; + memcpy(&protocols[1], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); -#ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[NGHTTP2_PROTO_VERSION_ID_LEN+1] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[NGHTTP2_PROTO_VERSION_ID_LEN+2], ALPN_HTTP_1_1, + ALPN_HTTP_1_1_LENGTH); - 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); + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + SSL_CTX_set_alpn_protos(connssl->ctx, protocols, + NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH + 2); + + infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID, + ALPN_HTTP_1_1); + connssl->asked_for_h2 = TRUE; } #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(connssl->ctx, protocols, cur); } #endif @@ -1938,7 +1801,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } - infof(data, "Cipher selection: %s\n", ciphers); #ifdef USE_TLS_SRP if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { @@ -1948,7 +1810,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) { + if(!SSL_CTX_set_srp_password(connssl->ctx,data->set.ssl.password)) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } @@ -1970,7 +1832,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) data->set.str[STRING_SSL_CAPATH])) { if(data->set.ssl.verifypeer) { /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate verify locations:\n" + failf(data,"error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", data->set.str[STRING_SSL_CAFILE]? data->set.str[STRING_SSL_CAFILE]: "none", @@ -2004,9 +1866,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), X509_LOOKUP_file()); if(!lookup || - (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE], + (!X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE], X509_FILETYPE_PEM)) ) { - failf(data, "error loading CRL file: %s", + failf(data,"error loading CRL file: %s", data->set.str[STRING_SSL_CRLFILE]); return CURLE_SSL_CRL_BADFILE; } @@ -2021,34 +1883,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) data->set.str[STRING_SSL_CRLFILE]: "none"); } - /* 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(data->set.ssl.verifypeer) { - X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->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(connssl->ctx, data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - NULL); + cert_verify_callback); /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { result = (*data->set.ssl.fsslctx)(data, connssl->ctx, data->set.ssl.fsslctxp); if(result) { - failf(data, "error signaled by ssl ctx callback"); + failf(data,"error signaled by ssl ctx callback"); return result; } } @@ -2061,13 +1909,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) 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_IS_BORINGSSL) - if(data->set.ssl.verifystatus) - SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); -#endif - SSL_set_connect_state(connssl->handle); connssl->server_cert = 0x0; @@ -2088,7 +1929,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* we got a session id, use it! */ if(!SSL_set_session(connssl->handle, ssl_sessionid)) { failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + ERR_error_string(ERR_get_error(),NULL)); return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ @@ -2098,7 +1939,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* pass the raw socket into the SSL layers */ if(!SSL_set_fd(connssl->handle, (int)sockfd)) { failf(data, "SSL: SSL_set_fd failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + ERR_error_string(ERR_get_error(),NULL)); return CURLE_SSL_CONNECT_ERROR; } @@ -2137,9 +1978,10 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) else { /* untreated error */ unsigned long errdetail; - char error_buffer[256]=""; /* OpenSSL documents that this must be at - least 256 bytes long. */ + char error_buffer[256]; /* OpenSSL documents that this must be at least + 256 bytes long. */ CURLcode result; + const char *cert_problem = NULL; long lerr; connssl->connecting_state = ssl_connect_2; /* the connection failed, @@ -2171,10 +2013,9 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) 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 problem, check your CA cert"); + cert_problem = "SSL certificate problem, verify that the CA cert is" + " OK."; + break; default: result = CURLE_SSL_CONNECT_ERROR; @@ -2195,7 +2036,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) } /* Could be a CERT problem */ - failf(data, "%s", error_buffer); + failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer); return result; } @@ -2206,7 +2047,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) /* Informational message */ infof(data, "SSL connection using %s / %s\n", - get_ssl_version_txt(connssl->handle), + get_ssl_version_txt(SSL_get_session(connssl->handle)), SSL_get_cipher(connssl->handle)); #ifdef HAS_ALPN @@ -2220,19 +2061,18 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) 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_0; + memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len) == 0) { + conn->negnpn = NPN_HTTP2; } - 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 if(len == + ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, + neg_protocol, + ALPN_HTTP_1_1_LENGTH) == 0) { + conn->negnpn = NPN_HTTP1_1; } } - else + else if(connssl->asked_for_h2) infof(data, "ALPN, server did not agree to a protocol\n"); } #endif @@ -2327,7 +2167,7 @@ static int X509V3_ext(struct SessionHandle *data, X509_EXTENSION_get_critical(ext)?"(critical)":""); if(!X509V3_EXT_print(bio_out, ext, 0, 0)) - ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); + M_ASN1_OCTET_STRING_print(bio_out, ext->value); BIO_get_mem_ptr(bio_out, &biomem); @@ -2457,22 +2297,28 @@ static CURLcode get_cert_chain(struct connectdata *conn, Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */ num=X509_get_serialNumber(x); - { + if(num->length <= 4) { + value = ASN1_INTEGER_get(num); + infof(data," Serial Number: %ld (0x%lx)\n", value, value); + snprintf(bufp, CERTBUFFERSIZE, "%lx", value); + } + else { int left = CERTBUFFERSIZE; ptr = bufp; - if(num->type == V_ASN1_NEG_INTEGER) { + *ptr++ = 0; + if(num->type == V_ASN1_NEG_INTEGER) *ptr++='-'; - left--; - } - for(j=0; (j<num->length) && (left>=3); j++) { - snprintf(ptr, left, "%02x", num->data[j]); - ptr += 2; - left -= 2; + for(j=0; (j<num->length) && (left>=4); j++) { + /* TODO: length restrictions */ + snprintf(ptr, 3, "%02x%c",num->data[j], + ((j+1 == num->length)?'\n':':')); + ptr += 3; + left-=4; } if(num->length) - infof(data, " Serial Number: %s\n", bufp); + infof(data," Serial Number: %s\n", bufp); else bufp[0]=0; } @@ -2581,23 +2427,23 @@ static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey) /* 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 + /* http://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 */ + /* http://www.openssl.org/docs/crypto/buffer.html */ buff1 = temp = OPENSSL_malloc(len1); if(!buff1) break; /* failed */ - /* https://www.openssl.org/docs/crypto/d2i_X509.html */ + /* http://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 + * sized the buffer.Its pretty weak since they should always be the * same. But it gives us something to test. */ if((len1 != len2) || !temp || ((temp - buff1) != len1)) @@ -2609,7 +2455,7 @@ static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey) result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1); } while(0); - /* https://www.openssl.org/docs/crypto/buffer.html */ + /* http://www.openssl.org/docs/crypto/buffer.html */ if(buff1) OPENSSL_free(buff1); @@ -2687,7 +2533,7 @@ static CURLcode servercert(struct connectdata *conn, /* e.g. match issuer name with provided issuer certificate */ if(data->set.str[STRING_SSL_ISSUERCERT]) { - fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT); + fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], "r"); if(!fp) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", @@ -2710,7 +2556,7 @@ static CURLcode servercert(struct connectdata *conn, fclose(fp); - if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { + if(X509_check_issued(issuer,connssl->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", data->set.str[STRING_SSL_ISSUERCERT]); @@ -2746,22 +2592,6 @@ static CURLcode servercert(struct connectdata *conn, infof(data, "\t SSL certificate verify ok.\n"); } -#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ - !defined(OPENSSL_IS_BORINGSSL) - if(data->set.ssl.verifystatus) { - result = verifystatus(conn, connssl); - if(result) { - X509_free(connssl->server_cert); - connssl->server_cert = NULL; - return result; - } - } -#endif - - if(!strict) - /* when not strict, we don't bother about the verify cert problems */ - result = CURLE_OK; - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; if(!result && ptr) { result = pkp_pin_peer_pubkey(connssl->server_cert, ptr); @@ -2787,11 +2617,25 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); +#ifdef HAVE_SSL_GET1_SESSION our_ssl_sessionid = SSL_get1_session(connssl->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. */ + /* 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. + This function was introduced in openssl 0.9.5a. */ +#else + our_ssl_sessionid = SSL_get_session(connssl->handle); + + /* if SSL_get1_session() is unavailable, use SSL_get_session(). + This is an inferior option because the session can be flushed + at any time by openssl. It is included only so curl compiles + under versions of openssl < 0.9.5a. + + WARNING: How curl behaves if it's session is flushed is + untested. + */ +#endif incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); if(incache) { @@ -2810,6 +2654,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) return result; } } +#ifdef HAVE_SSL_GET1_SESSION else { /* Session was incache, so refcount already incremented earlier. * Avoid further increments with each SSL_get1_session() call. @@ -2817,6 +2662,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) */ SSL_SESSION_free(our_ssl_sessionid); } +#endif /* * We check certificates to authenticate the server; otherwise we risk @@ -2825,8 +2671,10 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) * operations. */ - result = servercert(conn, connssl, - (data->set.ssl.verifypeer || data->set.ssl.verifyhost)); + if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost) + (void)servercert(conn, connssl, FALSE); + else + result = servercert(conn, connssl, TRUE); if(!result) connssl->connecting_state = ssl_connect_done; @@ -3064,7 +2912,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ 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 */ + /* http://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 @@ -3087,11 +2935,8 @@ size_t Curl_ossl_version(char *buffer, size_t size) to OpenSSL in all other aspects */ return snprintf(buffer, size, "yassl/%s", YASSL_VERSION); #else /* YASSL_VERSION */ -#ifdef OPENSSL_IS_BORINGSSL - return snprintf(buffer, size, "BoringSSL"); -#else /* OPENSSL_IS_BORINGSSL */ -#if(OPENSSL_VERSION_NUMBER >= 0x905000) +#if(SSLEAY_VERSION_NUMBER >= 0x905000) { char sub[3]; unsigned long ssleay_value; @@ -3119,44 +2964,47 @@ size_t Curl_ossl_version(char *buffer, size_t size) } return snprintf(buffer, size, "%s/%lx.%lx.%lx%s", +#ifdef OPENSSL_IS_BORINGSSL + "BoringSSL" +#else #ifdef LIBRESSL_VERSION_NUMBER "LibreSSL" #else "OpenSSL" #endif +#endif , (ssleay_value>>28)&0xf, (ssleay_value>>20)&0xff, (ssleay_value>>12)&0xff, sub); } -#else /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */ +#else /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */ -#if(OPENSSL_VERSION_NUMBER >= 0x900000) +#if(SSLEAY_VERSION_NUMBER >= 0x900000) return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx", - (OPENSSL_VERSION_NUMBER>>28)&0xff, - (OPENSSL_VERSION_NUMBER>>20)&0xff, - (OPENSSL_VERSION_NUMBER>>12)&0xf); + (SSLEAY_VERSION_NUMBER>>28)&0xff, + (SSLEAY_VERSION_NUMBER>>20)&0xff, + (SSLEAY_VERSION_NUMBER>>12)&0xf); -#else /* (OPENSSL_VERSION_NUMBER >= 0x900000) */ +#else /* (SSLEAY_VERSION_NUMBER >= 0x900000) */ { char sub[2]; sub[1]='\0'; - if(OPENSSL_VERSION_NUMBER&0x0f) { - sub[0]=(OPENSSL_VERSION_NUMBER&0x0f) + 'a' -1; + if(SSLEAY_VERSION_NUMBER&0x0f) { + sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1; } else sub[0]='\0'; return snprintf(buffer, size, "SSL/%x.%x.%x%s", - (OPENSSL_VERSION_NUMBER>>12)&0xff, - (OPENSSL_VERSION_NUMBER>>8)&0xf, - (OPENSSL_VERSION_NUMBER>>4)&0xf, sub); + (SSLEAY_VERSION_NUMBER>>12)&0xff, + (SSLEAY_VERSION_NUMBER>>8)&0xf, + (SSLEAY_VERSION_NUMBER>>4)&0xf, sub); } -#endif /* (OPENSSL_VERSION_NUMBER >= 0x900000) */ -#endif /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */ +#endif /* (SSLEAY_VERSION_NUMBER >= 0x900000) */ +#endif /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */ -#endif /* OPENSSL_IS_BORINGSSL */ #endif /* YASSL_VERSION */ } @@ -3164,9 +3012,8 @@ size_t Curl_ossl_version(char *buffer, size_t size) int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy, size_t length) { - if(data) { + if(data) Curl_ossl_seed(data); /* Initiate the seed if not already done */ - } RAND_bytes(entropy, curlx_uztosi(length)); return 0; /* 0 as in no problem */ } @@ -3182,28 +3029,4 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */ MD5_Update(&MD5pw, tmp, tmplen); MD5_Final(md5sum, &MD5pw); } - -#ifndef OPENSSL_NO_SHA256 -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 - -bool Curl_ossl_cert_status_request(void) -{ -#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ - !defined(OPENSSL_IS_BORINGSSL) - return TRUE; -#else - return FALSE; -#endif -} -#endif /* USE_OPENSSL */ +#endif /* USE_SSLEAY */ diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h index a1f347a05..9f5f3a28f 100644 --- a/lib/vtls/openssl.h +++ b/lib/vtls/openssl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,7 +24,7 @@ #include "curl_setup.h" -#ifdef USE_OPENSSL +#ifdef USE_SSLEAY /* * This header should only be needed to get included by vtls.c and openssl.c */ @@ -72,15 +72,6 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum /* output */, size_t unused); -void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused); - -bool Curl_ossl_cert_status_request(void); - -/* Set the API backend definition to OpenSSL */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL /* this backend supports the CAPATH option */ #define have_curlssl_ca_path 1 @@ -108,13 +99,9 @@ bool Curl_ossl_cert_status_request(void); #define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y) #define curlssl_random(x,y,z) Curl_ossl_random(x,y,z) #define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d) -#ifndef OPENSSL_NO_SHA256 -#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d) -#endif -#define curlssl_cert_status_request() Curl_ossl_cert_status_request() +#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL -#define DEFAULT_CIPHER_SELECTION \ - "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" +#define DEFAULT_CIPHER_SELECTION "ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4" -#endif /* USE_OPENSSL */ +#endif /* USE_SSLEAY */ #endif /* HEADER_CURL_SSLUSE_H */ diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c index 066c055e6..05fcfc208 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -55,7 +55,9 @@ #include "select.h" #include "rawstr.h" #include "polarssl_threadlock.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -118,8 +120,11 @@ static void polarssl_debug(void *context, int level, const char *line) #endif /* ALPN for http2? */ -#ifdef POLARSSL_SSL_ALPN -# define HAS_ALPN +#ifdef USE_NGHTTP2 +# undef HAS_ALPN +# ifdef POLARSSL_SSL_ALPN +# define HAS_ALPN +# endif #endif static Curl_recv polarssl_recv; @@ -284,36 +289,27 @@ polarssl_connect_step1(struct connectdata *conn, switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_1); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_2); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; } @@ -354,23 +350,16 @@ polarssl_connect_step1(struct connectdata *conn, } #ifdef HAS_ALPN - if(data->set.ssl_enable_alpn) { - static const char* protocols[3]; - int cur = 0; - -#ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.ssl_enable_alpn) { + static const char* protocols[] = { + NGHTTP2_PROTO_VERSION_ID, ALPN_HTTP_1_1, NULL + }; + ssl_set_alpn_protocols(&connssl->ssl, protocols); + infof(data, "ALPN, offering %s, %s\n", protocols[0], + protocols[1]); + connssl->asked_for_h2 = TRUE; } -#endif - - protocols[cur++] = ALPN_HTTP_1_1; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); - - protocols[cur] = NULL; - - ssl_set_alpn_protocols(&connssl->ssl, protocols); } #endif @@ -392,37 +381,47 @@ polarssl_connect_step2(struct connectdata *conn, struct ssl_connect_data* connssl = &conn->ssl[sockindex]; char buffer[1024]; +#ifdef HAS_ALPN + const char* next_protocol; +#endif + char errorbuf[128]; errorbuf[0] = 0; conn->recv[sockindex] = polarssl_recv; conn->send[sockindex] = polarssl_send; - ret = ssl_handshake(&connssl->ssl); - - switch(ret) { - case 0: - break; - - case POLARSSL_ERR_NET_WANT_READ: - connssl->connecting_state = ssl_connect_2_reading; - return CURLE_OK; - - case POLARSSL_ERR_NET_WANT_WRITE: - connssl->connecting_state = ssl_connect_2_writing; - return CURLE_OK; - - default: + for(;;) { + if(!(ret = ssl_handshake(&connssl->ssl))) + break; + else if(ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE) { #ifdef POLARSSL_ERROR_C - error_strerror(ret, errorbuf, sizeof(errorbuf)); + error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ - failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", - -ret, errorbuf); - return CURLE_SSL_CONNECT_ERROR; + failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", + -ret, errorbuf); + + return CURLE_SSL_CONNECT_ERROR; + } + else { + if(ret == POLARSSL_ERR_NET_WANT_READ) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + if(ret == POLARSSL_ERR_NET_WANT_WRITE) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + failf(data, "SSL_connect failed with error %d.", ret); + return CURLE_SSL_CONNECT_ERROR; + + } } infof(data, "PolarSSL: Handshake complete, cipher is %s\n", - ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) ); + ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) + ); ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); @@ -455,24 +454,22 @@ polarssl_connect_step2(struct connectdata *conn, #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { - const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl); + next_protocol = ssl_get_alpn_protocol(&connssl->ssl); if(next_protocol != NULL) { infof(data, "ALPN, server accepted to use %s\n", next_protocol); -#ifdef USE_NGHTTP2 - if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + if(strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = NPN_HTTP2; } - else -#endif - if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { - conn->negnpn = CURL_HTTP_VERSION_1_1; + else if(strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = NPN_HTTP1_1; } } - else + else if(connssl->asked_for_h2) { infof(data, "ALPN, server did not agree to a protocol\n"); + } } #endif @@ -490,7 +487,7 @@ polarssl_connect_step3(struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct SessionHandle *data = conn->data; void *old_ssl_sessionid = NULL; - ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn; + ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn ; bool incache; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); @@ -547,6 +544,11 @@ static ssize_t polarssl_send(struct connectdata *conn, return ret; } +void Curl_polarssl_close_all(struct SessionHandle *data) +{ + (void)data; +} + void Curl_polarssl_close(struct connectdata *conn, int sockindex) { rsa_free(&conn->ssl[sockindex].rsa); @@ -587,15 +589,11 @@ void Curl_polarssl_session_free(void *ptr) free(ptr); } -/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and - higher) will be mbed TLS branded.. */ - 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 snprintf(buffer, size, "PolarSSL/%d.%d.%d", version>>24, + (version>>16)&0xff, (version>>8)&0xff); } static CURLcode diff --git a/lib/vtls/polarssl.h b/lib/vtls/polarssl.h index f980dbb2e..57dfb6763 100644 --- a/lib/vtls/polarssl.h +++ b/lib/vtls/polarssl.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,6 +37,10 @@ CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); +/* tell PolarSSL to close down all open information regarding connections (and + thus session ID caching etc) */ +void Curl_polarssl_close_all(struct SessionHandle *data); + /* close a SSL connection */ void Curl_polarssl_close(struct connectdata *conn, int sockindex); @@ -44,9 +48,6 @@ void Curl_polarssl_session_free(void *ptr); size_t Curl_polarssl_version(char *buffer, size_t size); int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); -/* Set the API backend definition to PolarSSL */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL - /* this backend supports the CAPATH option */ #define have_curlssl_ca_path 1 @@ -56,7 +57,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); #define curlssl_connect Curl_polarssl_connect #define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking #define curlssl_session_free(x) Curl_polarssl_session_free(x) -#define curlssl_close_all(x) ((void)x) +#define curlssl_close_all Curl_polarssl_close_all #define curlssl_close Curl_polarssl_close #define curlssl_shutdown(x,y) 0 #define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) @@ -65,6 +66,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); #define curlssl_version Curl_polarssl_version #define curlssl_check_cxn(x) ((void)x, -1) #define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL /* This might cause libcurl to use a weeker random! TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/polarssl_threadlock.c index 62abf43b2..ad1871537 100644 --- a/lib/vtls/polarssl_threadlock.c +++ b/lib/vtls/polarssl_threadlock.c @@ -36,7 +36,10 @@ #endif #include "polarssl_threadlock.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 01bbc6130..a53ff4ad6 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -63,16 +63,18 @@ #include "sendf.h" #include "rawstr.h" #include "url.h" +#include "curl_memory.h" #include "progress.h" #include "share.h" #include "timeval.h" #include "curl_md5.h" #include "warnless.h" #include "curl_base64.h" -#include "curl_printf.h" -/* The last #include files should be: */ -#include "curl_memory.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + +/* The last #include file should be: */ #include "memdebug.h" /* convenience macro to check if this handle is using a shared SSL session */ @@ -276,25 +278,10 @@ void Curl_ssl_cleanup(void) } } -static bool ssl_prefs_check(struct SessionHandle *data) -{ - /* check for CURLOPT_SSLVERSION invalid parameter value */ - if((data->set.ssl.version < 0) - || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) { - failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); - return FALSE; - } - return TRUE; -} - CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex) { CURLcode result; - - if(!ssl_prefs_check(conn->data)) - return CURLE_SSL_CONNECT_ERROR; - /* mark this is being ssl-enabled from here on. */ conn->ssl[sockindex].use = TRUE; conn->ssl[sockindex].state = ssl_connection_negotiating; @@ -312,10 +299,6 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { CURLcode result; - - if(!ssl_prefs_check(conn->data)) - return CURLE_SSL_CONNECT_ERROR; - /* mark this is being ssl requested from here on. */ conn->ssl[sockindex].use = TRUE; #ifdef curlssl_connect_nonblocking @@ -482,8 +465,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, store->sessionid = ssl_sessionid; store->idsize = idsize; store->age = *general_age; /* set current age */ + if(store->name) /* free it if there's one already present */ - free(store->name); + free(store->name); store->name = clone_host; /* clone host name */ store->remote_port = conn->remote_port; /* port number */ @@ -774,78 +758,12 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, size_t size, pem_len; CURLcode pem_read; CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; -#ifdef curlssl_sha256sum - size_t pinkeylen; - char *pinkeycopy, *begin_pos, *end_pos; - unsigned char *sha256sumdigest = NULL, *expectedsha256sumdigest = NULL; -#endif /* if a path wasn't specified, don't pin */ if(!pinnedpubkey) return CURLE_OK; if(!pubkey || !pubkeylen) return result; - -#ifdef curlssl_sha256sum - /* only do this if pinnedpubkey starts with "sha256//", length 8 */ - if(strncmp(pinnedpubkey, "sha256//", 8) == 0) { - /* compute sha256sum of public key */ - sha256sumdigest = malloc(SHA256_DIGEST_LENGTH); - if(!sha256sumdigest) - return CURLE_OUT_OF_MEMORY; - curlssl_sha256sum(pubkey, pubkeylen, - sha256sumdigest, SHA256_DIGEST_LENGTH); - - /* it starts with sha256//, copy so we can modify it */ - pinkeylen = strlen(pinnedpubkey) + 1; - pinkeycopy = malloc(pinkeylen); - if(!pinkeycopy) { - Curl_safefree(sha256sumdigest); - return CURLE_OUT_OF_MEMORY; - } - memcpy(pinkeycopy, pinnedpubkey, pinkeylen); - /* point begin_pos to the copy, and start extracting keys */ - begin_pos = pinkeycopy; - do { - end_pos = strstr(begin_pos, ";sha256//"); - /* - * if there is an end_pos, null terminate, - * otherwise it'll go to the end of the original string - */ - if(end_pos) - end_pos[0] = '\0'; - - /* decode base64 pinnedpubkey, 8 is length of "sha256//" */ - pem_read = Curl_base64_decode(begin_pos + 8, - &expectedsha256sumdigest, &size); - /* if not valid base64, don't bother comparing or freeing */ - if(!pem_read) { - /* compare sha256 digests directly */ - if(SHA256_DIGEST_LENGTH == size && - !memcmp(sha256sumdigest, expectedsha256sumdigest, - SHA256_DIGEST_LENGTH)) { - result = CURLE_OK; - Curl_safefree(expectedsha256sumdigest); - break; - } - Curl_safefree(expectedsha256sumdigest); - } - - /* - * change back the null-terminator we changed earlier, - * and look for next begin - */ - if(end_pos) { - end_pos[0] = ';'; - begin_pos = strstr(end_pos, "sha256//"); - } - } while(end_pos && begin_pos); - Curl_safefree(sha256sumdigest); - Curl_safefree(pinkeycopy); - return result; - } -#endif - fp = fopen(pinnedpubkey, "rb"); if(!fp) return result; @@ -912,11 +830,10 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, return result; } -#ifndef CURL_DISABLE_CRYPTO_AUTH -CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) +void Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) { #ifdef curlssl_md5sum curlssl_md5sum(tmp, tmplen, md5sum, md5len); @@ -926,37 +843,9 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ (void) md5len; MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); - if(!MD5pw) - return CURLE_OUT_OF_MEMORY; Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen)); Curl_MD5_final(MD5pw, md5sum); #endif - return CURLE_OK; -} -#endif - -/* - * Check whether the SSL backend supports the status_request extension. - */ -bool Curl_ssl_cert_status_request(void) -{ -#ifdef curlssl_cert_status_request - return curlssl_cert_status_request(); -#else - return FALSE; -#endif -} - -/* - * Check whether the SSL backend supports false start. - */ -bool Curl_ssl_false_start(void) -{ -#ifdef curlssl_false_start - return curlssl_false_start(); -#else - return FALSE; -#endif } #endif /* USE_SSL */ diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 2349e5b93..19ef1cd6e 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,8 +30,8 @@ #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 */ +#include "curl_schannel.h" /* Schannel SSPI version */ +#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */ #ifndef MAX_PINNED_PUBKEY_SIZE #define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ @@ -41,10 +41,6 @@ #define MD5_DIGEST_LENGTH 16 /* fixed size */ #endif -#ifndef SHA256_DIGEST_LENGTH -#define SHA256_DIGEST_LENGTH 32 /* fixed size */ -#endif - /* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" @@ -112,24 +108,17 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); in */ int Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer, size_t length); -CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len); +void Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); /* Check pinned public key. */ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, const unsigned char *pubkey, size_t pubkeylen); -bool Curl_ssl_cert_status_request(void); - -bool Curl_ssl_false_start(void); - #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ #else -/* Set the API backend definition to none */ -#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE - /* When SSL support is not present, just define away these function calls */ #define Curl_ssl_init() 1 #define Curl_ssl_cleanup() Curl_nop_stmt @@ -150,8 +139,7 @@ bool Curl_ssl_false_start(void); #define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN #define Curl_ssl_kill_session(x) Curl_nop_stmt #define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) -#define Curl_ssl_cert_status_request() FALSE -#define Curl_ssl_false_start() FALSE +#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE #endif #endif /* HEADER_CURL_VTLS_H */ diff --git a/lib/wildcard.c b/lib/wildcard.c index 6f55839db..7130d5e49 100644 --- a/lib/wildcard.c +++ b/lib/wildcard.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2010, 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 @@ -25,7 +25,10 @@ #include "wildcard.h" #include "llist.h" #include "fileinfo.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -59,10 +62,15 @@ void Curl_wildcard_dtor(struct WildcardData *wc) wc->filelist = NULL; } - free(wc->path); - wc->path = NULL; - free(wc->pattern); - wc->pattern = NULL; + if(wc->path) { + free(wc->path); + wc->path = NULL; + } + + if(wc->pattern) { + free(wc->pattern); + wc->pattern = NULL; + } wc->customptr = NULL; wc->state = CURLWC_INIT; diff --git a/lib/x509asn1.c b/lib/x509asn1.c index a3dfd646b..af08cee54 100644 --- a/lib/x509asn1.c +++ b/lib/x509asn1.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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,8 +22,7 @@ #include "curl_setup.h" -#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_CYASSL) +#if defined(USE_GSKIT) || defined(USE_NSS) #include <curl/curl.h> #include "urldata.h" @@ -34,7 +33,10 @@ #include "inet_pton.h" #include "curl_base64.h" #include "x509asn1.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -210,6 +212,7 @@ static const char * octet2str(const char * beg, const char * end) } static const char * bit2str(const char * beg, const char * end) + { /* Convert an ASN.1 bit string to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -298,10 +301,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) case 4: wc = (wc << 8) | *(const unsigned char *) from++; wc = (wc << 8) | *(const unsigned char *) from++; - /* fallthrough */ case 2: wc = (wc << 8) | *(const unsigned char *) from++; - /* fallthrough */ default: /* case 1: */ wc = (wc << 8) | *(const unsigned char *) from++; } @@ -539,6 +540,8 @@ static const char * UTime2str(const char * beg, const char * end) const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) { + static const char zero = '\0'; + /* Convert an ASN.1 element to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -559,7 +562,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) case CURL_ASN1_OCTET_STRING: return octet2str(elem->beg, elem->end); case CURL_ASN1_NULL: - return strdup(""); + return strdup(&zero); case CURL_ASN1_OBJECT_IDENTIFIER: return OID2str(elem->beg, elem->end, TRUE); case CURL_ASN1_UTC_TIME: @@ -821,7 +824,7 @@ static void do_pubkey(struct SessionHandle * data, int certnum, /* Compute key length. */ for(q = elem.beg; !*q && q < elem.end; q++) ; - len = (unsigned long)((elem.end - q) * 8); + len = (elem.end - q) * 8; if(len) for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1) len--; @@ -1024,7 +1027,7 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, return CURLE_OK; } -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL */ +#endif /* USE_GSKIT or USE_NSS */ #if defined(USE_GSKIT) @@ -1116,7 +1119,8 @@ CURLcode Curl_verifyhost(struct connectdata * conn, if(len > 0) if(strlen(dnsname) == (size_t) len) i = Curl_cert_hostcheck((const char *) dnsname, conn->host.name); - free(dnsname); + if(dnsname) + free(dnsname); if(!i) return CURLE_PEER_FAILED_VERIFICATION; matched = i; diff --git a/lib/x509asn1.h b/lib/x509asn1.h index eb23e506a..075c424f3 100644 --- a/lib/x509asn1.h +++ b/lib/x509asn1.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, 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 @@ -25,8 +25,7 @@ #include "curl_setup.h" -#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_CYASSL) +#if defined(USE_GSKIT) || defined(USE_NSS) #include "urldata.h" @@ -128,5 +127,5 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum, CURLcode Curl_verifyhost(struct connectdata * conn, const char * beg, const char * end); -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL */ +#endif /* USE_GSKIT or USE_NSS */ #endif /* HEADER_CURL_X509ASN1_H */ |