Browse Source

Merge branch 'upstream-curl' into update-curl

* upstream-curl:
  curl 2019-05-22 (885ce314)
Brad King 6 years ago
parent
commit
a39138ef9a
100 changed files with 3168 additions and 1970 deletions
  1. 50 2
      Utilities/cmcurl/CMake/CurlTests.c
  2. 2 2
      Utilities/cmcurl/CMake/FindGSS.cmake
  3. 50 17
      Utilities/cmcurl/CMake/OtherTests.cmake
  4. 39 27
      Utilities/cmcurl/CMakeLists.txt
  5. 1 1
      Utilities/cmcurl/COPYING
  6. 58 8
      Utilities/cmcurl/include/curl/curl.h
  7. 6 6
      Utilities/cmcurl/include/curl/curlver.h
  8. 5 9
      Utilities/cmcurl/include/curl/typecheck-gcc.h
  9. 5 2
      Utilities/cmcurl/include/curl/urlapi.h
  10. 10 9
      Utilities/cmcurl/lib/Makefile.inc
  11. 569 0
      Utilities/cmcurl/lib/altsvc.c
  12. 77 0
      Utilities/cmcurl/lib/altsvc.h
  13. 25 7
      Utilities/cmcurl/lib/amigaos.c
  14. 8 2
      Utilities/cmcurl/lib/amigaos.h
  15. 140 17
      Utilities/cmcurl/lib/asyn-ares.c
  16. 50 20
      Utilities/cmcurl/lib/asyn-thread.c
  17. 26 10
      Utilities/cmcurl/lib/asyn.h
  18. 20 13
      Utilities/cmcurl/lib/base64.c
  19. 22 16
      Utilities/cmcurl/lib/conncache.c
  20. 4 4
      Utilities/cmcurl/lib/conncache.h
  21. 67 47
      Utilities/cmcurl/lib/connect.c
  22. 1 8
      Utilities/cmcurl/lib/connect.h
  23. 129 73
      Utilities/cmcurl/lib/cookie.c
  24. 11 2
      Utilities/cmcurl/lib/cookie.h
  25. 16 16
      Utilities/cmcurl/lib/curl_addrinfo.c
  26. 5 8
      Utilities/cmcurl/lib/curl_addrinfo.h
  27. 8 2
      Utilities/cmcurl/lib/curl_config.h.cmake
  28. 5 5
      Utilities/cmcurl/lib/curl_endian.c
  29. 4 11
      Utilities/cmcurl/lib/curl_fnmatch.c
  30. 55 0
      Utilities/cmcurl/lib/curl_get_line.c
  31. 7 11
      Utilities/cmcurl/lib/curl_get_line.h
  32. 3 3
      Utilities/cmcurl/lib/curl_gssapi.c
  33. 1 15
      Utilities/cmcurl/lib/curl_gssapi.h
  34. 3 1
      Utilities/cmcurl/lib/curl_md4.h
  35. 5 5
      Utilities/cmcurl/lib/curl_md5.h
  36. 2 2
      Utilities/cmcurl/lib/curl_memory.h
  37. 6 6
      Utilities/cmcurl/lib/curl_multibyte.c
  38. 32 37
      Utilities/cmcurl/lib/curl_ntlm_core.c
  39. 1 3
      Utilities/cmcurl/lib/curl_ntlm_core.h
  40. 67 19
      Utilities/cmcurl/lib/curl_ntlm_wb.c
  41. 7 4
      Utilities/cmcurl/lib/curl_ntlm_wb.h
  42. 5 1
      Utilities/cmcurl/lib/curl_path.c
  43. 4 12
      Utilities/cmcurl/lib/curl_printf.h
  44. 5 4
      Utilities/cmcurl/lib/curl_rtmp.c
  45. 20 20
      Utilities/cmcurl/lib/curl_sasl.c
  46. 20 9
      Utilities/cmcurl/lib/curl_setup.h
  47. 5 6
      Utilities/cmcurl/lib/curlx.h
  48. 4 7
      Utilities/cmcurl/lib/dict.c
  49. 87 40
      Utilities/cmcurl/lib/doh.c
  50. 9 1
      Utilities/cmcurl/lib/doh.h
  51. 27 84
      Utilities/cmcurl/lib/easy.c
  52. 1 1
      Utilities/cmcurl/lib/escape.c
  53. 15 14
      Utilities/cmcurl/lib/file.c
  54. 3 2
      Utilities/cmcurl/lib/fileinfo.c
  55. 7 7
      Utilities/cmcurl/lib/formdata.c
  56. 10 1
      Utilities/cmcurl/lib/formdata.h
  57. 47 56
      Utilities/cmcurl/lib/ftp.c
  58. 1 2
      Utilities/cmcurl/lib/ftp.h
  59. 2 5
      Utilities/cmcurl/lib/ftplistparser.c
  60. 4 4
      Utilities/cmcurl/lib/getinfo.c
  61. 21 7
      Utilities/cmcurl/lib/gopher.c
  62. 4 4
      Utilities/cmcurl/lib/hostasyn.c
  63. 4 7
      Utilities/cmcurl/lib/hostcheck.c
  64. 56 97
      Utilities/cmcurl/lib/hostip.c
  65. 6 13
      Utilities/cmcurl/lib/hostip.h
  66. 2 2
      Utilities/cmcurl/lib/hostip4.c
  67. 8 6
      Utilities/cmcurl/lib/hostip6.c
  68. 318 174
      Utilities/cmcurl/lib/http.c
  69. 5 4
      Utilities/cmcurl/lib/http.h
  70. 60 16
      Utilities/cmcurl/lib/http2.c
  71. 5 2
      Utilities/cmcurl/lib/http2.h
  72. 3 2
      Utilities/cmcurl/lib/http_digest.c
  73. 6 6
      Utilities/cmcurl/lib/http_digest.h
  74. 107 25
      Utilities/cmcurl/lib/http_negotiate.c
  75. 4 4
      Utilities/cmcurl/lib/http_negotiate.h
  76. 24 16
      Utilities/cmcurl/lib/http_ntlm.c
  77. 5 5
      Utilities/cmcurl/lib/http_ntlm.h
  78. 2 2
      Utilities/cmcurl/lib/http_proxy.c
  79. 14 45
      Utilities/cmcurl/lib/if2ip.c
  80. 2 4
      Utilities/cmcurl/lib/if2ip.h
  81. 19 22
      Utilities/cmcurl/lib/imap.c
  82. 6 6
      Utilities/cmcurl/lib/inet_ntop.c
  83. 2 1
      Utilities/cmcurl/lib/inet_pton.c
  84. 13 9
      Utilities/cmcurl/lib/ldap.c
  85. 6 6
      Utilities/cmcurl/lib/libcurl.rc
  86. 60 54
      Utilities/cmcurl/lib/md4.c
  87. 84 90
      Utilities/cmcurl/lib/md5.c
  88. 69 85
      Utilities/cmcurl/lib/memdebug.c
  89. 59 64
      Utilities/cmcurl/lib/memdebug.h
  90. 9 85
      Utilities/cmcurl/lib/mime.c
  91. 24 3
      Utilities/cmcurl/lib/mime.h
  92. 1 1
      Utilities/cmcurl/lib/mprintf.c
  93. 197 296
      Utilities/cmcurl/lib/multi.c
  94. 14 34
      Utilities/cmcurl/lib/multihandle.h
  95. 16 17
      Utilities/cmcurl/lib/multiif.h
  96. 13 3
      Utilities/cmcurl/lib/netrc.c
  97. 10 1
      Utilities/cmcurl/lib/netrc.h
  98. 2 2
      Utilities/cmcurl/lib/non-ascii.c
  99. 4 9
      Utilities/cmcurl/lib/openldap.c
  100. 26 15
      Utilities/cmcurl/lib/parsedate.c

+ 50 - 2
Utilities/cmcurl/CMake/CurlTests.c

@@ -240,6 +240,7 @@ int main()
 #ifndef inet_ntoa_r
   func_type func;
   func = (func_type)inet_ntoa_r;
+  (void)func;
 #endif
   return 0;
 }
@@ -255,6 +256,7 @@ int main()
 #ifndef inet_ntoa_r
   func_type func;
   func = (func_type)&inet_ntoa_r;
+  (void)func;
 #endif
   return 0;
 }
@@ -553,8 +555,8 @@ main() {
 #include <time.h>
 int
 main() {
-  struct timespec ts = {0, 0}; 
-  clock_gettime(CLOCK_MONOTONIC, &ts); 
+  struct timespec ts = {0, 0};
+  clock_gettime(CLOCK_MONOTONIC, &ts);
   return 0;
 }
 #endif
@@ -565,3 +567,49 @@ main() {
   return 0;
 }
 #endif
+#ifdef HAVE_VARIADIC_MACROS_C99
+#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
+#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = c99_vmacro3(1, 2, 3);
+  int res2 = c99_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif
+#ifdef HAVE_VARIADIC_MACROS_GCC
+#define gcc_vmacro3(first, args...) fun3(first, args)
+#define gcc_vmacro2(first, args...) fun2(first, args)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = gcc_vmacro3(1, 2, 3);
+  int res2 = gcc_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif

+ 2 - 2
Utilities/cmcurl/CMake/FindGSS.cmake

@@ -68,7 +68,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # should also work in an odd case when multiple directories are given
       string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
       string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
-      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
 
       foreach(_flag ${_GSS_CFLAGS})
         if(_flag MATCHES "^-I.*")
@@ -91,7 +91,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # this script gives us libraries and link directories. Blah. We have to deal with it.
       string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
       string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
 
       foreach(_flag ${_GSS_LIB_FLAGS})
         if(_flag MATCHES "^-l.*")

+ 50 - 17
Utilities/cmcurl/CMake/OtherTests.cmake

@@ -24,6 +24,8 @@ else()
   add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
 endif()
 
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
 check_c_source_compiles("${_source_epilogue}
 int main(void) {
     recv(0, 0, 0, 0);
@@ -177,23 +179,6 @@ int main(void) {
   return 0;
 }" HAVE_STRUCT_TIMEVAL)
 
-
-include(CheckCSourceRuns)
-# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
-if(NOT APPLE)
-  set(CMAKE_REQUIRED_FLAGS)
-  if(HAVE_SYS_POLL_H)
-    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-  endif()
-  check_c_source_runs("
-    #ifdef HAVE_SYS_POLL_H
-    #  include <sys/poll.h>
-    #endif
-    int main(void) {
-      return poll((void *)0, 0, 10 /*ms*/);
-    }" HAVE_POLL_FINE)
-endif()
-
 set(HAVE_SIG_ATOMIC_T 1)
 set(CMAKE_REQUIRED_FLAGS)
 if(HAVE_SIGNAL_H)
@@ -229,3 +214,51 @@ check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
 if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
   set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
 endif()
+
+unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
+
+if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+  # if not cross-compilation...
+  include(CheckCSourceRuns)
+  set(CMAKE_REQUIRED_FLAGS "")
+  if(HAVE_SYS_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+  elseif(HAVE_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
+  endif()
+  check_c_source_runs("
+    #include <stdlib.h>
+    #include <sys/time.h>
+
+    #ifdef HAVE_SYS_POLL_H
+    #  include <sys/poll.h>
+    #elif  HAVE_POLL_H
+    #  include <poll.h>
+    #endif
+
+    int main(void)
+    {
+        if(0 != poll(0, 0, 10)) {
+          return 1; /* fail */
+        }
+        else {
+          /* detect the 10.12 poll() breakage */
+          struct timeval before, after;
+          int rc;
+          size_t us;
+
+          gettimeofday(&before, NULL);
+          rc = poll(NULL, 0, 500);
+          gettimeofday(&after, NULL);
+
+          us = (after.tv_sec - before.tv_sec) * 1000000 +
+            (after.tv_usec - before.tv_usec);
+
+          if(us < 400000) {
+            return 1;
+          }
+        }
+        return 0;
+    }" HAVE_POLL_FINE)
+endif()
+

+ 39 - 27
Utilities/cmcurl/CMakeLists.txt

@@ -90,7 +90,7 @@ endif()
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -143,7 +143,6 @@ string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
   CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
 string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
 
-include_regular_expression("^.*$")    # Sukender: Is it necessary?
 
 # Setup package meta-data
 # SET(PACKAGE "curl")
@@ -158,7 +157,6 @@ endif()
 set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 set(OS "\"${CMAKE_SYSTEM_NAME}\"")
 
-include_directories(${PROJECT_BINARY_DIR}/include/curl)
 include_directories(${CURL_SOURCE_DIR}/include)
 
 option(CURL_WERROR "Turn compiler warnings into errors" OFF)
@@ -193,11 +191,7 @@ endif()
 
 if(ENABLE_DEBUG)
   # DEBUGBUILD will be defined only for Debug builds
-  if(NOT CMAKE_VERSION VERSION_LESS 3.0)
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
-  else()
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
-  endif()
+  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
   set(ENABLE_CURLDEBUG ON)
 endif()
 
@@ -393,10 +387,10 @@ if(WIN32)
 endif()
 
 # check SSL libraries
-# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
+# TODO support GNUTLS, NSS, POLARSSL, CYASSL
 
 if(APPLE)
-  option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
+  option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
 endif()
 if(WIN32)
   option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
@@ -406,13 +400,13 @@ endif()
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 
 set(openssl_default ON)
-if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
+if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
   set(openssl_default OFF)
 endif()
 
 count_true(enabled_ssl_options_count
   CMAKE_USE_WINSSL
-  CMAKE_USE_DARWINSSL
+  CMAKE_USE_SECTRANSP
   CMAKE_USE_OPENSSL
   CMAKE_USE_MBEDTLS
 )
@@ -432,6 +426,10 @@ if(CURL_WINDOWS_SSPI)
 endif()
 
 if(CMAKE_USE_DARWINSSL)
+  message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.")
+endif()
+
+if(CMAKE_USE_SECTRANSP)
   find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
   if(NOT COREFOUNDATION_FRAMEWORK)
       message(FATAL_ERROR "CoreFoundation framework not found")
@@ -443,7 +441,7 @@ if(CMAKE_USE_DARWINSSL)
   endif()
 
   set(SSL_ENABLED ON)
-  set(USE_DARWINSSL ON)
+  set(USE_SECTRANSP ON)
   list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
 endif()
 
@@ -578,6 +576,7 @@ if(NOT CURL_DISABLE_LDAP)
         list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
       endif()
       check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
       if(NOT_NEED_LBER_H)
         set(NEED_LBER_H OFF)
@@ -685,6 +684,7 @@ if(CMAKE_USE_LIBSSH2)
     check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
     check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
     set(CMAKE_EXTRA_INCLUDE_FILES "")
+    unset(CMAKE_REQUIRED_LIBRARIES)
   endif()
 endif()
 
@@ -699,7 +699,7 @@ if(CMAKE_USE_GSSAPI)
 
     message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
 
-    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES})
+    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR})
     check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
     check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
     check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
@@ -732,10 +732,11 @@ if(CMAKE_USE_GSSAPI)
       if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
         set(HAVE_OLD_GSSMIT ON)
       endif()
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
     endif()
 
-    include_directories(${GSS_INCLUDE_DIRECTORIES})
+    include_directories(${GSS_INCLUDE_DIR})
     link_directories(${GSS_LINK_DIRECTORIES})
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
@@ -942,12 +943,8 @@ endif()
 
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-# poll on macOS is unreliable, it first did not exist, then was broken until
-# fixed in 10.9 only to break again in 10.12.
-if(NOT APPLE)
-  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
-endif()
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
+check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
@@ -1003,6 +1000,8 @@ check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
 check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
+check_symbol_exists(getpeername    "${CURL_INCLUDES}" HAVE_GETPEERNAME)
+check_symbol_exists(getsockname    "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
 check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
@@ -1086,6 +1085,8 @@ foreach(CURL_TEST
     HAVE_INET_NTOA_R_DECL_REENTRANT
     HAVE_GETADDRINFO
     HAVE_FILE_OFFSET_BITS
+    HAVE_VARIADIC_MACROS_C99
+    HAVE_VARIADIC_MACROS_GCC
     )
   curl_internal_test(${CURL_TEST})
 endforeach()
@@ -1247,7 +1248,7 @@ if(CURL_WERROR)
 endif()
 
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
-function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
+function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
   file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
   string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
@@ -1311,10 +1312,7 @@ endfunction()
 
 # Clear list and try to detect available features
 set(_items)
-_add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
-_add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
-_add_if("DarwinSSL"     SSL_ENABLED AND USE_DARWINSSL)
-_add_if("mbedTLS"       SSL_ENABLED AND USE_MBEDTLS)
+_add_if("SSL"           SSL_ENABLED)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("libz"          HAVE_LIBZ)
@@ -1332,7 +1330,7 @@ _add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 # NTLM support requires crypto function adaptions from various SSL libs
 # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS))
   _add_if("NTLM"        1)
   # TODO missing option (autoconf: --enable-ntlm-wb)
   _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
@@ -1371,10 +1369,24 @@ _add_if("SCP"           USE_LIBSSH2)
 _add_if("SFTP"          USE_LIBSSH2)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTMP"          USE_LIBRTMP)
-list(SORT _items)
+if(_items)
+  list(SORT _items)
+endif()
 string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 
+# Clear list and collect SSL backends
+set(_items)
+_add_if("WinSSL"           SSL_ENABLED AND USE_WINDOWS_SSPI)
+_add_if("OpenSSL"          SSL_ENABLED AND USE_OPENSSL)
+_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
+_add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
+if(_items)
+  list(SORT _items)
+endif()
+string(REPLACE ";" " " SSL_BACKENDS "${_items}")
+message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
+
 # curl-config needs the following options to be set.
 set(CC                      "${CMAKE_C_COMPILER}")
 # TODO probably put a -D... options here?

+ 1 - 1
Utilities/cmcurl/COPYING

@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 
-Copyright (c) 1996 - 2018, Daniel Stenberg, <[email protected]>, and many
+Copyright (c) 1996 - 2019, Daniel Stenberg, <[email protected]>, and many
 contributors, see the THANKS file.
 
 All rights reserved.

+ 58 - 8
Utilities/cmcurl/include/curl/curl.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -91,6 +91,11 @@
 #include <support/SupportDefs.h>
 #endif
 
+/* Compatibility for non-Clang compilers */
+#ifndef __has_declspec_attribute
+#  define __has_declspec_attribute(x) 0
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -109,7 +114,9 @@ typedef void CURLSH;
 
 #ifdef CURL_STATICLIB
 #  define CURL_EXTERN
-#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+#elif defined(WIN32) || defined(__SYMBIAN32__) || \
+     (__has_declspec_attribute(dllexport) && \
+      __has_declspec_attribute(dllimport))
 #  if defined(BUILDING_LIBCURL)
 #    define CURL_EXTERN  __declspec(dllexport)
 #  else
@@ -144,8 +151,8 @@ typedef enum {
   CURLSSLBACKEND_POLARSSL = 6,
   CURLSSLBACKEND_WOLFSSL = 7,
   CURLSSLBACKEND_SCHANNEL = 8,
-  CURLSSLBACKEND_DARWINSSL = 9,
-  CURLSSLBACKEND_AXTLS = 10,
+  CURLSSLBACKEND_SECURETRANSPORT = 9,
+  CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
   CURLSSLBACKEND_MBEDTLS = 11,
   CURLSSLBACKEND_MESALINK = 12
 } curl_sslbackend;
@@ -153,7 +160,10 @@ typedef enum {
 /* aliases for library clones and renames */
 #define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 #define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+
+/* deprecated names: */
 #define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
 
 struct curl_httppost {
   struct curl_httppost *next;       /* next entry in the list */
@@ -280,7 +290,7 @@ typedef enum {
 struct curl_fileinfo {
   char *filename;
   curlfiletype filetype;
-  time_t time;
+  time_t time; /* always zero! */
   unsigned int perm;
   int uid;
   int gid;
@@ -355,11 +365,21 @@ typedef int (*curl_seek_callback)(void *instream,
    signal libcurl to pause sending data on the current transfer. */
 #define CURL_READFUNC_PAUSE 0x10000001
 
+/* Return code for when the trailing headers' callback has terminated
+   without any errors*/
+#define CURL_TRAILERFUNC_OK 0
+/* Return code for when was an error in the trailing header's list and we
+  want to abort the request */
+#define CURL_TRAILERFUNC_ABORT 1
+
 typedef size_t (*curl_read_callback)(char *buffer,
                                       size_t size,
                                       size_t nitems,
                                       void *instream);
 
+typedef int (*curl_trailer_callback)(struct curl_slist **list,
+                                      void *userdata);
+
 typedef enum {
   CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
   CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
@@ -585,9 +605,6 @@ typedef enum {
   CURL_LAST /* never use! */
 } CURLcode;
 
-/* added in 7.62.0 */
-#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
-
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
@@ -602,6 +619,9 @@ typedef enum {
 #define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 #define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 
+/* The following were added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
 /* The following were added in 7.21.5, April 2011 */
 #define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 
@@ -861,6 +881,14 @@ typedef enum {
 #define CURLHEADER_UNIFIED  0
 #define CURLHEADER_SEPARATE (1<<0)
 
+/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
+#define CURLALTSVC_IMMEDIATELY  (1<<0)
+#define CURLALTSVC_ALTUSED      (1<<1)
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1           (1<<3)
+#define CURLALTSVC_H2           (1<<4)
+#define CURLALTSVC_H3           (1<<5)
+
 /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 #define CURLPROTO_HTTP   (1<<0)
 #define CURLPROTO_HTTPS  (1<<1)
@@ -1872,6 +1900,27 @@ typedef enum {
   /* Time in ms between connection upkeep calls for long-lived connections. */
   CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
 
+  /* Specify URL using CURL URL API. */
+  CINIT(CURLU, OBJECTPOINT, 282),
+
+  /* add trailing data just after no more data is available */
+  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+
+  /* pointer to be passed to HTTP_TRAILER_FUNCTION */
+  CINIT(TRAILERDATA, OBJECTPOINT, 284),
+
+  /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+  CINIT(HTTP09_ALLOWED, LONG, 285),
+
+  /* alt-svc control bitmask */
+  CINIT(ALTSVC_CTRL, LONG, 286),
+
+  /* alt-svc cache file name to possibly read from/write to */
+  CINIT(ALTSVC, STRINGPOINT, 287),
+
+  /* maximum age of a connection to consider it for reuse (in seconds) */
+  CINIT(MAXAGE_CONN, LONG, 288),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -2734,6 +2783,7 @@ typedef struct {
 #define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 #define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 #define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
+#define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 
  /*
  * NAME curl_version_info()

+ 6 - 6
Utilities/cmcurl/include/curl/curlver.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,16 +26,16 @@
    a script at release-time. This was made its own header file in 7.11.2 */
 
 /* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <[email protected]>."
+#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <[email protected]>."
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.62.0"
+#define LIBCURL_VERSION "7.65.0"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 62
+#define LIBCURL_VERSION_MINOR 65
 #define LIBCURL_VERSION_PATCH 0
 
 /* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x073E00
+#define LIBCURL_VERSION_NUM 0x074100
 
 /*
  * This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
  */
 #define LIBCURL_TIMESTAMP "[unreleased]"
 
-#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
+#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #define CURL_AT_LEAST_VERSION(x,y,z) \
   (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 

+ 5 - 9
Utilities/cmcurl/include/curl/typecheck-gcc.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -113,7 +113,6 @@ __extension__ ({                                                              \
 })
 
 /* wraps curl_easy_getinfo() with typechecking */
-/* FIXME: don't allow const pointers */
 #define curl_easy_getinfo(handle, info, arg)                                  \
 __extension__ ({                                                              \
   __typeof__(info) _curl_info = info;                                         \
@@ -146,9 +145,8 @@ __extension__ ({                                                              \
   curl_easy_getinfo(handle, _curl_info, arg);                                 \
 })
 
-/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
- * for now just make sure that the functions are called with three
- * arguments
+/*
+ * For now, just make sure that the functions are called with three arguments
  */
 #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
@@ -256,6 +254,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
 #define _curl_is_string_option(option)                                        \
   ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
    (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+   (option) == CURLOPT_ALTSVC ||                                              \
    (option) == CURLOPT_CAINFO ||                                              \
    (option) == CURLOPT_CAPATH ||                                              \
    (option) == CURLOPT_COOKIE ||                                              \
@@ -363,6 +362,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    (option) == CURLOPT_WRITEDATA ||                                           \
    (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
+   (option) == CURLOPT_CURLU ||                                               \
    0)
 
 /* evaluates to true if option takes a POST data argument (void* or char*) */
@@ -504,10 +504,6 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    _curl_is_arr((expr), char) ||                                              \
    _curl_is_arr((expr), unsigned char))
 
-/* FIXME: the whole callback checking is messy...
- * The idea is to tolerate char vs. void and const vs. not const
- * pointers in arguments at least
- */
 /* helper: __builtin_types_compatible_p distinguishes between functions and
  * function pointers, hide it */
 #define _curl_callback_compatible(func, type)                                 \

+ 5 - 2
Utilities/cmcurl/include/curl/urlapi.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  ***************************************************************************/
 
+#include "curl.h"
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -58,7 +60,8 @@ typedef enum {
   CURLUPART_PORT,
   CURLUPART_PATH,
   CURLUPART_QUERY,
-  CURLUPART_FRAGMENT
+  CURLUPART_FRAGMENT,
+  CURLUPART_ZONEID /* added in 7.65.0 */
 } CURLUPart;
 
 #define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */

+ 10 - 9
Utilities/cmcurl/lib/Makefile.inc

@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,13 +28,13 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c         \
 LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
 
 LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
-  vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c               \
+  vtls/polarssl.c vtls/polarssl_threadlock.c                            \
   vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c                  \
-  vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
+  vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
 
 LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h                \
-  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h   \
-  vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h           \
+  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h                \
+  vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h           \
   vtls/mbedtls.h vtls/mesalink.h
 
 LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
@@ -52,10 +52,10 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
-  curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
+  curl_multibyte.c hostcheck.c conncache.c dotdot.c                     \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c      \
   mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c  \
-  doh.c urlapi.c
+  doh.c urlapi.c curl_get_line.c altsvc.c
 
 LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
@@ -72,10 +72,11 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h           \
   http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h             \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
-  curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
+  curl_setup_once.h multihandle.h setup-vms.h dotdot.h                  \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
   curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h     \
-  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h
+  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h        \
+  curl_get_line.h altsvc.h
 
 LIB_RCFILES = libcurl.rc
 

+ 569 - 0
Utilities/cmcurl/lib/altsvc.c

@@ -0,0 +1,569 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <[email protected]>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ * The Alt-Svc: header is defined in RFC 7838:
+ * https://tools.ietf.org/html/rfc7838
+ */
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "urldata.h"
+#include "altsvc.h"
+#include "curl_get_line.h"
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.h"
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MAX_ALTSVC_LINE 4095
+#define MAX_ALTSVC_DATELENSTR "64"
+#define MAX_ALTSVC_DATELEN 64
+#define MAX_ALTSVC_HOSTLENSTR "512"
+#define MAX_ALTSVC_HOSTLEN 512
+#define MAX_ALTSVC_ALPNLENSTR "10"
+#define MAX_ALTSVC_ALPNLEN 10
+
+static enum alpnid alpn2alpnid(char *name)
+{
+  if(strcasecompare(name, "h1"))
+    return ALPN_h1;
+  if(strcasecompare(name, "h2"))
+    return ALPN_h2;
+  if(strcasecompare(name, "h2c"))
+    return ALPN_h2c;
+  if(strcasecompare(name, "h3"))
+    return ALPN_h3;
+  return ALPN_none; /* unknown, probably rubbish input */
+}
+
+/* Given the ALPN ID, return the name */
+const char *Curl_alpnid2str(enum alpnid id)
+{
+  switch(id) {
+  case ALPN_h1:
+    return "h1";
+  case ALPN_h2:
+    return "h2";
+  case ALPN_h2c:
+    return "h2c";
+  case ALPN_h3:
+    return "h3";
+  default:
+    return ""; /* bad */
+  }
+}
+
+
+static void altsvc_free(struct altsvc *as)
+{
+  free(as->srchost);
+  free(as->dsthost);
+  free(as);
+}
+
+static struct altsvc *altsvc_createid(const char *srchost,
+                                      const char *dsthost,
+                                      enum alpnid srcalpnid,
+                                      enum alpnid dstalpnid,
+                                      unsigned int srcport,
+                                      unsigned int dstport)
+{
+  struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+  if(!as)
+    return NULL;
+
+  as->srchost = strdup(srchost);
+  if(!as->srchost)
+    goto error;
+  as->dsthost = strdup(dsthost);
+  if(!as->dsthost)
+    goto error;
+
+  as->srcalpnid = srcalpnid;
+  as->dstalpnid = dstalpnid;
+  as->srcport = curlx_ultous(srcport);
+  as->dstport = curlx_ultous(dstport);
+
+  return as;
+  error:
+  altsvc_free(as);
+  return NULL;
+}
+
+static struct altsvc *altsvc_create(char *srchost,
+                                    char *dsthost,
+                                    char *srcalpn,
+                                    char *dstalpn,
+                                    unsigned int srcport,
+                                    unsigned int dstport)
+{
+  enum alpnid dstalpnid = alpn2alpnid(dstalpn);
+  enum alpnid srcalpnid = alpn2alpnid(srcalpn);
+  if(!srcalpnid || !dstalpnid)
+    return NULL;
+  return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid,
+                         srcport, dstport);
+}
+
+/* only returns SERIOUS errors */
+static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
+{
+  /* Example line:
+     h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
+   */
+  char srchost[MAX_ALTSVC_HOSTLEN + 1];
+  char dsthost[MAX_ALTSVC_HOSTLEN + 1];
+  char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char date[MAX_ALTSVC_DATELEN + 1];
+  unsigned int srcport;
+  unsigned int dstport;
+  unsigned int prio;
+  unsigned int persist;
+  int rc;
+
+  rc = sscanf(line,
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
+              srcalpn, srchost, &srcport,
+              dstalpn, dsthost, &dstport,
+              date, &persist, &prio);
+  if(9 == rc) {
+    struct altsvc *as;
+    time_t expires = curl_getdate(date, NULL);
+    as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
+    if(as) {
+      as->expires = expires;
+      as->prio = prio;
+      as->persist = persist ? 1 : 0;
+      Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+      asi->num++; /* one more entry */
+    }
+  }
+
+  return CURLE_OK;
+}
+
+/*
+ * Load alt-svc entries from the given file. The text based line-oriented file
+ * format is documented here:
+ * https://github.com/curl/curl/wiki/QUIC-implementation
+ *
+ * This function only returns error on major problems that prevents alt-svc
+ * handling to work completely. It will ignore individual syntactical errors
+ * etc.
+ */
+static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result = CURLE_OK;
+  char *line = NULL;
+  FILE *fp = fopen(file, FOPEN_READTEXT);
+  if(fp) {
+    line = malloc(MAX_ALTSVC_LINE);
+    if(!line)
+      goto fail;
+    while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
+      char *lineptr = line;
+      while(*lineptr && ISBLANK(*lineptr))
+        lineptr++;
+      if(*lineptr == '#')
+        /* skip commented lines */
+        continue;
+
+      altsvc_add(asi, lineptr);
+    }
+    free(line); /* free the line buffer */
+    fclose(fp);
+  }
+  return result;
+
+  fail:
+  free(line);
+  fclose(fp);
+  return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Write this single altsvc entry to a single output line
+ */
+
+static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
+{
+  struct tm stamp;
+  CURLcode result = Curl_gmtime(as->expires, &stamp);
+  if(result)
+    return result;
+
+  fprintf(fp,
+          "%s %s %u "
+          "%s %s %u "
+          "\"%d%02d%02d "
+          "%02d:%02d:%02d\" "
+          "%u %d\n",
+          Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport,
+          Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport,
+          stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+          stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
+          as->persist, as->prio);
+  return CURLE_OK;
+}
+
+/* ---- library-wide functions below ---- */
+
+/*
+ * Curl_altsvc_init() creates a new altsvc cache.
+ * It returns the new instance or NULL if something goes wrong.
+ */
+struct altsvcinfo *Curl_altsvc_init(void)
+{
+  struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+  if(!asi)
+    return NULL;
+  Curl_llist_init(&asi->list, NULL);
+
+  /* set default behavior */
+  asi->flags = CURLALTSVC_H1
+#ifdef USE_NGHTTP2
+    | CURLALTSVC_H2
+#endif
+#ifdef USE_HTTP3
+    | CURLALTSVC_H3
+#endif
+    ;
+  return asi;
+}
+
+/*
+ * Curl_altsvc_load() loads alt-svc from file.
+ */
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result;
+  DEBUGASSERT(asi);
+  result = altsvc_load(asi, file);
+  return result;
+}
+
+/*
+ * Curl_altsvc_ctrl() passes on the external bitmask.
+ */
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
+{
+  DEBUGASSERT(asi);
+  if(!ctrl)
+    /* unexpected */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  asi->flags = ctrl;
+  return CURLE_OK;
+}
+
+/*
+ * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
+ * resources.
+ */
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  if(altsvc) {
+    for(e = altsvc->list.head; e; e = n) {
+      struct altsvc *as = e->ptr;
+      n = e->next;
+      altsvc_free(as);
+    }
+    free(altsvc);
+  }
+}
+
+/*
+ * Curl_altsvc_save() writes the altsvc cache to a file.
+ */
+CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  CURLcode result = CURLE_OK;
+  FILE *out;
+
+  if(!altsvc)
+    /* no cache activated */
+    return CURLE_OK;
+
+  if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0])
+    /* marked as read-only or zero length file name */
+    return CURLE_OK;
+  out = fopen(file, FOPEN_WRITETEXT);
+  if(!out)
+    return CURLE_WRITE_ERROR;
+  fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
+        "# This file was generated by libcurl! Edit at your own risk.\n",
+        out);
+  for(e = altsvc->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    result = altsvc_out(as, out);
+    if(result)
+      break;
+  }
+  fclose(out);
+  return result;
+}
+
+static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
+{
+  size_t len;
+  const char *protop;
+  const char *p = *ptr;
+  while(*p && ISBLANK(*p))
+    p++;
+  protop = p;
+  while(*p && ISALNUM(*p))
+    p++;
+  len = p - protop;
+
+  if(!len || (len >= buflen))
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  memcpy(alpnbuf, protop, len);
+  alpnbuf[len] = 0;
+  *ptr = p;
+  return CURLE_OK;
+}
+
+/* altsvc_flush() removes all alternatives for this source origin from the
+   list */
+static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
+                         const char *srchost, unsigned short srcport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if((srcalpnid == as->srcalpnid) &&
+       (srcport == as->srcport) &&
+       strcasecompare(srchost, as->srchost)) {
+      Curl_llist_remove(&asi->list, e, NULL);
+      altsvc_free(as);
+      asi->num--;
+    }
+  }
+}
+
+#ifdef DEBUGBUILD
+/* to play well with debug builds, we can *set* a fixed time this will
+   return */
+static time_t debugtime(void *unused)
+{
+  char *timestr = getenv("CURL_TIME");
+  (void)unused;
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    return (time_t)val;
+  }
+  return time(NULL);
+}
+#define time(x) debugtime(x)
+#endif
+
+/*
+ * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
+ * the data correctly in the cache.
+ *
+ * 'value' points to the header *value*. That's contents to the right of the
+ * header name.
+ */
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *asi, const char *value,
+                           enum alpnid srcalpnid, const char *srchost,
+                           unsigned short srcport)
+{
+  const char *p = value;
+  size_t len;
+  enum alpnid dstalpnid = srcalpnid; /* the same by default */
+  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
+  char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
+  struct altsvc *as;
+  unsigned short dstport = srcport; /* the same by default */
+  const char *semip;
+  time_t maxage = 24 * 3600; /* default is 24 hours */
+  bool persist = FALSE;
+  CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+  if(result)
+    return result;
+
+  DEBUGASSERT(asi);
+
+  /* Flush all cached alternatives for this source origin, if any */
+  altsvc_flush(asi, srcalpnid, srchost, srcport);
+
+  /* "clear" is a magic keyword */
+  if(strcasecompare(alpnbuf, "clear")) {
+    return CURLE_OK;
+  }
+
+  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
+     but are set after the list on the line. Scan for the semicolons and get
+     those fields first! */
+  semip = p;
+  do {
+    semip = strchr(semip, ';');
+    if(semip) {
+      char option[32];
+      unsigned long num;
+      char *end_ptr;
+      semip++; /* pass the semicolon */
+      result = getalnum(&semip, option, sizeof(option));
+      if(result)
+        break;
+      while(*semip && ISBLANK(*semip))
+        semip++;
+      if(*semip != '=')
+        continue;
+      semip++;
+      num = strtoul(semip, &end_ptr, 10);
+      if(num < ULONG_MAX) {
+        if(strcasecompare("ma", option))
+          maxage = num;
+        else if(strcasecompare("persist", option) && (num == 1))
+          persist = TRUE;
+      }
+      semip = end_ptr;
+    }
+  } while(semip);
+
+  do {
+    if(*p == '=') {
+      /* [protocol]="[host][:port]" */
+      dstalpnid = alpn2alpnid(alpnbuf);
+      if(!dstalpnid) {
+        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
+        return CURLE_OK;
+      }
+      p++;
+      if(*p == '\"') {
+        const char *dsthost;
+        p++;
+        if(*p != ':') {
+          /* host name starts here */
+          const char *hostp = p;
+          while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
+            p++;
+          len = p - hostp;
+          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
+            return CURLE_BAD_FUNCTION_ARGUMENT;
+          memcpy(namebuf, hostp, len);
+          namebuf[len] = 0;
+          dsthost = namebuf;
+        }
+        else {
+          /* no destination name, use source host */
+          dsthost = srchost;
+        }
+        if(*p == ':') {
+          /* a port number */
+          char *end_ptr;
+          unsigned long port = strtoul(++p, &end_ptr, 10);
+          if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
+            infof(data, "Unknown alt-svc port number, ignoring...\n");
+            return CURLE_OK;
+          }
+          p = end_ptr;
+          dstport = curlx_ultous(port);
+        }
+        if(*p++ != '\"')
+          return CURLE_BAD_FUNCTION_ARGUMENT;
+        as = altsvc_createid(srchost, dsthost,
+                             srcalpnid, dstalpnid,
+                             srcport, dstport);
+        if(as) {
+          /* The expires time also needs to take the Age: value (if any) into
+             account. [See RFC 7838 section 3.1] */
+          as->expires = maxage + time(NULL);
+          as->persist = persist;
+          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+          asi->num++; /* one more entry */
+          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+                Curl_alpnid2str(dstalpnid));
+        }
+      }
+      /* after the double quote there can be a comma if there's another
+         string or a semicolon if no more */
+      if(*p == ',') {
+        /* comma means another alternative is presented */
+        p++;
+        result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+        if(result)
+          /* failed to parse, but since we already did at least one host we
+             return OK */
+          return CURLE_OK;
+      }
+    }
+  } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
+
+  return CURLE_OK;
+}
+
+/*
+ * Return TRUE on a match
+ */
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  time_t now = time(NULL);
+  DEBUGASSERT(asi);
+  DEBUGASSERT(srchost);
+  DEBUGASSERT(dsthost);
+
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if(as->expires < now) {
+      /* an expired entry, remove */
+      altsvc_free(as);
+      continue;
+    }
+    if((as->srcalpnid == srcalpnid) &&
+       strcasecompare(as->srchost, srchost) &&
+       as->srcport == srcport) {
+      /* match */
+      *dstalpnid = as->dstalpnid;
+      *dsthost = as->dsthost;
+      *dstport = as->dstport;
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */

+ 77 - 0
Utilities/cmcurl/lib/altsvc.h

@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_ALTSVC_H
+#define HEADER_CURL_ALTSVC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <[email protected]>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "llist.h"
+
+enum alpnid {
+  ALPN_none,
+  ALPN_h1,
+  ALPN_h2,
+  ALPN_h2c,
+  ALPN_h3
+};
+
+struct altsvc {
+  char *srchost;
+  char *dsthost;
+  unsigned short srcport;
+  unsigned short dstport;
+  enum alpnid srcalpnid;
+  enum alpnid dstalpnid;
+  time_t expires;
+  bool persist;
+  int prio;
+  struct curl_llist_element node;
+};
+
+struct altsvcinfo {
+  char *filename;
+  struct curl_llist list; /* list of entries */
+  size_t num; /* number of alt-svc entries */
+  long flags; /* the publicly set bitmask */
+};
+
+const char *Curl_alpnid2str(enum alpnid id);
+struct altsvcinfo *Curl_altsvc_init(void);
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *altsvc, const char *value,
+                           enum alpnid srcalpn, const char *srchost,
+                           unsigned short srcport);
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport);
+#else
+/* disabled */
+#define Curl_altsvc_save(a,b)
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#endif /* HEADER_CURL_ALTSVC_H */

+ 25 - 7
Utilities/cmcurl/lib/amigaos.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,26 @@
 
 #include "curl_setup.h"
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
-
-#include <amitcp/socketbasetags.h>
+#ifdef __AMIGA__
+#  include "amigaos.h"
+#  if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#    include <amitcp/socketbasetags.h>
+#  endif
+#  ifdef __libnix__
+#    include <stabs.h>
+#  endif
+#endif
 
-#include "amigaos.h"
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
 
+#ifdef __AMIGA__
+#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
 struct Library *SocketBase = NULL;
 extern int errno, h_errno;
 
 #ifdef __libnix__
-#include <stabs.h>
 void __request(const char *msg);
 #else
 # define __request(msg)       Printf(msg "\n\a")
@@ -74,4 +83,13 @@ bool Curl_amiga_init()
 ADD2EXIT(Curl_amiga_cleanup, -50);
 #endif
 
-#endif /* __AMIGA__ && ! __ixemul__ */
+#endif /* HAVE_PROTO_BSDSOCKET_H */
+
+#ifdef USE_AMISSL
+void Curl_amiga_X509_free(X509 *a)
+{
+  X509_free(a);
+}
+#endif /* USE_AMISSL */
+#endif /* __AMIGA__ */
+

+ 8 - 2
Utilities/cmcurl/lib/amigaos.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
+#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
 
 bool Curl_amiga_init();
 void Curl_amiga_cleanup();
@@ -35,4 +35,10 @@ void Curl_amiga_cleanup();
 
 #endif
 
+#ifdef USE_AMISSL
+#include <openssl/x509v3.h>
+void Curl_amiga_X509_free(X509 *a);
+#endif /* USE_AMISSL */
+
 #endif /* HEADER_CURL_AMIGAOS_H */
+

+ 140 - 17
Utilities/cmcurl/lib/asyn-ares.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,7 @@
 #include "progress.h"
 
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
-     (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+     (defined(WIN32) || defined(__SYMBIAN32__))
 #    define CARES_STATICLIB
 #  endif
 #  include <ares.h>
@@ -89,8 +89,20 @@ struct ResolverResults {
   int num_pending; /* number of ares_gethostbyname() requests */
   Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
   int last_status;
+  struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
 };
 
+/* How long we are willing to wait for additional parallel responses after
+   obtaining a "definitive" one.
+
+   This is intended to equal the c-ares default timeout.  cURL always uses that
+   default value.  Unfortunately, c-ares doesn't expose its default timeout in
+   its API, but it is officially documented as 5 seconds.
+
+   See query_completed_cb() for an explanation of how this is used.
+ */
+#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
+
 /*
  * Curl_resolver_global_init() - the generic low-level asynchronous name
  * resolve API.  Called from curl_global_init() to initialize global resolver
@@ -119,6 +131,17 @@ void Curl_resolver_global_cleanup(void)
 #endif
 }
 
+
+static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
+                                    int readable, int writable)
+{
+  struct Curl_easy *easy = data;
+  if(!readable && !writable) {
+    DEBUGASSERT(easy);
+    Curl_multi_closed(easy, socket_fd);
+  }
+}
+
 /*
  * Curl_resolver_init()
  *
@@ -126,9 +149,14 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).  Fills the passed pointer by the initialized ares_channel.
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
-  int status = ares_init((ares_channel*)resolver);
+  int status;
+  struct ares_options options;
+  int optmask = ARES_OPT_SOCK_STATE_CB;
+  options.sock_state_cb = Curl_ares_sock_state_cb;
+  options.sock_state_cb_data = easy;
+  status = ares_init_options((ares_channel*)resolver, &options, optmask);
   if(status != ARES_SUCCESS) {
     if(status == ARES_ENOMEM)
       return CURLE_OUT_OF_MEMORY;
@@ -159,12 +187,15 @@ void Curl_resolver_cleanup(void *resolver)
  * environment ('resolver' member of the UrlState structure).  Duplicates the
  * 'from' ares channel and passes the resulting channel to the 'to' pointer.
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
-  /* Clone the ares channel for the new handle */
-  if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
-    return CURLE_FAILED_INIT;
-  return CURLE_OK;
+  (void)from;
+  /*
+   * it would be better to call ares_dup instead, but right now
+   * it is not possible to set 'sock_state_cb_data' outside of
+   * ares_init_options
+   */
+  return Curl_resolver_init(easy, to);
 }
 
 static void destroy_async_data(struct Curl_async *async);
@@ -179,6 +210,17 @@ void Curl_resolver_cancel(struct connectdata *conn)
   destroy_async_data(&conn->async);
 }
 
+/*
+ * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
+ * never block.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  /* We don't need to check the resolver state because we can be called safely
+     at any time and we always do the same thing. */
+  Curl_resolver_cancel(conn);
+}
+
 /*
  * destroy_async_data() cleans up async resolver data.
  */
@@ -289,9 +331,9 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
     /* move through the descriptors and ask for processing on them */
     for(i = 0; i < num; i++)
       ares_process_fd((ares_channel)data->state.resolver,
-                      pfd[i].revents & (POLLRDNORM|POLLIN)?
+                      (pfd[i].revents & (POLLRDNORM|POLLIN))?
                       pfd[i].fd:ARES_SOCKET_BAD,
-                      pfd[i].revents & (POLLWRNORM|POLLOUT)?
+                      (pfd[i].revents & (POLLWRNORM|POLLOUT))?
                       pfd[i].fd:ARES_SOCKET_BAD);
   }
   return nfds;
@@ -317,6 +359,29 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 
   waitperform(conn, 0);
 
+  /* Now that we've checked for any last minute results above, see if there are
+     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
+     expires. */
+  if(res
+     && res->num_pending
+     /* This is only set to non-zero if the timer was started. */
+     && (res->happy_eyeballs_dns_time.tv_sec
+         || res->happy_eyeballs_dns_time.tv_usec)
+     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
+         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
+    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
+       running. */
+    memset(
+      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
+
+    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
+       ARES_ECANCELLED synchronously for all pending responses.  This will
+       leave us with res->num_pending == 0, which is perfect for the next
+       block. */
+    ares_cancel((ares_channel)data->state.resolver);
+    DEBUGASSERT(res->num_pending == 0);
+  }
+
   if(res && !res->num_pending) {
     if(dns) {
       (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
@@ -342,13 +407,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
  * Curl_resolver_wait_resolv()
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **entry)
@@ -425,9 +490,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 
   if(result)
     /* close the connection, since we can't return failure here without
-       cleaning up this connection properly.
-       TODO: remove this action from here, it is not a name resolver decision.
-    */
+       cleaning up this connection properly. */
     connclose(conn, "c-ares resolve failed");
 
   return result;
@@ -487,6 +550,66 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
     /* A successful result overwrites any previous error */
     if(res->last_status != ARES_SUCCESS)
       res->last_status = status;
+
+    /* If there are responses still pending, we presume they must be the
+       complementary IPv4 or IPv6 lookups that we started in parallel in
+       Curl_resolver_getaddrinfo() (for Happy Eyeballs).  If we've got a
+       "definitive" response from one of a set of parallel queries, we need to
+       think about how long we're willing to wait for more responses. */
+    if(res->num_pending
+       /* Only these c-ares status values count as "definitive" for these
+          purposes.  For example, ARES_ENODATA is what we expect when there is
+          no IPv6 entry for a domain name, and that's not a reason to get more
+          aggressive in our timeouts for the other response.  Other errors are
+          either a result of bad input (which should affect all parallel
+          requests), local or network conditions, non-definitive server
+          responses, or us cancelling the request. */
+       && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
+      /* Right now, there can only be up to two parallel queries, so don't
+         bother handling any other cases. */
+      DEBUGASSERT(res->num_pending == 1);
+
+      /* It's possible that one of these parallel queries could succeed
+         quickly, but the other could always fail or timeout (when we're
+         talking to a pool of DNS servers that can only successfully resolve
+         IPv4 address, for example).
+
+         It's also possible that the other request could always just take
+         longer because it needs more time or only the second DNS server can
+         fulfill it successfully.  But, to align with the philosophy of Happy
+         Eyeballs, we don't want to wait _too_ long or users will think
+         requests are slow when IPv6 lookups don't actually work (but IPv4 ones
+         do).
+
+         So, now that we have a usable answer (some IPv4 addresses, some IPv6
+         addresses, or "no such domain"), we start a timeout for the remaining
+         pending responses.  Even though it is typical that this resolved
+         request came back quickly, that needn't be the case.  It might be that
+         this completing request didn't get a result from the first DNS server
+         or even the first round of the whole DNS server pool.  So it could
+         already be quite some time after we issued the DNS queries in the
+         first place.  Without modifying c-ares, we can't know exactly where in
+         its retry cycle we are.  We could guess based on how much time has
+         gone by, but it doesn't really matter.  Happy Eyeballs tells us that,
+         given usable information in hand, we simply don't want to wait "too
+         much longer" after we get a result.
+
+         We simply wait an additional amount of time equal to the default
+         c-ares query timeout.  That is enough time for a typical parallel
+         response to arrive without being "too long".  Even on a network
+         where one of the two types of queries is failing or timing out
+         constantly, this will usually mean we wait a total of the default
+         c-ares timeout (5 seconds) plus the round trip time for the successful
+         request, which seems bearable.  The downside is that c-ares might race
+         with us to issue one more retry just before we give up, but it seems
+         better to "waste" that request instead of trying to guess the perfect
+         timeout to prevent it.  After all, we don't even know where in the
+         c-ares retry cycle each request is.
+      */
+      res->happy_eyeballs_dns_time = Curl_now();
+      Curl_expire(
+        conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+    }
   }
 }
 

+ 50 - 20
Utilities/cmcurl/lib/asyn-thread.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -108,8 +108,9 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
+  (void)easy;
   *resolver = calloc(1, sizeof(struct resdata));
   if(!*resolver)
     return CURLE_OUT_OF_MEMORY;
@@ -132,10 +133,10 @@ void Curl_resolver_cleanup(void *resolver)
  * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
  * environment ('resolver' member of the UrlState structure).
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
   (void)from;
-  return Curl_resolver_init(to);
+  return Curl_resolver_init(easy, to);
 }
 
 static void destroy_async_data(struct Curl_async *);
@@ -276,7 +277,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
   char service[12];
   int rc;
 
-  snprintf(service, sizeof(service), "%d", tsd->port);
+  msnprintf(service, sizeof(service), "%d", tsd->port);
 
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
 
@@ -460,23 +461,15 @@ static CURLcode resolver_error(struct connectdata *conn)
   return result;
 }
 
-/*
- * Curl_resolver_wait_resolv()
- *
- * waits for a resolve to finish. This function should be avoided since using
- * this risk getting the multi interface to "hang".
- *
- * If 'entry' is non-NULL, make it point to the resolved dns entry
- *
- * This is the version for resolves-in-a-thread.
- */
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
-                                   struct Curl_dns_entry **entry)
+static CURLcode thread_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry,
+                                   bool report)
 {
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   CURLcode result = CURLE_OK;
 
   DEBUGASSERT(conn && td);
+  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
 
   /* wait for the thread to resolve the name */
   if(Curl_thread_join(&td->thread_hnd)) {
@@ -491,18 +484,55 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   if(entry)
     *entry = conn->async.dns;
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     /* a name was not resolved, report error */
     result = resolver_error(conn);
 
   destroy_async_data(&conn->async);
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     connclose(conn, "asynch resolve failed");
 
   return result;
 }
 
+
+/*
+ * Until we gain a way to signal the resolver threads to stop early, we must
+ * simply wait for them and ignore their results.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+
+  /* If we're still resolving, we must wait for the threads to fully clean up,
+     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
+     data. */
+  if(td && td->thread_hnd != curl_thread_t_null)
+    (void)thread_wait_resolv(conn, NULL, FALSE);
+  else
+    Curl_resolver_cancel(conn);
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * Waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry)
+{
+  return thread_wait_resolv(conn, entry, TRUE);
+}
+
 /*
  * Curl_resolver_is_resolved() is called repeatedly to check if a previous
  * name resolve request has completed. It should also make sure to time-out if
@@ -678,7 +708,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
   hints.ai_family = pf;
   hints.ai_socktype = conn->socktype;
 
-  snprintf(sbuf, sizeof(sbuf), "%d", port);
+  msnprintf(sbuf, sizeof(sbuf), "%d", port);
 
   reslv->start = Curl_now();
   /* fire up a new resolver thread! */

+ 26 - 10
Utilities/cmcurl/lib/asyn.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,7 @@ void Curl_resolver_global_cleanup(void);
  * Returning anything else than CURLE_OK fails curl_easy_init() with the
  * correspondent code.
  */
-CURLcode Curl_resolver_init(void **resolver);
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
 
 /*
  * Curl_resolver_cleanup()
@@ -79,17 +79,33 @@ void Curl_resolver_cleanup(void *resolver);
  * pointer.  Returning anything else than CURLE_OK causes failed
  * curl_easy_duphandle() call.
  */
-int Curl_resolver_duphandle(void **to, void *from);
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
+                                 void *from);
 
 /*
  * Curl_resolver_cancel().
  *
  * It is called from inside other functions to cancel currently performing
  * resolver request. Should also free any temporary resources allocated to
- * perform a request.
+ * perform a request.  This never waits for resolver threads to complete.
+ *
+ * It is safe to call this when conn is in any state.
  */
 void Curl_resolver_cancel(struct connectdata *conn);
 
+/*
+ * Curl_resolver_kill().
+ *
+ * This acts like Curl_resolver_cancel() except it will block until any threads
+ * associated with the resolver are complete.  This never blocks for resolvers
+ * that do not use threads.  This is intended to be the "last chance" function
+ * that cleans up an in-progress resolver completely (before its owner is about
+ * to die).
+ *
+ * It is safe to call this when conn is in any state.
+ */
+void Curl_resolver_kill(struct connectdata *conn);
+
 /* Curl_resolver_getsock()
  *
  * This function is called from the multi_getsock() function.  'sock' is a
@@ -116,14 +132,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
  * Curl_resolver_wait_resolv()
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
-
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **dnsentry);
@@ -147,11 +162,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 #ifndef CURLRES_ASYNCH
 /* convert these functions if an asynch resolver isn't used */
 #define Curl_resolver_cancel(x) Curl_nop_stmt
+#define Curl_resolver_kill(x) Curl_nop_stmt
 #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_getsock(x,y,z) 0
-#define Curl_resolver_duphandle(x,y) CURLE_OK
-#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_duphandle(x,y,z) CURLE_OK
+#define Curl_resolver_init(x,y) CURLE_OK
 #define Curl_resolver_global_init() CURLE_OK
 #define Curl_resolver_global_cleanup() Curl_nop_stmt
 #define Curl_resolver_cleanup(x) Curl_nop_stmt

+ 20 - 13
Utilities/cmcurl/lib/base64.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +23,11 @@
 /* Base64 encoding/decoding */
 
 #include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \
+  defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \
+  !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
+
 #include "urldata.h" /* for the Curl_easy definition */
 #include "warnless.h"
 #include "curl_base64.h"
@@ -233,24 +238,24 @@ static CURLcode base64_encode(const char *table64,
 
     switch(inputparts) {
     case 1: /* only one byte read */
-      snprintf(output, 5, "%c%c==",
-               table64[obuf[0]],
-               table64[obuf[1]]);
+      msnprintf(output, 5, "%c%c==",
+                table64[obuf[0]],
+                table64[obuf[1]]);
       break;
 
     case 2: /* two bytes read */
-      snprintf(output, 5, "%c%c%c=",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]]);
+      msnprintf(output, 5, "%c%c%c=",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]]);
       break;
 
     default:
-      snprintf(output, 5, "%c%c%c%c",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]],
-               table64[obuf[3]]);
+      msnprintf(output, 5, "%c%c%c%c",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]],
+                table64[obuf[3]]);
       break;
     }
     output += 4;
@@ -317,3 +322,5 @@ CURLcode Curl_base64url_encode(struct Curl_easy *data,
 {
   return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
 }
+
+#endif /* no users so disabled */

+ 22 - 16
Utilities/cmcurl/lib/conncache.c

@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <[email protected]>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -175,12 +175,12 @@ static void hashkey(struct connectdata *conn, char *buf,
   DEBUGASSERT(len > 32);
 
   /* put the number first so that the hostname gets cut off if too long */
-  snprintf(buf, len, "%ld%s", conn->port, hostname);
+  msnprintf(buf, len, "%ld%s", conn->port, hostname);
 }
 
-void Curl_conncache_unlock(struct connectdata *conn)
+void Curl_conncache_unlock(struct Curl_easy *data)
 {
-  CONN_UNLOCK(conn->data);
+  CONN_UNLOCK(data);
 }
 
 /* Returns number of connections currently held in the connection cache.
@@ -302,9 +302,14 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   return result;
 }
 
-void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
+/*
+ * Removes the connectdata object from the connection cache *and* clears the
+ * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument
+ * depending on if the parent function already holds the lock or not.
+ */
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn, bool lock)
 {
-  struct Curl_easy *data = conn->data;
   struct connectbundle *bundle = conn->bundle;
   struct conncache *connc = data->state.conn_cache;
 
@@ -323,6 +328,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
       DEBUGF(infof(data, "The cache now contains %zu members\n",
                    connc->num_conn));
     }
+    conn->data = NULL; /* clear the association */
     if(lock) {
       CONN_UNLOCK(data);
     }
@@ -386,8 +392,8 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
    NOTE: no locking is done here as this is presumably only done when cleaning
    up a cache!
 */
-struct connectdata *
-Curl_conncache_find_first_connection(struct conncache *connc)
+static struct connectdata *
+conncache_find_first_connection(struct conncache *connc)
 {
   struct curl_hash_iterator iter;
   struct curl_hash_element *he;
@@ -427,6 +433,8 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
     data->multi->maxconnects;
   struct connectdata *conn_candidate = NULL;
 
+  conn->data = NULL; /* no owner anymore */
+  conn->lastused = Curl_now(); /* it was used up until now */
   if(maxconnects > 0 &&
      Curl_conncache_size(data) > maxconnects) {
     infof(data, "Connection cache is full, closing the oldest one.\n");
@@ -470,9 +478,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
   while(curr) {
     conn = curr->ptr;
 
-    if(!CONN_INUSE(conn)) {
+    if(!CONN_INUSE(conn) && !conn->data) {
       /* Set higher score for the age passed since the connection was used */
-      score = Curl_timediff(now, conn->now);
+      score = Curl_timediff(now, conn->lastused);
 
       if(score > highscore) {
         highscore = score;
@@ -528,9 +536,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
     while(curr) {
       conn = curr->ptr;
 
-      if(!CONN_INUSE(conn)) {
+      if(!CONN_INUSE(conn) && !conn->data) {
         /* Set higher score for the age passed since the connection was used */
-        score = Curl_timediff(now, conn->now);
+        score = Curl_timediff(now, conn->lastused);
 
         if(score > highscore) {
           highscore = score;
@@ -560,20 +568,18 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
 {
   struct connectdata *conn;
 
-  conn = Curl_conncache_find_first_connection(connc);
+  conn = conncache_find_first_connection(connc);
   while(conn) {
     SIGPIPE_VARIABLE(pipe_st);
     conn->data = connc->closure_handle;
 
     sigpipe_ignore(conn->data, &pipe_st);
-    conn->data->easy_conn = NULL; /* clear the easy handle's connection
-                                     pointer */
     /* This will remove the connection from the cache */
     connclose(conn, "kill all");
     (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
     sigpipe_restore(&pipe_st);
 
-    conn = Curl_conncache_find_first_connection(connc);
+    conn = conncache_find_first_connection(connc);
   }
 
   if(connc->closure_handle) {

+ 4 - 4
Utilities/cmcurl/lib/conncache.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2015 - 2019, Daniel Stenberg, <[email protected]>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <[email protected]>
  *
  * This software is licensed as described in the file COPYING, which
@@ -40,7 +40,6 @@ struct conncache {
 
 #define BUNDLE_NO_MULTIUSE -1
 #define BUNDLE_UNKNOWN     0  /* initial value */
-#define BUNDLE_PIPELINING  1
 #define BUNDLE_MULTIPLEX   2
 
 struct connectbundle {
@@ -56,7 +55,7 @@ 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);
-void Curl_conncache_unlock(struct connectdata *conn);
+void Curl_conncache_unlock(struct Curl_easy *data);
 /* returns number of connections currently held in the connection cache */
 size_t Curl_conncache_size(struct Curl_easy *data);
 size_t Curl_conncache_bundle_size(struct connectdata *conn);
@@ -64,7 +63,8 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
 bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn) WARN_UNUSED_RESULT;
-void Curl_conncache_remove_conn(struct connectdata *conn,
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn,
                                 bool lock);
 bool Curl_conncache_foreach(struct Curl_easy *data,
                             struct conncache *connc,

+ 67 - 47
Utilities/cmcurl/lib/connect.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -357,7 +357,7 @@ static CURLcode bindlocal(struct connectdata *conn,
         conn->ip_version = CURL_IPRESOLVE_V6;
 #endif
 
-      rc = Curl_resolv(conn, dev, 0, &h);
+      rc = Curl_resolv(conn, dev, 0, FALSE, &h);
       if(rc == CURLRESOLV_PENDING)
         (void)Curl_resolver_wait_resolv(conn, &h);
       conn->ip_version = ipver;
@@ -446,9 +446,10 @@ static CURLcode bindlocal(struct connectdata *conn,
       curl_socklen_t size = sizeof(add);
       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+        char buffer[STRERROR_LEN];
         data->state.os_errno = error = SOCKERRNO;
         failf(data, "getsockname() failed with errno %d: %s",
-              error, Curl_strerror(conn, error));
+              error, Curl_strerror(error, buffer, sizeof(buffer)));
         return CURLE_INTERFACE_FAILED;
       }
       infof(data, "Local port: %hu\n", port);
@@ -470,10 +471,12 @@ static CURLcode bindlocal(struct connectdata *conn,
     else
       break;
   }
-
-  data->state.os_errno = error = SOCKERRNO;
-  failf(data, "bind failed with errno %d: %s",
-        error, Curl_strerror(conn, error));
+  {
+    char buffer[STRERROR_LEN];
+    data->state.os_errno = error = SOCKERRNO;
+    failf(data, "bind failed with errno %d: %s",
+          error, Curl_strerror(error, buffer, sizeof(buffer)));
+  }
 
   return CURLE_INTERFACE_FAILED;
 }
@@ -522,7 +525,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
     err = 0;
   }
 #endif
-#ifdef __minix
+#if defined(EBADIOCTL) && defined(__minix)
   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
   if(EBADIOCTL == err) {
     SET_SOCKERRNO(0);
@@ -617,12 +620,14 @@ void Curl_persistconninfo(struct connectdata *conn)
   conn->data->info.conn_local_port = conn->local_port;
 }
 
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port);
+
 /* retrieves ip address and port from a sockaddr structure.
    note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
-                         long *port)
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port)
 {
-  unsigned short us_port;
   struct sockaddr_in *si = NULL;
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *si6 = NULL;
@@ -636,7 +641,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si = (struct sockaddr_in *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si->sin_port);
+        unsigned short us_port = ntohs(si->sin_port);
         *port = us_port;
         return TRUE;
       }
@@ -646,7 +651,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si6->sin6_port);
+        unsigned short us_port = ntohs(si6->sin6_port);
         *port = us_port;
         return TRUE;
       }
@@ -655,7 +660,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
     case AF_UNIX:
       su = (struct sockaddr_un*)sa;
-      snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+      msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
       *port = 0;
       return TRUE;
 #endif
@@ -673,49 +678,57 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
    connection */
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 {
-  curl_socklen_t len;
-  struct Curl_sockaddr_storage ssrem;
-  struct Curl_sockaddr_storage ssloc;
-  struct Curl_easy *data = conn->data;
-
   if(conn->socktype == SOCK_DGRAM)
     /* there's no connection! */
     return;
 
+#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+    struct Curl_easy *data = conn->data;
+    char buffer[STRERROR_LEN];
+    struct Curl_sockaddr_storage ssrem;
+    struct Curl_sockaddr_storage ssloc;
+    curl_socklen_t len;
+#ifdef HAVE_GETPEERNAME
     len = sizeof(struct Curl_sockaddr_storage);
     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
       int error = SOCKERRNO;
       failf(data, "getpeername() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
     }
-
+#endif
+#ifdef HAVE_GETSOCKNAME
     len = sizeof(struct Curl_sockaddr_storage);
     memset(&ssloc, 0, sizeof(ssloc));
     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
       int error = SOCKERRNO;
       failf(data, "getsockname() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
     }
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
-                            conn->primary_ip, &conn->primary_port)) {
+#endif
+#ifdef HAVE_GETPEERNAME
+    if(!getaddressinfo((struct sockaddr*)&ssrem,
+                       conn->primary_ip, &conn->primary_port)) {
       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
     }
     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
-                            conn->local_ip, &conn->local_port)) {
+#endif
+#ifdef HAVE_GETSOCKNAME
+    if(!getaddressinfo((struct sockaddr*)&ssloc,
+                       conn->local_ip, &conn->local_port)) {
       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
     }
-
+#endif
   }
+#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
+  (void)sockfd; /* unused */
+#endif
 
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
@@ -836,9 +849,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       if(conn->tempaddr[i]) {
         CURLcode status;
         char ipaddress[MAX_IPADR_LEN];
+        char buffer[STRERROR_LEN];
         Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
         infof(data, "connect to %s port %ld failed: %s\n",
-              ipaddress, conn->port, Curl_strerror(conn, error));
+              ipaddress, conn->port,
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
         conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
                                    allow : allow / 2;
@@ -854,8 +869,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
   if(result) {
     /* no more addresses to try */
-
     const char *hostname;
+    char buffer[STRERROR_LEN];
 
     /* if the first address family runs out of addresses to try before
        the happy eyeball timeout, go ahead and try the next family now */
@@ -875,13 +890,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       hostname = conn->host.name;
 
     failf(data, "Failed to connect to %s port %ld: %s",
-        hostname, conn->port, Curl_strerror(conn, error));
+          hostname, conn->port,
+          Curl_strerror(error, buffer, sizeof(buffer)));
   }
 
   return result;
 }
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
+static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 {
 #if defined(TCP_NODELAY)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -889,6 +905,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 #endif
   curl_socklen_t onoff = (curl_socklen_t) 1;
   int level = IPPROTO_TCP;
+  char buffer[STRERROR_LEN];
 
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
   (void) conn;
@@ -897,7 +914,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                 sizeof(onoff)) < 0)
     infof(data, "Could not set TCP_NODELAY: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
   else
     infof(data, "TCP_NODELAY set\n");
 #else
@@ -917,9 +934,11 @@ static void nosigpipe(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   int onoff = 1;
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
-                sizeof(onoff)) < 0)
+                sizeof(onoff)) < 0) {
+    char buffer[STRERROR_LEN];
     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+  }
 }
 #else
 #define nosigpipe(x,y) Curl_nop_stmt
@@ -995,6 +1014,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
 #ifdef TCP_FASTOPEN_CONNECT
   int optval = 1;
 #endif
+  char buffer[STRERROR_LEN];
 
   *sockp = CURL_SOCKET_BAD;
 
@@ -1006,15 +1026,15 @@ static CURLcode singleipconnect(struct connectdata *conn,
     return CURLE_OK;
 
   /* store remote address and port used in this connection attempt */
-  if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
-                          ipaddress, &port)) {
+  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
+                     ipaddress, &port)) {
     /* malformed address or bug in inet_ntop, try next address */
     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     Curl_closesocket(conn, sockfd);
     return CURLE_OK;
   }
-  infof(data, "  Trying %s...\n", ipaddress);
+  infof(data, "  Trying %s:%ld...\n", ipaddress, port);
 
 #ifdef ENABLE_IPV6
   is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1023,7 +1043,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
   is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
 #endif
   if(is_tcp && data->set.tcp_nodelay)
-    Curl_tcpnodelay(conn, sockfd);
+    tcpnodelay(conn, sockfd);
 
   nosigpipe(conn, sockfd);
 
@@ -1146,7 +1166,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
     default:
       /* unknown error, fallthrough and try another address! */
       infof(data, "Immediate connect fail for %s: %s\n",
-            ipaddress, Curl_strerror(conn, error));
+            ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
       data->state.os_errno = error;
 
       /* connect failed */
@@ -1314,7 +1334,7 @@ int Curl_closesocket(struct connectdata *conn,
       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
     else {
       int rc;
-      Curl_multi_closed(conn, sock);
+      Curl_multi_closed(conn->data, sock);
       Curl_set_in_callback(conn->data, true);
       rc = conn->fclosesocket(conn->closesocket_client, sock);
       Curl_set_in_callback(conn->data, false);
@@ -1324,7 +1344,7 @@ int Curl_closesocket(struct connectdata *conn,
 
   if(conn)
     /* tell the multi-socket code about this */
-    Curl_multi_closed(conn, sock);
+    Curl_multi_closed(conn->data, sock);
 
   sclose(sock);
 
@@ -1420,7 +1440,7 @@ void Curl_conncontrol(struct connectdata *conn,
   if((ctrl == CONNCTRL_STREAM) &&
      (conn->handler->flags & PROTOPT_STREAM))
     DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
-  else if(closeit != conn->bits.close) {
+  else if((bit)closeit != conn->bits.close) {
     DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
                  closeit?"closure":"keep alive", reason));
     conn->bits.close = closeit; /* the only place in the source code that

+ 1 - 8
Utilities/cmcurl/lib/connect.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -75,11 +75,6 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
 void Curl_persistconninfo(struct connectdata *conn);
 int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
 
-/*
- * Get presentation format IP address and port from a sockaddr.
- */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
-
 /*
  * The Curl_sockaddr_ex structure is basically libcurl's external API
  * curl_sockaddr structure with enough space available to directly hold any
@@ -111,8 +106,6 @@ CURLcode Curl_socket(struct connectdata *conn,
                      struct Curl_sockaddr_ex *addr,
                      curl_socket_t *sockfd);
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
-
 /*
  * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
  * argument specifies if it is the end of a connection or a stream.

+ 129 - 73
Utilities/cmcurl/lib/cookie.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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 @@ Example set of cookies:
 #include "share.h"
 #include "strtoofft.h"
 #include "strcase.h"
+#include "curl_get_line.h"
 #include "curl_memrchr.h"
 #include "inet_pton.h"
 
@@ -223,7 +224,7 @@ static bool pathmatch(const char *cookie_path, const char *request_uri)
     goto pathmatched;
   }
 
-  /* here, cookie_path_len < url_path_len */
+  /* here, cookie_path_len < uri_path_len */
   if(uri_path[cookie_path_len] == '/') {
     ret = TRUE;
     goto pathmatched;
@@ -433,9 +434,10 @@ Curl_cookie_add(struct Curl_easy *data,
                 bool noexpire, /* if TRUE, skip remove_expired() */
                 char *lineptr,   /* first character of the line */
                 const char *domain, /* default domain */
-                const char *path)   /* full path used when this cookie is set,
+                const char *path,   /* full path used when this cookie is set,
                                        used to get default path for the cookie
                                        unless set */
+                bool secure)  /* TRUE if connection is over secure origin */
 {
   struct Cookie *clist;
   struct Cookie *co;
@@ -527,6 +529,19 @@ Curl_cookie_add(struct Curl_easy *data,
         while(*whatptr && ISBLANK(*whatptr))
           whatptr++;
 
+        /*
+         * Check if we have a reserved prefix set before anything else, as we
+         * otherwise have to test for the prefix in both the cookie name and
+         * "the rest". Prefixes must start with '__' and end with a '-', so
+         * only test for names where that can possibly be true.
+         */
+        if(nlen > 3 && name[0] == '_' && name[1] == '_') {
+          if(strncasecompare("__Secure-", name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
+
         if(!co->name) {
           /* The very first name/value pair is the actual cookie name */
           if(!sep) {
@@ -546,8 +561,20 @@ Curl_cookie_add(struct Curl_easy *data,
           /* this was a "<name>=" with no content, and we must allow
              'secure' and 'httponly' specified this weirdly */
           done = TRUE;
-          if(strcasecompare("secure", name))
-            co->secure = TRUE;
+          /*
+           * secure cookies are only allowed to be set when the connection is
+           * using a secure protocol, or when the cookie is being set by
+           * reading from file
+           */
+          if(strcasecompare("secure", name)) {
+            if(secure || !c->running) {
+              co->secure = TRUE;
+            }
+            else {
+              badcookie = TRUE;
+              break;
+            }
+          }
           else if(strcasecompare("httponly", name))
             co->httponly = TRUE;
           else if(sep)
@@ -675,7 +702,10 @@ Curl_cookie_add(struct Curl_easy *data,
         /* overflow, used max value */
         co->expires = CURL_OFF_T_MAX;
       else if(!offt) {
-        if(CURL_OFF_T_MAX - now < co->expires)
+        if(!co->expires)
+          /* already expired */
+          co->expires = 1;
+        else if(CURL_OFF_T_MAX - now < co->expires)
           /* would overflow */
           co->expires = CURL_OFF_T_MAX;
         else
@@ -828,7 +858,13 @@ Curl_cookie_add(struct Curl_easy *data,
         fields++; /* add a field and fall down to secure */
         /* FALLTHROUGH */
       case 3:
-        co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
+        co->secure = FALSE;
+        if(strcasecompare(ptr, "TRUE")) {
+          if(secure || c->running)
+            co->secure = TRUE;
+          else
+            badcookie = TRUE;
+        }
         break;
       case 4:
         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
@@ -838,6 +874,13 @@ Curl_cookie_add(struct Curl_easy *data,
         co->name = strdup(ptr);
         if(!co->name)
           badcookie = TRUE;
+        else {
+          /* For Netscape file format cookies we check prefix on the name */
+          if(strncasecompare("__Secure-", co->name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", co->name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
         break;
       case 6:
         co->value = strdup(ptr);
@@ -866,6 +909,26 @@ Curl_cookie_add(struct Curl_easy *data,
 
   }
 
+  if(co->prefix & COOKIE_PREFIX__SECURE) {
+    /* The __Secure- prefix only requires that the cookie be set secure */
+    if(!co->secure) {
+      freecookie(co);
+      return NULL;
+    }
+  }
+  if(co->prefix & COOKIE_PREFIX__HOST) {
+    /*
+     * The __Host- prefix requires the cookie to be secure, have a "/" path
+     * and not have a domain set.
+     */
+    if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch)
+      ;
+    else {
+      freecookie(co);
+      return NULL;
+    }
+  }
+
   if(!c->running &&    /* read from a file */
      c->newsession &&  /* clean session cookies */
      !co->expires) {   /* this is a session cookie since it doesn't expire! */
@@ -926,9 +989,31 @@ Curl_cookie_add(struct Curl_easy *data,
         /* the domains were identical */
 
         if(clist->spath && co->spath) {
-          if(strcasecompare(clist->spath, co->spath)) {
-            replace_old = TRUE;
+          if(clist->secure && !co->secure && !secure) {
+            size_t cllen;
+            const char *sep;
+
+            /*
+             * A non-secure cookie may not overlay an existing secure cookie.
+             * For an existing cookie "a" with path "/login", refuse a new
+             * cookie "a" with for example path "/login/en", while the path
+             * "/loginhelper" is ok.
+             */
+
+            sep = strchr(clist->spath + 1, '/');
+
+            if(sep)
+              cllen = sep - clist->spath;
+            else
+              cllen = strlen(clist->spath);
+
+            if(strncasecompare(clist->spath, co->spath, cllen)) {
+              freecookie(co);
+              return NULL;
+            }
           }
+          else if(strcasecompare(clist->spath, co->spath))
+            replace_old = TRUE;
           else
             replace_old = FALSE;
         }
@@ -1003,33 +1088,6 @@ Curl_cookie_add(struct Curl_easy *data,
   return co;
 }
 
-/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
- */
-static char *get_line(char *buf, int len, FILE *input)
-{
-  bool partial = FALSE;
-  while(1) {
-    char *b = fgets(buf, len, input);
-    if(b) {
-      size_t rlen = strlen(b);
-      if(rlen && (b[rlen-1] == '\n')) {
-        if(partial) {
-          partial = FALSE;
-          continue;
-        }
-        return b;
-      }
-      /* read a partial, discard the next piece that ends with newline */
-      partial = TRUE;
-    }
-    else
-      break;
-  }
-  return NULL;
-}
-
 
 /*****************************************************************************
  *
@@ -1087,7 +1145,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
     line = malloc(MAX_COOKIE_LINE);
     if(!line)
       goto fail;
-    while(get_line(line, MAX_COOKIE_LINE, fp)) {
+    while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
       if(checkprefix("Set-Cookie:", line)) {
         /* This is a cookie line, get it! */
         lineptr = &line[11];
@@ -1100,7 +1158,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
 
-      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
+      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
     }
     free(line); /* free the line buffer */
     remove_expired(c); /* run this once, not on every cookie */
@@ -1451,27 +1509,14 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   struct Cookie *co;
   FILE *out;
   bool use_stdout = FALSE;
-  char *format_ptr;
-  unsigned int i;
-  unsigned int j;
-  struct Cookie **array;
 
-  if((NULL == c) || (0 == c->numcookies))
-    /* If there are no known cookies, we don't write or even create any
-       destination file */
+  if(!c)
+    /* no cookie engine alive */
     return 0;
 
   /* at first, remove expired cookies */
   remove_expired(c);
 
-  /* make sure we still have cookies after expiration */
-  if(0 == c->numcookies)
-    return 0;
-
-  array = malloc(sizeof(struct Cookie *) * c->numcookies);
-  if(!array)
-    return 1;
-
   if(!strcmp("-", dumphere)) {
     /* use stdout */
     out = stdout;
@@ -1480,7 +1525,6 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   else {
     out = fopen(dumphere, FOPEN_WRITETEXT);
     if(!out) {
-      free(array);
       return 1; /* failure */
     }
   }
@@ -1490,32 +1534,44 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
         "# This file was generated by libcurl! Edit at your own risk.\n\n",
         out);
 
-  j = 0;
-  for(i = 0; i < COOKIE_HASH_SIZE; i++) {
-    for(co = c->cookies[i]; co; co = co->next) {
-      if(!co->domain)
-        continue;
-      array[j++] = co;
-    }
-  }
-
-  qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+  if(c->numcookies) {
+    unsigned int i;
+    unsigned int j;
+    struct Cookie **array;
 
-  for(i = 0; i < j; i++) {
-    format_ptr = get_netscape_format(array[i]);
-    if(format_ptr == NULL) {
-      fprintf(out, "#\n# Fatal libcurl error\n");
-      free(array);
+    array = malloc(sizeof(struct Cookie *) * c->numcookies);
+    if(!array) {
       if(!use_stdout)
         fclose(out);
       return 1;
     }
-    fprintf(out, "%s\n", format_ptr);
-    free(format_ptr);
-  }
 
-  free(array);
+    j = 0;
+    for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+      for(co = c->cookies[i]; co; co = co->next) {
+        if(!co->domain)
+          continue;
+        array[j++] = co;
+      }
+    }
+
+    qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
 
+    for(i = 0; i < j; i++) {
+      char *format_ptr = get_netscape_format(array[i]);
+      if(format_ptr == NULL) {
+        fprintf(out, "#\n# Fatal libcurl error\n");
+        free(array);
+        if(!use_stdout)
+          fclose(out);
+        return 1;
+      }
+      fprintf(out, "%s\n", format_ptr);
+      free(format_ptr);
+    }
+
+    free(array);
+  }
   if(!use_stdout)
     fclose(out);
 

+ 11 - 2
Utilities/cmcurl/lib/cookie.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -44,8 +44,16 @@ struct Cookie {
   bool livecookie;   /* updated from a server, not a stored file */
   bool httponly;     /* true if the httponly directive is present */
   int creationtime;  /* time when the cookie was written */
+  unsigned char prefix; /* bitmap fields indicating which prefix are set */
 };
 
+/*
+ * Available cookie prefixes, as defined in
+ * draft-ietf-httpbis-rfc6265bis-02
+ */
+#define COOKIE_PREFIX__SECURE (1<<0)
+#define COOKIE_PREFIX__HOST (1<<1)
+
 #define COOKIE_HASH_SIZE 256
 
 struct CookieInfo {
@@ -85,7 +93,8 @@ struct Curl_easy;
 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
                                struct CookieInfo *, bool header, bool noexpiry,
                                char *lineptr,
-                               const char *domain, const char *path);
+                               const char *domain, const char *path,
+                               bool secure);
 
 struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
                                    const char *, bool);

+ 16 - 16
Utilities/cmcurl/lib/curl_addrinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -539,7 +539,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) &&  \
   defined(HAVE_FREEADDRINFO)
 /*
- * curl_dofreeaddrinfo()
+ * curl_dbg_freeaddrinfo()
  *
  * This is strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -547,23 +547,23 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
  */
 
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source)
+curl_dbg_freeaddrinfo(struct addrinfo *freethis,
+                      int line, const char *source)
 {
+  curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n",
+               source, line, (void *)freethis);
 #ifdef USE_LWIPSOCK
   lwip_freeaddrinfo(freethis);
 #else
   (freeaddrinfo)(freethis);
 #endif
-  curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
-              source, line, (void *)freethis);
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 /*
- * curl_dogetaddrinfo()
+ * curl_dbg_getaddrinfo()
  *
  * This is strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -571,11 +571,11 @@ curl_dofreeaddrinfo(struct addrinfo *freethis,
  */
 
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source)
+curl_dbg_getaddrinfo(const char *hostname,
+                    const char *service,
+                    const struct addrinfo *hints,
+                    struct addrinfo **result,
+                    int line, const char *source)
 {
 #ifdef USE_LWIPSOCK
   int res = lwip_getaddrinfo(hostname, service, hints, result);
@@ -584,11 +584,11 @@ curl_dogetaddrinfo(const char *hostname,
 #endif
   if(0 == res)
     /* success */
-    curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
-                source, line, (void *)*result);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n",
+                 source, line, (void *)*result);
   else
-    curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
-                source, line);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n",
+                 source, line);
   return res;
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */

+ 5 - 8
Utilities/cmcurl/lib/curl_addrinfo.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -86,17 +86,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
     defined(HAVE_FREEADDRINFO)
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source);
+curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source);
 #endif
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source);
+curl_dbg_getaddrinfo(const char *hostname, const char *service,
+                     const struct addrinfo *hints, struct addrinfo **result,
+                     int line, const char *source);
 #endif
 
 #ifdef HAVE_GETADDRINFO

+ 8 - 2
Utilities/cmcurl/lib/curl_config.h.cmake

@@ -226,6 +226,12 @@
 /* Define to 1 if you have the `getprotobyname' function. */
 #cmakedefine HAVE_GETPROTOBYNAME 1
 
+/* Define to 1 if you have the `getpeername' function. */
+#cmakedefine HAVE_GETPEERNAME 1
+
+/* Define to 1 if you have the `getsockname' function. */
+#cmakedefine HAVE_GETSOCKNAME 1
+
 /* Define to 1 if you have the `getpwuid' function. */
 #cmakedefine HAVE_GETPWUID 1
 
@@ -930,8 +936,8 @@
 /* if PolarSSL is enabled */
 #cmakedefine USE_POLARSSL 1
 
-/* if DarwinSSL is enabled */
-#cmakedefine USE_DARWINSSL 1
+/* if Secure Transport is enabled */
+#cmakedefine USE_SECTRANSP 1
 
 /* if mbedTLS is enabled */
 #cmakedefine USE_MBEDTLS 1

+ 5 - 5
Utilities/cmcurl/lib/curl_endian.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
 }
 
 /*
- * Curl_write32_le()
+ * write32_le()
  *
  * This function converts a 32-bit integer from the native endian format,
  * to little endian format ready for sending down the wire.
@@ -92,7 +92,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
  * value    [in]     - The 32-bit integer value.
  * buffer   [in]     - A pointer to the output buffer.
  */
-void Curl_write32_le(const int value, unsigned char *buffer)
+static void write32_le(const int value, unsigned char *buffer)
 {
   buffer[0] = (char)(value & 0x000000FF);
   buffer[1] = (char)((value & 0x0000FF00) >> 8);
@@ -118,7 +118,7 @@ void Curl_write64_le(const long long value, unsigned char *buffer)
 void Curl_write64_le(const __int64 value, unsigned char *buffer)
 #endif
 {
-  Curl_write32_le((int)value, buffer);
-  Curl_write32_le((int)(value >> 32), buffer + 4);
+  write32_le((int)value, buffer);
+  write32_le((int)(value >> 32), buffer + 4);
 }
 #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */

+ 4 - 11
Utilities/cmcurl/lib/curl_fnmatch.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include <curl/curl.h>
 
 #include "curl_fnmatch.h"
@@ -32,15 +32,6 @@
 
 #ifndef HAVE_FNMATCH
 
-/*
- * TODO:
- *
- * Make this function match POSIX. Test 1307 includes a set of test patterns
- * that returns different results with a POSIX fnmatch() than with this
- * implementation and this is considered a bug where POSIX is the guiding
- * light.
- */
-
 #define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
 
@@ -394,3 +385,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
 }
 
 #endif
+
+#endif /* if FTP is disabled */

+ 55 - 0
Utilities/cmcurl/lib/curl_get_line.c

@@ -0,0 +1,55 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_get_line.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline.
+ */
+char *Curl_get_line(char *buf, int len, FILE *input)
+{
+  bool partial = FALSE;
+  while(1) {
+    char *b = fgets(buf, len, input);
+    if(b) {
+      size_t rlen = strlen(b);
+      if(rlen && (b[rlen-1] == '\n')) {
+        if(partial) {
+          partial = FALSE;
+          continue;
+        }
+        return b;
+      }
+      /* read a partial, discard the next piece that ends with newline */
+      partial = TRUE;
+    }
+    else
+      break;
+  }
+  return NULL;
+}

+ 7 - 11
Utilities/cmcurl/lib/vtls/axtls.h → Utilities/cmcurl/lib/curl_get_line.h

@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_AXTLS_H
-#define HEADER_CURL_AXTLS_H
+#ifndef HEADER_CURL_GET_LINE_H
+#define HEADER_CURL_GET_LINE_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,8 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu <[email protected]>
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,11 +22,8 @@
  *
  ***************************************************************************/
 
-#ifdef USE_AXTLS
-#include "curl/curl.h"
-#include "urldata.h"
+/* get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline. */
+char *Curl_get_line(char *buf, int len, FILE *input);
 
-extern const struct Curl_ssl Curl_ssl_axtls;
-
-#endif /* USE_AXTLS */
-#endif /* HEADER_CURL_AXTLS_H */
+#endif /* HEADER_CURL_GET_LINE_H */

+ 3 - 3
Utilities/cmcurl/lib/curl_gssapi.c

@@ -97,9 +97,9 @@ static size_t display_gss_error(OM_uint32 status, int type,
                                   &msg_ctx,
                                   &status_string);
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
-      len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
-                      "%.*s. ", (int)status_string.length,
-                      (char *)status_string.value);
+      len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
+                       "%.*s. ", (int)status_string.length,
+                       (char *)status_string.value);
     }
     gss_release_buffer(&min_stat, &status_string);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);

+ 1 - 15
Utilities/cmcurl/lib/curl_gssapi.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2011 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,19 +26,6 @@
 #include "urldata.h"
 
 #ifdef HAVE_GSSAPI
-
-#ifdef HAVE_GSSGNU
-#  include <gss.h>
-#elif defined HAVE_GSSMIT
-   /* MIT style */
-#  include <gssapi/gssapi.h>
-#  include <gssapi/gssapi_generic.h>
-#  include <gssapi/gssapi_krb5.h>
-#else
-   /* Heimdal-style */
-#  include <gssapi.h>
-#endif
-
 extern gss_OID_desc Curl_spnego_mech_oid;
 extern gss_OID_desc Curl_krb5_mech_oid;
 
@@ -71,5 +58,4 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
 #define GSSAUTH_P_PRIVACY   4
 
 #endif /* HAVE_GSSAPI */
-
 #endif /* HEADER_CURL_GSSAPI_H */

+ 3 - 1
Utilities/cmcurl/lib/curl_md4.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,11 +25,13 @@
 #include "curl_setup.h"
 
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
 
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
 
 #endif /* HEADER_CURL_MD4_H */

+ 5 - 5
Utilities/cmcurl/lib/curl_md5.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,10 +53,10 @@ void Curl_md5it(unsigned char *output,
                 const unsigned char *input);
 
 MD5_context * Curl_MD5_init(const MD5_params *md5params);
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len);
-int Curl_MD5_final(MD5_context *context, unsigned char *result);
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len);
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result);
 
 #endif
 

+ 2 - 2
Utilities/cmcurl/lib/curl_memory.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,7 @@
  *
  * File lib/strdup.c is an exception, given that it provides a strdup
  * clone implementation while using malloc. Extra care needed inside
- * this one. TODO: revisit this paragraph and related code.
+ * this one.
  *
  * The need for curl_memory.h inclusion is due to libcurl's feature
  * of allowing library user to provide memory replacement functions,

+ 6 - 6
Utilities/cmcurl/lib/curl_multibyte.c

@@ -64,13 +64,13 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
   char *str_utf8 = NULL;
 
   if(str_w) {
-    int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
-                                           0, NULL, NULL);
-    if(str_utf8_len > 0) {
-      str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+    int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
+                                    NULL, 0, NULL, NULL);
+    if(bytes > 0) {
+      str_utf8 = malloc(bytes);
       if(str_utf8) {
-        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
-                               NULL, FALSE) == 0) {
+        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
+                               NULL, NULL) == 0) {
           free(str_utf8);
           return NULL;
         }

+ 32 - 37
Utilities/cmcurl/lib/curl_ntlm_core.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
    3. USE_GNUTLS
    4. USE_NSS
    5. USE_MBEDTLS
-   6. USE_DARWINSSL
+   6. USE_SECTRANSP
    7. USE_OS400CRYPTO
    8. USE_WIN32_CRYPTO
 
@@ -54,23 +54,15 @@
 
 #ifdef USE_OPENSSL
 
-#  ifdef USE_OPENSSL
-#    include <openssl/des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <openssl/md4.h>
-#    endif
-#    include <openssl/md5.h>
-#    include <openssl/ssl.h>
-#    include <openssl/rand.h>
+#  include <openssl/des.h>
+#  ifndef OPENSSL_NO_MD4
+#    include <openssl/md4.h>
 #  else
-#    include <des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <md4.h>
-#    endif
-#    include <md5.h>
-#    include <ssl.h>
-#    include <rand.h>
+#    include "curl_md4.h"
 #  endif
+#  include <openssl/md5.h>
+#  include <openssl/ssl.h>
+#  include <openssl/rand.h>
 #  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
 #    define DES_key_schedule des_key_schedule
 #    define DES_cblock des_cblock
@@ -111,7 +103,7 @@
 #    include "curl_md4.h"
 #  endif
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 #  include <CommonCrypto/CommonCryptor.h>
 #  include <CommonCrypto/CommonDigest.h>
@@ -300,7 +292,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
   return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
 }
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
                         const unsigned char *key_56)
@@ -447,7 +439,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   setup_des_key(keys + 14, &des);
   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
   gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
@@ -511,7 +503,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
     setup_des_key(pw + 7, &des);
     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
     gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -578,10 +570,14 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
   {
     /* Create NT hashed password. */
 #ifdef USE_OPENSSL
+#if !defined(OPENSSL_NO_MD4)
     MD4_CTX MD4pw;
     MD4_Init(&MD4pw);
     MD4_Update(&MD4pw, pw, 2 * len);
     MD4_Final(ntbuffer, &MD4pw);
+#else
+    Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
 #elif defined(USE_GNUTLS_NETTLE)
     struct md4_ctx MD4pw;
     md4_init(&MD4pw);
@@ -601,7 +597,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #else
     Curl_md4it(ntbuffer, pw, 2 * len);
 #endif
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
 #elif defined(USE_OS400CRYPTO)
     Curl_md4it(ntbuffer, pw, 2 * len);
@@ -631,9 +627,9 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 /* This returns the HMAC MD5 digest */
-CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
-                       const unsigned char *data, unsigned int datalen,
-                       unsigned char *output)
+static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen,
+                         const unsigned char *data, unsigned int datalen,
+                         unsigned char *output)
 {
   HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
 
@@ -678,9 +674,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
 
-  result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
-                         ntlmv2hash);
-
+  result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
+                    ntlmv2hash);
   free(identity);
 
   return result;
@@ -753,12 +748,12 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
     return CURLE_OUT_OF_MEMORY;
 
   /* Create the BLOB structure */
-  snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
-           "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
-           "%c%c%c%c",  /* Reserved = 0 */
-           NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
-           NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
-           0, 0, 0, 0);
+  msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+            "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
+            "%c%c%c%c",  /* Reserved = 0 */
+            NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
+            NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
+            0, 0, 0, 0);
 
   Curl_write64_le(tw, ptr + 24);
   memcpy(ptr + 32, challenge_client, 8);
@@ -766,8 +761,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
 
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
-  result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
-                         NTLMv2_BLOB_LEN + 8, hmac_output);
+  result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+                    NTLMv2_BLOB_LEN + 8, hmac_output);
   if(result) {
     free(ptr);
     return result;
@@ -809,7 +804,7 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[8], challenge_client, 8);
 
-  result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+  result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
   if(result)
     return result;
 

+ 1 - 3
Utilities/cmcurl/lib/curl_ntlm_core.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -43,9 +43,7 @@
 
 /* Define USE_NTRESPONSES in order to make the type-3 message include
  * the NT response message. */
-#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4)
 #define USE_NTRESPONSES
-#endif
 
 /* Define USE_NTLM2SESSION in order to make the type-3 message include the
    NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a

+ 67 - 19
Utilities/cmcurl/lib/curl_ntlm_wb.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +53,8 @@
 #include "url.h"
 #include "strerror.h"
 #include "strdup.h"
+#include "strcase.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -74,7 +76,7 @@
 #  define sclose_nolog(x)  close((x))
 #endif
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
 {
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
     sclose(conn->ntlm_auth_hlpr_socket);
@@ -124,6 +126,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
   struct passwd pw, *pw_res;
   char pwbuf[1024];
 #endif
+  char buffer[STRERROR_LEN];
 
   /* Return if communication with ntlm_auth already set up */
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
@@ -179,13 +182,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
   if(access(ntlm_auth, X_OK) != 0) {
     failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
-          ntlm_auth, errno, Curl_strerror(conn, errno));
+          ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
 
   if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
     failf(conn->data, "Could not open socket pair. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
 
@@ -194,7 +197,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose(sockfds[0]);
     sclose(sockfds[1]);
     failf(conn->data, "Could not fork. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
   else if(!child_pid) {
@@ -206,13 +209,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose_nolog(sockfds[0]);
     if(dup2(sockfds[1], STDIN_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdin. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
 
     if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdout. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
 
@@ -232,7 +235,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
     sclose_nolog(sockfds[1]);
     failf(conn->data, "Could not execl(). errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     exit(1);
   }
 
@@ -332,6 +335,48 @@ done:
   return CURLE_REMOTE_ACCESS_DENIED;
 }
 
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
+                            bool proxy,
+                            const char *header)
+{
+  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
+
+  if(!checkprefix("NTLM", header))
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  header += strlen("NTLM");
+  while(*header && ISSPACE(*header))
+    header++;
+
+  if(*header) {
+    conn->challenge_header = strdup(header);
+    if(!conn->challenge_header)
+      return CURLE_OUT_OF_MEMORY;
+
+    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+  }
+  else {
+    if(*state == NTLMSTATE_LAST) {
+      infof(conn->data, "NTLM auth restarted\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+    }
+    else if(*state == NTLMSTATE_TYPE3) {
+      infof(conn->data, "NTLM handshake rejected\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+      *state = NTLMSTATE_NONE;
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+    else if(*state >= NTLMSTATE_TYPE1) {
+      infof(conn->data, "NTLM handshake failure (internal error)\n");
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+
+    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+  }
+
+  return CURLE_OK;
+}
+
 /*
  * This is for creating ntlm header output by delegating challenge/response
  * to Samba's winbind daemon helper ntlm_auth.
@@ -344,8 +389,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   char **allocuserpwd;
   /* point to the name and password for this */
   const char *userp;
-  /* point to the correct struct with this */
-  struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
 
   CURLcode res = CURLE_OK;
@@ -357,13 +401,13 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->http_proxy.user;
-    ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
   }
   else {
     allocuserpwd = &conn->allocptr.userpwd;
     userp = conn->user;
-    ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
   }
   authp->done = FALSE;
@@ -372,7 +416,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(!userp)
     userp = "";
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   default:
     /* Use Samba's 'winbind' daemon to support NTLM authentication,
@@ -391,7 +435,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
     res = ntlm_wb_init(conn, userp);
     if(res)
       return res;
-    res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+    res = ntlm_wb_response(conn, "YR\n", *state);
     if(res)
       return res;
 
@@ -405,11 +449,12 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
       return CURLE_OUT_OF_MEMORY;
     conn->response_header = NULL;
     break;
+
   case NTLMSTATE_TYPE2:
     input = aprintf("TT %s\n", conn->challenge_header);
     if(!input)
       return CURLE_OUT_OF_MEMORY;
-    res = ntlm_wb_response(conn, input, ntlm->state);
+    res = ntlm_wb_response(conn, input, *state);
     free(input);
     input = NULL;
     if(res)
@@ -420,17 +465,20 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
                             proxy ? "Proxy-" : "",
                             conn->response_header);
     DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
-    ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+    *state = NTLMSTATE_TYPE3; /* we sent a type-3 */
     authp->done = TRUE;
-    Curl_ntlm_wb_cleanup(conn);
+    Curl_http_auth_cleanup_ntlm_wb(conn);
     if(!*allocuserpwd)
       return CURLE_OUT_OF_MEMORY;
     break;
+
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
      * don't send a header in future requests */
-    free(*allocuserpwd);
-    *allocuserpwd = NULL;
+    *state = NTLMSTATE_LAST;
+    /* FALLTHROUGH */
+  case NTLMSTATE_LAST:
+    Curl_safefree(*allocuserpwd);
     authp->done = TRUE;
     break;
   }

+ 7 - 4
Utilities/cmcurl/lib/curl_ntlm_wb.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,11 +27,14 @@
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
 
-/* this is for creating ntlm header output by delegating challenge/response
-   to Samba's winbind daemon helper ntlm_auth */
+/* this is for ntlm header input */
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,
+                            const char *header);
+
+/* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
 

+ 5 - 1
Utilities/cmcurl/lib/curl_path.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
 
 #include "curl_setup.h"
 
+#if defined(USE_SSH)
+
 #include <curl/curl.h>
 #include "curl_memory.h"
 #include "curl_path.h"
@@ -193,3 +195,5 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
   Curl_safefree(*path);
   return CURLE_QUOTE_ERROR;
 }
+
+#endif /* if SSH is used */

+ 4 - 12
Utilities/cmcurl/lib/curl_printf.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
 
 # undef printf
 # undef fprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vfprintf
 # undef vsnprintf
@@ -39,18 +39,10 @@
 # undef vaprintf
 # define printf curl_mprintf
 # define fprintf curl_mfprintf
-# define snprintf curl_msnprintf
+# define msnprintf curl_msnprintf
 # define vprintf curl_mvprintf
 # define vfprintf curl_mvfprintf
-# define vsnprintf curl_mvsnprintf
+# define mvsnprintf curl_mvsnprintf
 # define aprintf curl_maprintf
 # define vaprintf curl_mvaprintf
-
-/* We define away the sprintf functions unconditonally since we don't want
-   internal code to be using them, intentionally or by mistake!*/
-# undef sprintf
-# undef vsprintf
-# define sprintf sprintf_was_used
-# define vsprintf vsprintf_was_used
-
 #endif /* HEADER_CURL_PRINTF_H */

+ 5 - 4
Utilities/cmcurl/lib/curl_rtmp.c

@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, et al.
  * Copyright (C) 2010, Howard Chu, <[email protected]>
  *
  * This software is licensed as described in the file COPYING, which
@@ -239,17 +239,18 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
 
 static CURLcode rtmp_do(struct connectdata *conn, bool *done)
 {
+  struct Curl_easy *data = conn->data;
   RTMP *r = conn->proto.generic;
 
   if(!RTMP_ConnectStream(r, 0))
     return CURLE_FAILED_INIT;
 
   if(conn->data->set.upload) {
-    Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_pgrsSetUploadSize(data, data->state.infilesize);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
   }
   else
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   return CURLE_OK;
 }

+ 20 - 20
Utilities/cmcurl/lib/curl_sasl.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +31,9 @@
 
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
+  !defined(CURL_DISABLE_POP3)
+
 #include <curl/curl.h>
 #include "urldata.h"
 
@@ -83,14 +86,14 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
 #if defined(USE_KERBEROS5)
   /* Cleanup the gssapi structure */
   if(authused == SASL_MECH_GSSAPI) {
-    Curl_auth_gssapi_cleanup(&conn->krb5);
+    Curl_auth_cleanup_gssapi(&conn->krb5);
   }
 #endif
 
 #if defined(USE_NTLM)
   /* Cleanup the NTLM structure */
   if(authused == SASL_MECH_NTLM) {
-    Curl_auth_ntlm_cleanup(&conn->ntlm);
+    Curl_auth_cleanup_ntlm(&conn->ntlm);
   }
 #endif
 
@@ -290,7 +293,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
 #if defined(USE_KERBEROS5)
     if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
        Curl_auth_user_contains_domain(conn->user)) {
-      sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+      sasl->mutual_auth = FALSE;
       mech = SASL_MECH_STRING_GSSAPI;
       state1 = SASL_GSSAPI;
       state2 = SASL_GSSAPI_TOKEN;
@@ -300,8 +303,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
         result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                       conn->passwd,
                                                       service,
-                                                      data->easy_conn->
-                                                            host.name,
+                                                      data->conn->host.name,
                                                       sasl->mutual_auth,
                                                       NULL, &conn->krb5,
                                                       &resp, &len);
@@ -358,10 +360,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_XOAUTH2;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                       NULL, 0,
-                                                       conn->oauth_bearer,
-                                                       &resp, &len);
+        result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                        conn->oauth_bearer,
+                                                        &resp, &len);
     }
     else if(enabledmechs & SASL_MECH_PLAIN) {
       mech = SASL_MECH_STRING_PLAIN;
@@ -369,8 +370,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_PLAIN;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                                &resp, &len);
+        result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                                conn->passwd, &resp, &len);
     }
     else if(enabledmechs & SASL_MECH_LOGIN) {
       mech = SASL_MECH_STRING_LOGIN;
@@ -452,9 +453,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     *progress = SASL_DONE;
     return result;
   case SASL_PLAIN:
-    result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                            &resp,
-                                            &len);
+    result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                            conn->passwd, &resp, &len);
     break;
   case SASL_LOGIN:
     result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
@@ -517,7 +517,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                   conn->passwd,
                                                   service,
-                                                  data->easy_conn->host.name,
+                                                  data->conn->host.name,
                                                   sasl->mutual_auth, NULL,
                                                   &conn->krb5,
                                                   &resp, &len);
@@ -563,10 +563,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
       newstate = SASL_OAUTH2_RESP;
     }
     else
-      result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                     NULL, 0,
-                                                     conn->oauth_bearer,
-                                                     &resp, &len);
+      result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                      conn->oauth_bearer,
+                                                      &resp, &len);
     break;
 
   case SASL_OAUTH2_RESP:
@@ -627,3 +626,4 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
 
   return result;
 }
+#endif /* protocols are enabled that use SASL */

+ 20 - 9
Utilities/cmcurl/lib/curl_setup.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -314,11 +314,12 @@
 #endif
 
 #ifdef __AMIGA__
-#  ifndef __ixemul__
-#    include <exec/types.h>
-#    include <exec/execbase.h>
-#    include <proto/exec.h>
-#    include <proto/dos.h>
+#  include <exec/types.h>
+#  include <exec/execbase.h>
+#  include <proto/exec.h>
+#  include <proto/dos.h>
+#  ifdef HAVE_PROTO_BSDSOCKET_H
+#    include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
 #    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 #  endif
 #endif
@@ -661,9 +662,9 @@ int netware_init(void);
 #define LIBIDN_REQUIRED_VERSION "0.4.1"
 
 #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
-    defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
+    defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
-    defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
+    defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK)
 #define USE_SSL    /* SSL support has been enabled */
 #endif
 
@@ -682,7 +683,7 @@ int netware_init(void);
 /* Single point where USE_NTLM definition might be defined */
 #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
-    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
+    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
     defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
     defined(USE_MBEDTLS)
 
@@ -700,6 +701,10 @@ int netware_init(void);
 #error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
 #endif
 
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
+#define USE_SSH
+#endif
+
 /*
  * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
  * Parameters should of course normally not be unused, but for example when
@@ -831,4 +836,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
                size_t buflen, struct passwd **result);
 #endif
 
+#ifdef DEBUGBUILD
+#define UNITTEST
+#else
+#define UNITTEST static
+#endif
+
 #endif /* HEADER_CURL_SETUP_H */

+ 5 - 6
Utilities/cmcurl/lib/curlx.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -81,22 +81,21 @@
 # undef printf
 # undef fprintf
 # undef sprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vfprintf
 # undef vsprintf
-# undef vsnprintf
+# undef mvsnprintf
 # undef aprintf
 # undef vaprintf
 
 # define printf curlx_mprintf
 # define fprintf curlx_mfprintf
 # define sprintf curlx_msprintf
-# define snprintf curlx_msnprintf
+# define msnprintf curlx_msnprintf
 # define vprintf curlx_mvprintf
 # define vfprintf curlx_mvfprintf
-# define vsprintf curlx_mvsprintf
-# define vsnprintf curlx_mvsnprintf
+# define mvsnprintf curlx_mvsnprintf
 # define aprintf curlx_maprintf
 # define vaprintf curlx_mvaprintf
 #endif /* ENABLE_CURLX_PRINTF */

+ 4 - 7
Utilities/cmcurl/lib/dict.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -137,7 +137,6 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
   char *path = data->state.up.path;
-  curl_off_t *bytecount = &data->req.bytecount;
 
   *done = TRUE; /* unconditionally */
 
@@ -200,8 +199,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       return result;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
   }
   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -247,8 +245,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       return result;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   }
   else {
 
@@ -270,7 +267,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
         return result;
       }
 
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
     }
   }
 

+ 87 - 40
Utilities/cmcurl/lib/doh.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,19 @@
 
 #include "curl_setup.h"
 
+#ifndef CURL_DISABLE_DOH
+
 #include "urldata.h"
 #include "curl_addrinfo.h"
 #include "doh.h"
 
-#ifdef USE_NGHTTP2
 #include "sendf.h"
 #include "multiif.h"
 #include "url.h"
 #include "share.h"
 #include "curl_base64.h"
 #include "connect.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -143,8 +145,8 @@ doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
     /* suspiciously much for us */
     return 0;
 
-  mem->memory = realloc(mem->memory, mem->size + realsize);
-  if(mem->memory == NULL)
+  mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
+  if(!mem->memory)
     /* out of memory! */
     return 0;
 
@@ -160,7 +162,7 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   struct Curl_easy *data = doh->set.dohfor;
   /* so one of the DOH request done for the 'data' transfer is now complete! */
   data->req.doh.pending--;
-  infof(data, "a DOH request is completed, %d to go\n", data->req.doh.pending);
+  infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
   if(result)
     infof(data, "DOH request %s\n", curl_easy_strerror(result));
 
@@ -173,8 +175,12 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   return 0;
 }
 
-#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y);   \
-  if(result) goto error
+#define ERROR_CHECK_SETOPT(x,y) \
+do {                                      \
+  result = curl_easy_setopt(doh, x, y);   \
+  if(result)                              \
+    goto error;                           \
+} WHILE_FALSE
 
 static CURLcode dohprobe(struct Curl_easy *data,
                          struct dnsprobe *p, DNStype dnstype,
@@ -234,13 +240,76 @@ static CURLcode dohprobe(struct Curl_easy *data,
       ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
     }
     ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+#ifdef USE_NGHTTP2
     ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#endif
 #ifndef CURLDEBUG
     /* enforce HTTPS if not debug */
     ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
 #endif
     ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
-    ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.verbose)
+      ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.no_signal)
+      ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
+
+    /* Inherit *some* SSL options from the user's transfer. This is a
+       best-guess as to which options are needed for compatibility. #3661 */
+    if(data->set.ssl.falsestart)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
+    if(data->set.ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
+    if(data->set.proxy_ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
+    if(data->set.ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
+    if(data->set.proxy_ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+    if(data->set.ssl.primary.verifystatus)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
+    if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_PROXY]);
+    }
+    if(data->set.ssl.certinfo)
+      ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
+    if(data->set.str[STRING_SSL_RANDOM_FILE]) {
+      ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE,
+        data->set.str[STRING_SSL_RANDOM_FILE]);
+    }
+    if(data->set.str[STRING_SSL_EGDSOCKET]) {
+      ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET,
+        data->set.str[STRING_SSL_EGDSOCKET]);
+    }
+    if(data->set.ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.proxy_ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.ssl.fsslctx)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
+    if(data->set.ssl.fsslctxp)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+
     doh->set.fmultidone = Curl_doh_done;
     doh->set.dohfor = data; /* identify for which transfer this is done */
     p->easy = doh;
@@ -515,7 +584,6 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
   unsigned short qdcount;
   unsigned short ancount;
   unsigned short type = 0;
-  unsigned short class;
   unsigned short rdlength;
   unsigned short nscount;
   unsigned short arcount;
@@ -524,7 +592,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
   if(dohlen < 12)
     return DOH_TOO_SMALL_BUFFER; /* too small */
-  if(doh[0] || doh[1])
+  if(!doh || doh[0] || doh[1])
     return DOH_DNS_BAD_ID; /* bad ID */
   rcode = doh[3] & 0x0f;
   if(rcode)
@@ -543,6 +611,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
   ancount = get16bit(doh, 6);
   while(ancount) {
+    unsigned short class;
     unsigned int ttl;
 
     rc = skipqname(doh, dohlen, &index);
@@ -660,13 +729,13 @@ static void showdoh(struct Curl_easy *data,
       char buffer[128];
       char *ptr;
       size_t len;
-      snprintf(buffer, 128, "DOH AAAA: ");
+      msnprintf(buffer, 128, "DOH AAAA: ");
       ptr = &buffer[10];
       len = 118;
       for(j = 0; j < 16; j += 2) {
         size_t l;
-        snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
-                 d->addr[i].ip.v6[j + 1]);
+        msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+                  d->addr[i].ip.v6[j + 1]);
         l = strlen(ptr);
         len -= l;
         ptr += l;
@@ -827,8 +896,6 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
     DOHcode rc;
     DOHcode rc2;
     struct dohentry de;
-    struct Curl_dns_entry *dns;
-    struct Curl_addrinfo *ai;
     /* remove DOH handles from multi handle and close them */
     curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
     Curl_close(data->req.doh.probe[0].easy);
@@ -853,11 +920,14 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                      &de);
     free(data->req.doh.probe[1].serverdoh.memory);
     if(rc2) {
-      infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+      infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
             type2name(data->req.doh.probe[1].dnstype),
             data->req.doh.host);
     }
     if(!rc || !rc2) {
+      struct Curl_dns_entry *dns;
+      struct Curl_addrinfo *ai;
+
       infof(data, "DOH Host name: %s\n", data->req.doh.host);
       showdoh(data, &de);
 
@@ -894,27 +964,4 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
   return CURLE_OK;
 }
 
-#else /* !USE_NGHTTP2 */
-/*
- */
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        int *waitp)
-{
-  (void)conn;
-  (void)hostname;
-  (void)port;
-  (void)waitp;
-  return NULL;
-}
-
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
-                              struct Curl_dns_entry **dnsp)
-{
-  (void)conn;
-  (void)dnsp;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* USE_NGHTTP2 */
+#endif /* CURL_DISABLE_DOH */

+ 9 - 1
Utilities/cmcurl/lib/doh.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +25,8 @@
 #include "urldata.h"
 #include "curl_addrinfo.h"
 
+#ifndef CURL_DISABLE_DOH
+
 /*
  * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
  * and returns a 'Curl_addrinfo *' with the address information.
@@ -102,4 +104,10 @@ DOHcode doh_decode(unsigned char *doh,
                    struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 #endif
+
+#else /* if DOH is disabled */
+#define Curl_doh(a,b,c,d) NULL
+#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#endif
+
 #endif /* HEADER_CURL_DOH_H */

+ 27 - 84
Utilities/cmcurl/lib/easy.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +75,7 @@
 #include "ssh.h"
 #include "setopt.h"
 #include "http_digest.h"
+#include "system_win32.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -83,70 +84,6 @@
 
 void Curl_version_init(void);
 
-/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
-   of win32_init() */
-static void win32_cleanup(void)
-{
-#ifdef USE_WINSOCK
-  WSACleanup();
-#endif
-#ifdef USE_WINDOWS_SSPI
-  Curl_sspi_global_cleanup();
-#endif
-}
-
-/* win32_init() performs win32 socket initialization to properly setup the
-   stack to allow networking */
-static CURLcode win32_init(void)
-{
-#ifdef USE_WINSOCK
-  WORD wVersionRequested;
-  WSADATA wsaData;
-  int res;
-
-#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
-  Error IPV6_requires_winsock2
-#endif
-
-  wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
-
-  res = WSAStartup(wVersionRequested, &wsaData);
-
-  if(res != 0)
-    /* Tell the user that we couldn't find a usable */
-    /* winsock.dll.     */
-    return CURLE_FAILED_INIT;
-
-  /* Confirm that the Windows Sockets DLL supports what we need.*/
-  /* Note that if the DLL supports versions greater */
-  /* than wVersionRequested, it will still return */
-  /* wVersionRequested in wVersion. wHighVersion contains the */
-  /* highest supported version. */
-
-  if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
-     HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
-    /* Tell the user that we couldn't find a usable */
-
-    /* winsock.dll. */
-    WSACleanup();
-    return CURLE_FAILED_INIT;
-  }
-  /* The Windows Sockets DLL is acceptable. Proceed. */
-#elif defined(USE_LWIPSOCK)
-  lwip_init();
-#endif
-
-#ifdef USE_WINDOWS_SSPI
-  {
-    CURLcode result = Curl_sspi_global_init();
-    if(result)
-      return result;
-  }
-#endif
-
-  return CURLE_OK;
-}
-
 /* true globals -- for curl_global_init() and curl_global_cleanup() */
 static unsigned int  initialized;
 static long          init_flags;
@@ -223,11 +160,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     return CURLE_FAILED_INIT;
   }
 
-  if(flags & CURL_GLOBAL_WIN32)
-    if(win32_init()) {
-      DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
-      return CURLE_FAILED_INIT;
-    }
+#ifdef WIN32
+  if(Curl_win32_init(flags)) {
+    DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+#endif
 
 #ifdef __AMIGA__
   if(!Curl_amiga_init()) {
@@ -327,12 +265,12 @@ void curl_global_cleanup(void)
   if(--initialized)
     return;
 
-  Curl_global_host_cache_dtor();
   Curl_ssl_cleanup();
   Curl_resolver_global_cleanup();
 
-  if(init_flags & CURL_GLOBAL_WIN32)
-    win32_cleanup();
+#ifdef WIN32
+  Curl_win32_cleanup(init_flags);
+#endif
 
   Curl_amiga_cleanup();
 
@@ -489,8 +427,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
            mask. Convert from libcurl bitmask to the poll one. */
         m->socket.events = socketcb2poll(what);
         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       break;
     }
@@ -513,8 +451,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         m->socket.revents = 0;
         ev->list = m;
         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       else
         return CURLE_OUT_OF_MEMORY;
@@ -621,7 +559,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
       return CURLE_RECV_ERROR;
 
     if(mcode)
-      return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
+      return CURLE_URL_MALFORMAT;
 
     /* we don't really care about the "msgs_in_queue" value returned in the
        second argument */
@@ -664,12 +602,12 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
   while(!done && !mcode) {
     int still_running = 0;
-    int rc;
+    bool gotsocket = FALSE;
 
-    mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
+    mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket);
 
     if(!mcode) {
-      if(!rc) {
+      if(!gotsocket) {
         long sleep_ms;
 
         /* If it returns without any filedescriptor instantly, we need to
@@ -688,6 +626,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
     /* only read 'still_running' if curl_multi_perform() return OK */
     if(!mcode && !still_running) {
+      int rc;
       CURLMsg *msg = curl_multi_info_read(multi, &rc);
       if(msg) {
         result = msg->data.result;
@@ -966,7 +905,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   }
 
   /* Clone the resolver handle, if present, for the new handle */
-  if(Curl_resolver_duphandle(&outcurl->state.resolver,
+  if(Curl_resolver_duphandle(outcurl,
+                             &outcurl->state.resolver,
                              data->state.resolver))
     goto fail;
 
@@ -1021,7 +961,10 @@ void curl_easy_reset(struct Curl_easy *data)
   /* zero out authentication data: */
   memset(&data->state.authhost, 0, sizeof(struct auth));
   memset(&data->state.authproxy, 0, sizeof(struct auth));
-  Curl_digest_cleanup(data);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+  Curl_http_auth_cleanup_digest(data);
+#endif
 }
 
 /*
@@ -1058,7 +1001,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
     unsigned int i;
     unsigned int count = data->state.tempcount;
     struct tempbuf writebuf[3]; /* there can only be three */
-    struct connectdata *conn = data->easy_conn;
+    struct connectdata *conn = data->conn;
     struct Curl_easy *saved_data = NULL;
 
     /* copy the structs to allow for immediate re-pausing */

+ 1 - 1
Utilities/cmcurl/lib/escape.c

@@ -122,7 +122,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
         return NULL;
       }
 
-      snprintf(&ns[strindex], 4, "%%%02X", in);
+      msnprintf(&ns[strindex], 4, "%%%02X", in);
 
       strindex += 3;
     }

+ 15 - 14
Utilities/cmcurl/lib/file.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -311,7 +311,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(result)
       break;
 
-    if(readcount <= 0)  /* fix questionable compare error. curlvms */
+    if(!readcount)
       break;
 
     nread = readcount;
@@ -417,8 +417,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     struct tm buffer;
     const struct tm *tm = &buffer;
     char header[80];
-    snprintf(header, sizeof(header),
-             "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+    msnprintf(header, sizeof(header),
+              "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+              expected_size);
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
       return result;
@@ -434,16 +435,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
       return result;
 
     /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-    snprintf(header, sizeof(header),
-             "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
-             Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-             tm->tm_mday,
-             Curl_month[tm->tm_mon],
-             tm->tm_year + 1900,
-             tm->tm_hour,
-             tm->tm_min,
-             tm->tm_sec,
-             data->set.opt_no_body ? "": "\r\n");
+    msnprintf(header, sizeof(header),
+              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
+              Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+              tm->tm_mday,
+              Curl_month[tm->tm_mon],
+              tm->tm_year + 1900,
+              tm->tm_hour,
+              tm->tm_min,
+              tm->tm_sec,
+              data->set.opt_no_body ? "": "\r\n");
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
       return result;

+ 3 - 2
Utilities/cmcurl/lib/fileinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2010 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include "strdup.h"
 #include "fileinfo.h"
 #include "curl_memory.h"
@@ -41,3 +41,4 @@ void Curl_fileinfo_cleanup(struct fileinfo *finfo)
   Curl_safefree(finfo->info.b_data);
   free(finfo);
 }
+#endif

+ 7 - 7
Utilities/cmcurl/lib/formdata.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,14 +24,14 @@
 
 #include <curl/curl.h>
 
-#ifndef CURL_DISABLE_HTTP
+#include "formdata.h"
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
 #endif
 
 #include "urldata.h" /* for struct Curl_easy */
-#include "formdata.h"
 #include "mime.h"
 #include "non-ascii.h"
 #include "vtls/vtls.h"
@@ -569,7 +569,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(((form->flags & HTTPPOST_FILENAME) ||
           (form->flags & HTTPPOST_BUFFER)) &&
          !form->contenttype) {
-        char *f = form->flags & HTTPPOST_BUFFER?
+        char *f = (form->flags & HTTPPOST_BUFFER)?
           form->showfilename : form->value;
         char const *type;
         type = Curl_mime_contenttype(f);
@@ -921,7 +921,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   return result;
 }
 
-#else  /* CURL_DISABLE_HTTP */
+#else
+/* if disabled */
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
                           struct curl_httppost **last_post,
                           ...)
@@ -946,5 +947,4 @@ void curl_formfree(struct curl_httppost *form)
   /* does nothing HTTP is disabled */
 }
 
-
-#endif  /* !defined(CURL_DISABLE_HTTP) */
+#endif  /* if disabled */

+ 10 - 1
Utilities/cmcurl/lib/formdata.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,10 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_MIME
+
 /* used by FormAdd for temporary storage */
 typedef struct FormInfo {
   char *name;
@@ -47,5 +51,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                           curl_mimepart *,
                           struct curl_httppost *post,
                           curl_read_callback fread_func);
+#else
+/* disabled */
+#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
+#endif
+
 
 #endif /* HEADER_CURL_FORMDATA_H */

+ 47 - 56
Utilities/cmcurl/lib/ftp.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -448,7 +448,6 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
 static CURLcode InitiateTransfer(struct connectdata *conn)
 {
   struct Curl_easy *data = conn->data;
-  struct FTP *ftp = data->req.protop;
   CURLcode result = CURLE_OK;
 
   if(conn->bits.ftp_use_data_ssl) {
@@ -461,24 +460,19 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   }
 
   if(conn->proto.ftpc.state_saved == FTP_STOR) {
-    *(ftp->bytecountp) = 0;
-
     /* When we know we're uploading a specified file, we can get the file
        size prior to the actual upload. */
-
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
-                        SECONDARYSOCKET, ftp->bytecountp);
+    Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
   }
   else {
     /* FTP download: */
-    Curl_setup_transfer(conn, SECONDARYSOCKET,
-                        conn->proto.ftpc.retr_size_saved, FALSE,
-                        ftp->bytecountp, -1, NULL); /* no upload here */
+    Curl_setup_transfer(data, SECONDARYSOCKET,
+                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
   }
 
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
@@ -578,7 +572,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
 
 #if defined(HAVE_GSSAPI)
   /* handle the security-oriented responses 6xx ***/
-  /* FIXME: some errorchecking perhaps... ***/
   switch(code) {
   case 631:
     code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
@@ -655,7 +648,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 
   while(!*ftpcode && !result) {
     /* check and reset timeout value every lap */
-    time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+    time_t timeout = Curl_pp_state_timeout(pp, FALSE);
     time_t interval_ms;
 
     if(timeout <= 0) {
@@ -955,7 +948,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   unsigned short port_max = 0;
   unsigned short port;
   bool possibly_non_local = TRUE;
-
+  char buffer[STRERROR_LEN];
   char *addr = NULL;
 
   /* Step 1, figure out what is requested,
@@ -1064,11 +1057,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   if(!host) {
     /* not an interface and not a host name, get default by extracting
        the IP from the control connection */
-
     sslen = sizeof(ss);
     if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
       failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       free(addr);
       return CURLE_FTP_PORT_FAILED;
     }
@@ -1087,7 +1079,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   }
 
   /* resolv ip/host to ip */
-  rc = Curl_resolv(conn, host, 0, &h);
+  rc = Curl_resolv(conn, host, 0, FALSE, &h);
   if(rc == CURLRESOLV_PENDING)
     (void)Curl_resolver_wait_resolv(conn, &h);
   if(h) {
@@ -1121,7 +1113,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     break;
   }
   if(!ai) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, error));
+    failf(data, "socket failure: %s",
+          Curl_strerror(error, buffer, sizeof(buffer)));
     return CURLE_FTP_PORT_FAILED;
   }
 
@@ -1145,14 +1138,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         /* The requested bind address is not local.  Use the address used for
          * the control connection instead and restart the port loop
          */
-
         infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
         sslen = sizeof(ss);
         if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
           failf(data, "getsockname() failed: %s",
-                Curl_strerror(conn, SOCKERRNO) );
+                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
           Curl_closesocket(conn, portsock);
           return CURLE_FTP_PORT_FAILED;
         }
@@ -1162,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       }
       if(error != EADDRINUSE && error != EACCES) {
         failf(data, "bind(port=%hu) failed: %s", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
         Curl_closesocket(conn, portsock);
         return CURLE_FTP_PORT_FAILED;
       }
@@ -1185,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   sslen = sizeof(ss);
   if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
     failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
   }
@@ -1193,7 +1185,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   /* step 4, listen on the socket */
 
   if(listen(portsock, 1)) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
+    failf(data, "socket failure: %s",
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
   }
@@ -1272,7 +1265,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         source++;
       }
       *dest = 0;
-      snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 
       result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
       if(result) {
@@ -1658,7 +1651,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
         infof(data, "File already completely uploaded\n");
 
         /* no data to transfer */
-        Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+        Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
         /* Set ->transfer so that we won't get any error in
          * ftp_done() because we didn't transfer anything! */
@@ -1940,7 +1933,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      */
     const char * const host_name = conn->bits.socksproxy ?
       conn->socks_proxy.host.name : conn->http_proxy.host.name;
-    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
+    rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
@@ -1956,7 +1949,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
   }
   else {
     /* normal, direct, ftp connection */
-    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
+    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING */
       (void)Curl_resolver_wait_resolv(conn, &addr);
@@ -2061,9 +2054,9 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
         char timebuf[24];
         time_t secs = time(NULL);
 
-        snprintf(timebuf, sizeof(timebuf),
-                 "%04d%02d%02d %02d:%02d:%02d GMT",
-                 year, month, day, hour, minute, second);
+        msnprintf(timebuf, sizeof(timebuf),
+                  "%04d%02d%02d %02d:%02d:%02d GMT",
+                  year, month, day, hour, minute, second);
         /* now, convert this into a time() value: */
         data->info.filetime = curl_getdate(timebuf, &secs);
       }
@@ -2086,15 +2079,15 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
           return result;
 
         /* format: "Tue, 15 Nov 1994 12:45:26" */
-        snprintf(headerbuf, sizeof(headerbuf),
-                 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-                 tm->tm_mday,
-                 Curl_month[tm->tm_mon],
-                 tm->tm_year + 1900,
-                 tm->tm_hour,
-                 tm->tm_min,
-                 tm->tm_sec);
+        msnprintf(headerbuf, sizeof(headerbuf),
+                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+                  tm->tm_mday,
+                  Curl_month[tm->tm_mon],
+                  tm->tm_year + 1900,
+                  tm->tm_hour,
+                  tm->tm_min,
+                  tm->tm_sec);
         result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
         if(result)
           return result;
@@ -2230,7 +2223,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
 
     if(ftp->downloadsize == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded\n");
 
       /* Set ->transfer so that we won't get any error in ftp_done()
@@ -2276,8 +2269,8 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
     if(-1 != filesize) {
       char clbuf[128];
-      snprintf(clbuf, sizeof(clbuf),
-               "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+      msnprintf(clbuf, sizeof(clbuf),
+                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
       result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
       if(result)
         return result;
@@ -3054,7 +3047,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
                                     bool *done)
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
+  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
 
   /* Check for the state outside of the Curl_socket_check() return code checks
      since at times we are in fact already in this state when this function
@@ -3071,7 +3064,7 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
   CURLcode result = CURLE_OK;
 
   while(ftpc->state != FTP_STOP) {
-    result = Curl_pp_statemach(pp, TRUE);
+    result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
     if(result)
       break;
   }
@@ -3308,33 +3301,33 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     ;
   else if(data->set.upload) {
     if((-1 != data->state.infilesize) &&
-       (data->state.infilesize != *ftp->bytecountp) &&
+       (data->state.infilesize != data->req.writebytecount) &&
        !data->set.crlf &&
        (ftp->transfer == FTPTRANSFER_BODY)) {
       failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
-            *ftp->bytecountp, data->state.infilesize);
+            data->req.bytecount, data->state.infilesize);
       result = CURLE_PARTIAL_FILE;
     }
   }
   else {
     if((-1 != data->req.size) &&
-       (data->req.size != *ftp->bytecountp) &&
+       (data->req.size != data->req.bytecount) &&
 #ifdef CURL_DO_LINEEND_CONV
        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
         * we'll check to see if the discrepancy can be explained by the number
         * of CRLFs we've changed to LFs.
         */
        ((data->req.size + data->state.crlf_conversions) !=
-        *ftp->bytecountp) &&
+        data->req.bytecount) &&
 #endif /* CURL_DO_LINEEND_CONV */
-       (data->req.maxdownload != *ftp->bytecountp)) {
+       (data->req.maxdownload != data->req.bytecount)) {
       failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
-            " bytes", *ftp->bytecountp);
+            " bytes", data->req.bytecount);
       result = CURLE_PARTIAL_FILE;
     }
     else if(!ftpc->dont_check &&
-            !*ftp->bytecountp &&
+            !data->req.bytecount &&
             (data->req.size>0)) {
       failf(data, "No data was received!");
       result = CURLE_FTP_COULDNT_RETR_FILE;
@@ -3496,7 +3489,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
     if(Curl_connect_ongoing(conn)) {
       /* 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 */
+         aren't used so we blank their arguments. */
       result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
 
       return result;
@@ -3629,7 +3622,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!result && (ftp->transfer != FTPTRANSFER_BODY))
     /* no data to transfer. FIX: it feels like a kludge to have this here
        too! */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
   if(!ftpc->wait_data_conn) {
     /* no waiting for the data connection so this is now complete */
@@ -4309,7 +4302,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
 
   if(ftp->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
   else if(!connected)
     /* since we didn't connect now, we want do_more to get called */
     conn->bits.do_more = TRUE;
@@ -4396,7 +4389,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     return CURLE_OUT_OF_MEMORY;
 
   ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
-  data->state.slash_removed = TRUE; /* we've skipped the slash */
 
   /* FTP URLs support an extension like ";type=<typecode>" that
    * we'll try to get now! */
@@ -4429,7 +4421,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
   }
 
   /* get some initial data into the ftp struct */
-  ftp->bytecountp = &conn->data->req.bytecount;
   ftp->transfer = FTPTRANSFER_BODY;
   ftp->downloadsize = 0;
 

+ 1 - 2
Utilities/cmcurl/lib/ftp.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -102,7 +102,6 @@ typedef enum {
    perhaps the Curl_easy is changed between the times the connection is
    used. */
 struct FTP {
-  curl_off_t *bytecountp;
   char *user;    /* user name string */
   char *passwd;  /* password string */
   char *path;    /* points to the urlpieces struct field */

+ 2 - 5
Utilities/cmcurl/lib/ftplistparser.c

@@ -405,7 +405,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             /* start FSM again not considering size of directory */
             finfo->b_used = 0;
-            i--;
+            continue;
           }
           break;
         case PL_UNIX_TOTALSIZE_READING:
@@ -914,10 +914,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       case PL_WINNT_DIRORSIZE:
         switch(parser->state.NT.sub.dirorsize) {
         case PL_WINNT_DIRORSIZE_PRESPACE:
-          if(c == ' ') {
-
-          }
-          else {
+          if(c != ' ') {
             parser->item_offset = finfo->b_used - 1;
             parser->item_length = 1;
             parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;

+ 4 - 4
Utilities/cmcurl/lib/getinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -163,10 +163,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
       *param_longp = (long)data->info.filetime;
     break;
   case CURLINFO_HEADER_SIZE:
-    *param_longp = data->info.header_size;
+    *param_longp = (long)data->info.header_size;
     break;
   case CURLINFO_REQUEST_SIZE:
-    *param_longp = data->info.request_size;
+    *param_longp = (long)data->info.request_size;
     break;
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
@@ -390,7 +390,7 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
                                           param_slistp;
       struct curl_tlssessioninfo *tsi = &data->tsi;
 #ifdef USE_SSL
-      struct connectdata *conn = data->easy_conn;
+      struct connectdata *conn = data->conn;
 #endif
 
       *tsip = tsi;

+ 21 - 7
Utilities/cmcurl/lib/gopher.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,9 +31,11 @@
 #include "progress.h"
 #include "gopher.h"
 #include "select.h"
+#include "strdup.h"
 #include "url.h"
 #include "escape.h"
 #include "warnless.h"
+#include "curl_printf.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
@@ -76,9 +78,9 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-
-  curl_off_t *bytecount = &data->req.bytecount;
+  char *gopherpath;
   char *path = data->state.up.path;
+  char *query = data->state.up.query;
   char *sel = NULL;
   char *sel_org = NULL;
   ssize_t amount, k;
@@ -86,20 +88,33 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
   *done = TRUE; /* unconditionally */
 
+  /* path is guaranteed non-NULL */
+  DEBUGASSERT(path);
+
+  if(query)
+    gopherpath = aprintf("%s?%s", path, query);
+  else
+    gopherpath = strdup(path);
+
+  if(!gopherpath)
+    return CURLE_OUT_OF_MEMORY;
+
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
-  if(strlen(path) <= 2) {
+  if(strlen(gopherpath) <= 2) {
     sel = (char *)"";
     len = strlen(sel);
+    free(gopherpath);
   }
   else {
     char *newp;
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
-    newp = path;
+    newp = gopherpath;
     newp += 2;
 
     /* ... and finally unescape */
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+    free(gopherpath);
     if(result)
       return result;
     sel_org = sel;
@@ -153,8 +168,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   if(result)
     return result;
 
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                      -1, NULL); /* no upload */
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   return CURLE_OK;
 }
 #endif /*CURL_DISABLE_GOPHER*/

+ 4 - 4
Utilities/cmcurl/lib/hostasyn.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -85,14 +85,14 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
       dns = Curl_cache_addr(data, ai,
                             conn->async.hostname,
                             conn->async.port);
+      if(data->share)
+        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
       if(!dns) {
         /* failed to store, cleanup and return error */
         Curl_freeaddrinfo(ai);
         result = CURLE_OUT_OF_MEMORY;
       }
-
-      if(data->share)
-        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
     }
     else {
       result = CURLE_OUT_OF_MEMORY;

+ 4 - 7
Utilities/cmcurl/lib/hostcheck.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,6 @@
 #include "curl_setup.h"
 
 #if defined(USE_OPENSSL)                                \
-  || defined(USE_AXTLS)                                 \
   || defined(USE_GSKIT)                                 \
   || defined(USE_SCHANNEL)
 /* these backends use functions from this file */
@@ -128,16 +127,14 @@ static int hostmatch(char *hostname, char *pattern)
 
 int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
 {
-  char *matchp;
-  char *hostp;
   int res = 0;
   if(!match_pattern || !*match_pattern ||
       !hostname || !*hostname) /* sanity check */
     ;
   else {
-    matchp = strdup(match_pattern);
+    char *matchp = strdup(match_pattern);
     if(matchp) {
-      hostp = strdup(hostname);
+      char *hostp = strdup(hostname);
       if(hostp) {
         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
           res = 1;
@@ -150,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
   return res;
 }
 
-#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
+#endif /* OPENSSL, GSKIT or schannel+wince */

+ 56 - 97
Utilities/cmcurl/lib/hostip.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -73,6 +73,8 @@
 #define USE_ALARM_TIMEOUT
 #endif
 
+#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
+
 /*
  * hostip.c explained
  * ==================
@@ -112,42 +114,8 @@
  * CURLRES_* defines based on the config*.h and curl_setup.h defines.
  */
 
-/* These two symbols are for the global DNS cache */
-static struct curl_hash hostname_cache;
-static int host_cache_initialized;
-
 static void freednsentry(void *freethis);
 
-/*
- * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
- * Global DNS cache is general badness. Do not use. This will be removed in
- * a future version. Use the share interface instead!
- *
- * Returns a struct curl_hash pointer on success, NULL on failure.
- */
-struct curl_hash *Curl_global_host_cache_init(void)
-{
-  int rc = 0;
-  if(!host_cache_initialized) {
-    rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
-                        Curl_str_key_compare, freednsentry);
-    if(!rc)
-      host_cache_initialized = 1;
-  }
-  return rc?NULL:&hostname_cache;
-}
-
-/*
- * Destroy and cleanup the global DNS cache
- */
-void Curl_global_host_cache_dtor(void)
-{
-  if(host_cache_initialized) {
-    Curl_hash_destroy(&hostname_cache);
-    host_cache_initialized = 0;
-  }
-}
-
 /*
  * Return # of addresses in a Curl_addrinfo struct
  */
@@ -198,23 +166,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
 }
 
 /*
- * Return a hostcache id string for the provided host + port, to be used by
- * the DNS caching.
+ * Create a hostcache id string for the provided host + port, to be used by
+ * the DNS caching. Without alloc.
  */
-static char *
-create_hostcache_id(const char *name, int port)
+static void
+create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
 {
-  /* create and return the new allocated entry */
-  char *id = aprintf("%s:%d", name, port);
-  char *ptr = id;
-  if(ptr) {
-    /* lower case the name part */
-    while(*ptr && (*ptr != ':')) {
-      *ptr = (char)TOLOWER(*ptr);
-      ptr++;
-    }
-  }
-  return id;
+  size_t len = strlen(name);
+  if(len > (buflen - 7))
+    len = buflen - 7;
+  /* store and lower case the name */
+  while(len--)
+    *ptr++ = (char)TOLOWER(*name++);
+  msnprintf(ptr, 7, ":%u", port);
 }
 
 struct hostcache_prune_data {
@@ -296,22 +260,27 @@ fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 int port)
 {
-  char *entry_id = NULL;
   struct Curl_dns_entry *dns = NULL;
   size_t entry_len;
   struct Curl_easy *data = conn->data;
+  char entry_id[MAX_HOSTCACHE_LEN];
 
   /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return dns;
-
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
   entry_len = strlen(entry_id);
 
   /* See if its already in our dns cache */
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
+  /* No entry found in cache, check if we might have a wildcard entry */
+  if(!dns && data->change.wildcard_resolve) {
+    create_hostcache_id("*", port, entry_id, sizeof(entry_id));
+    entry_len = strlen(entry_id);
+
+    /* See if it's 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;
@@ -326,9 +295,6 @@ fetch_addr(struct connectdata *conn,
     }
   }
 
-  /* free the allocated entry_id again */
-  free(entry_id);
-
   return dns;
 }
 
@@ -368,6 +334,9 @@ Curl_fetch_addr(struct connectdata *conn,
   return dns;
 }
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr);
 /*
  * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
  * struct by re-linking its linked list.
@@ -380,7 +349,8 @@ Curl_fetch_addr(struct connectdata *conn,
  *
  * @unittest: 1608
  */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr)
 {
   CURLcode result = CURLE_OK;
   const int num_addrs = Curl_num_addresses(*addr);
@@ -431,6 +401,7 @@ CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
   }
   return result;
 }
+#endif
 
 /*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
@@ -447,32 +418,30 @@ Curl_cache_addr(struct Curl_easy *data,
                 const char *hostname,
                 int port)
 {
-  char *entry_id;
+  char entry_id[MAX_HOSTCACHE_LEN];
   size_t entry_len;
   struct Curl_dns_entry *dns;
   struct Curl_dns_entry *dns2;
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
   /* shuffle addresses if requested */
   if(data->set.dns_shuffle_addresses) {
     CURLcode result = Curl_shuffle_addr(data, &addr);
     if(result)
       return NULL;
   }
-
-  /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return NULL;
-  entry_len = strlen(entry_id);
+#endif
 
   /* Create a new cache entry */
   dns = calloc(1, sizeof(struct Curl_dns_entry));
   if(!dns) {
-    free(entry_id);
     return NULL;
   }
 
+  /* Create an entry id, based upon the hostname and port */
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
+  entry_len = strlen(entry_id);
+
   dns->inuse = 1;   /* the cache has the first reference */
   dns->addr = addr; /* this is the address(es) */
   time(&dns->timestamp);
@@ -484,16 +453,11 @@ Curl_cache_addr(struct Curl_easy *data,
                        (void *)dns);
   if(!dns2) {
     free(dns);
-    free(entry_id);
     return NULL;
   }
 
   dns = dns2;
   dns->inuse++;         /* mark entry as in-use */
-
-  /* free the allocated entry_id */
-  free(entry_id);
-
   return dns;
 }
 
@@ -521,6 +485,7 @@ Curl_cache_addr(struct Curl_easy *data,
 int Curl_resolv(struct connectdata *conn,
                 const char *hostname,
                 int port,
+                bool allowDOH,
                 struct Curl_dns_entry **entry)
 {
   struct Curl_dns_entry *dns = NULL;
@@ -548,7 +513,7 @@ int Curl_resolv(struct connectdata *conn,
     /* The entry was not in the cache. Resolve it to IP address */
 
     Curl_addrinfo *addr;
-    int respwait;
+    int respwait = 0;
 
     /* Check what IP specifics the app has requested and if we can provide it.
      * If not, bail out. */
@@ -566,7 +531,7 @@ int Curl_resolv(struct connectdata *conn,
         return CURLRESOLV_ERROR;
     }
 
-    if(data->set.doh) {
+    if(allowDOH && data->set.doh) {
       addr = Curl_doh(conn, hostname, port, &respwait);
     }
     else {
@@ -692,7 +657,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
 
   if(!timeout)
     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
-    return Curl_resolv(conn, hostname, port, entry);
+    return Curl_resolv(conn, hostname, port, TRUE, entry);
 
   if(timeout < 1000) {
     /* The alarm() function only provides integer second resolution, so if
@@ -754,7 +719,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
   /* Perform the actual name resolution. This might be interrupted by an
    * alarm if it takes too long.
    */
-  rc = Curl_resolv(conn, hostname, port, entry);
+  rc = Curl_resolv(conn, hostname, port, TRUE, entry);
 
 #ifdef USE_ALARM_TIMEOUT
 clean_up:
@@ -872,11 +837,14 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
   char hostname[256];
   int port = 0;
 
+  /* Default is no wildcard found */
+  data->change.wildcard_resolve = false;
+
   for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
+    char entry_id[MAX_HOSTCACHE_LEN];
     if(!hostp->data)
       continue;
     if(hostp->data[0] == '-') {
-      char *entry_id;
       size_t entry_len;
 
       if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
@@ -886,12 +854,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
 
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        return CURLE_OUT_OF_MEMORY;
-      }
-
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
 
       if(data->share)
@@ -902,14 +865,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
-      /* free the allocated entry_id again */
-      free(entry_id);
     }
     else {
       struct Curl_dns_entry *dns;
       Curl_addrinfo *head = NULL, *tail = NULL;
-      char *entry_id;
       size_t entry_len;
       char address[64];
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -1005,12 +964,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
 
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        Curl_freeaddrinfo(head);
-        return CURLE_OUT_OF_MEMORY;
-      }
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
 
       if(data->share)
@@ -1031,8 +985,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
         Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
       }
-      /* free the allocated entry_id again */
-      free(entry_id);
 
       /* put this new host in the cache */
       dns = Curl_cache_addr(data, head, hostname, port);
@@ -1052,6 +1004,13 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
       infof(data, "Added %s:%d:%s to DNS cache\n",
             hostname, port, addresses);
+
+      /* Wildcard hostname */
+      if(hostname[0] == '*' && hostname[1] == '\0') {
+        infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
+              hostname, port);
+        data->change.wildcard_resolve = true;
+      }
     }
   }
   data->change.resolve = NULL; /* dealt with now */

+ 6 - 13
Utilities/cmcurl/lib/hostip.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,8 +83,11 @@ struct Curl_dns_entry {
 #define CURLRESOLV_ERROR    -1
 #define CURLRESOLV_RESOLVED  0
 #define CURLRESOLV_PENDING   1
-int Curl_resolv(struct connectdata *conn, const char *hostname,
-                int port, struct Curl_dns_entry **dnsentry);
+int Curl_resolv(struct connectdata *conn,
+                const char *hostname,
+                int port,
+                bool allowDOH,
+                struct Curl_dns_entry **dnsentry);
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
                         time_t timeoutms);
@@ -178,16 +181,6 @@ Curl_fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 int port);
 
-/*
- * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
- * struct by re-linking its linked list.
- *
- * The addr argument should be the address of a pointer to the head node of a
- * `Curl_addrinfo` list and it will be modified to point to the new head after
- * shuffling.
- */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
-
 /*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
  *

+ 2 - 2
Utilities/cmcurl/lib/hostip4.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -145,7 +145,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
     hints.ai_family = PF_INET;
     hints.ai_socktype = SOCK_STREAM;
     if(port) {
-      snprintf(sbuf, sizeof(sbuf), "%d", port);
+      msnprintf(sbuf, sizeof(sbuf), "%d", port);
       sbufptr = sbuf;
     }
 

+ 8 - 6
Utilities/cmcurl/lib/hostip6.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -101,14 +101,16 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
 {
   printf("dump_addrinfo:\n");
   for(; ai; ai = ai->ai_next) {
-    char  buf[INET6_ADDRSTRLEN];
-
+    char buf[INET6_ADDRSTRLEN];
     printf("    fam %2d, CNAME %s, ",
            ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
     if(Curl_printable_address(ai, buf, sizeof(buf)))
       printf("%s\n", buf);
-    else
-      printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
+    else {
+      char buffer[STRERROR_LEN];
+      printf("failed; %s\n",
+             Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+    }
   }
 }
 #else
@@ -178,7 +180,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
 #endif
 
   if(port) {
-    snprintf(sbuf, sizeof(sbuf), "%d", port);
+    msnprintf(sbuf, sizeof(sbuf), "%d", port);
     sbufptr = sbuf;
   }
 

+ 318 - 174
Utilities/cmcurl/lib/http.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -73,10 +73,10 @@
 #include "http_proxy.h"
 #include "warnless.h"
 #include "non-ascii.h"
-#include "pipeline.h"
 #include "http2.h"
 #include "connect.h"
 #include "strdup.h"
+#include "altsvc.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -92,7 +92,9 @@ static int http_getsock_do(struct connectdata *conn,
                            int numsocks);
 static int http_should_fail(struct connectdata *conn);
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+#endif
 
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done);
@@ -102,13 +104,14 @@ static int https_getsock(struct connectdata *conn,
 #else
 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
 #endif
+static CURLcode http_setup_conn(struct connectdata *conn);
 
 /*
  * HTTP handler interface.
  */
 const struct Curl_handler Curl_handler_http = {
   "HTTP",                               /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -133,7 +136,7 @@ const struct Curl_handler Curl_handler_http = {
  */
 const struct Curl_handler Curl_handler_https = {
   "HTTPS",                              /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -153,7 +156,7 @@ const struct Curl_handler Curl_handler_https = {
 };
 #endif
 
-CURLcode Curl_http_setup_conn(struct connectdata *conn)
+static CURLcode http_setup_conn(struct connectdata *conn)
 {
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
@@ -175,7 +178,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   return CURLE_OK;
 }
 
-
+#ifndef CURL_DISABLE_PROXY
 /*
  * checkProxyHeaders() checks the linked list of custom proxy headers
  * if proxy headers are not available, then it will lookup into http header
@@ -202,6 +205,10 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
 
   return NULL;
 }
+#else
+/* disabled */
+#define Curl_checkProxyheaders(x,y) NULL
+#endif
 
 /*
  * Strip off leading and trailing whitespace from the value in the
@@ -256,6 +263,7 @@ char *Curl_copy_header_value(const char *header)
   return value;
 }
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
  * http_output_basic() sets up an Authorization: header (or the proxy version)
  * for HTTP Basic authentication.
@@ -337,6 +345,8 @@ static CURLcode http_output_bearer(struct connectdata *conn)
   return result;
 }
 
+#endif
+
 /* pickoneauth() selects the most favourable authentication method from the
  * ones available and the ones we want.
  *
@@ -415,7 +425,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
     break;
   }
 
-  bytessent = http->writebytecount;
+  bytessent = data->req.writebytecount;
 
   if(conn->bits.authneg) {
     /* This is a state where we are known to be negotiating and we don't send
@@ -456,8 +466,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
        (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)) {
+         (conn->http_ntlm_state != NTLMSTATE_NONE) ||
+         (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
            data left to send, keep on sending. */
 
@@ -479,8 +489,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
             (curl_off_t)(expectsend - bytessent));
     }
 #endif
+#if defined(USE_SPNEGO)
+    /* There is still data left to send */
+    if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
+       (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
+      if(((expectsend - bytessent) < 2000) ||
+         (conn->http_negotiate_state != GSS_AUTHNONE) ||
+         (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
+        /* The NEGOTIATE-negotiation has started *OR*
+        there is just a little (<2K) data left to send, keep on sending. */
+
+        /* rewind data when completely done sending! */
+        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
+          conn->bits.rewindaftersend = TRUE;
+          infof(data, "Rewind stream after send\n");
+        }
+
+        return CURLE_OK;
+      }
 
-    /* This is not NTLM or many bytes left to send: close */
+      if(conn->bits.close)
+        /* this is already marked to get closed */
+        return CURLE_OK;
+
+      infof(data, "NEGOTIATE send, close instead of sending %"
+        CURL_FORMAT_CURL_OFF_T " bytes\n",
+        (curl_off_t)(expectsend - bytessent));
+    }
+#endif
+
+    /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     data->req.size = 0; /* don't download any more than 0 bytes */
 
@@ -526,6 +564,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
     pickhost = pickoneauth(&data->state.authhost, authmask);
     if(!pickhost)
       data->state.authproblem = TRUE;
+    if(data->state.authhost.picked == CURLAUTH_NTLM &&
+       conn->httpversion > 11) {
+      infof(data, "Forcing HTTP/1.1 for NTLM");
+      connclose(conn, "Force HTTP/1.1 connection");
+      conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+    }
   }
   if(conn->bits.proxy_user_passwd &&
      ((data->req.httpcode == 407) ||
@@ -576,6 +620,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   return result;
 }
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
  * Output the correct authentication header depending on the auth type
  * and whether or not it is to a proxy.
@@ -592,10 +637,6 @@ output_auth_headers(struct connectdata *conn,
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
   struct Curl_easy *data = conn->data;
 #endif
-#ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy ?
-    &data->state.proxyneg : &data->state.negotiate;
-#endif
 
 #ifdef CURL_DISABLE_CRYPTO_AUTH
   (void)request;
@@ -603,15 +644,11 @@ output_auth_headers(struct connectdata *conn,
 #endif
 
 #ifdef USE_SPNEGO
-  negdata->state = GSS_AUTHNONE;
-  if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
-     negdata->context && !GSS_ERROR(negdata->status)) {
+  if((authstatus->picked == CURLAUTH_NEGOTIATE)) {
     auth = "Negotiate";
     result = Curl_output_negotiate(conn, proxy);
     if(result)
       return result;
-    authstatus->done = TRUE;
-    negdata->state = GSS_AUTHSENT;
   }
   else
 #endif
@@ -697,7 +734,7 @@ output_auth_headers(struct connectdata *conn,
  *
  * @param conn all information about the current connection
  * @param request pointer to the request keyword
- * @param path pointer to the requested path
+ * @param path pointer to the requested path; should include query part
  * @param proxytunnel boolean if this is the request setting up a "proxy
  * tunnel"
  *
@@ -744,7 +781,7 @@ Curl_http_output_auth(struct connectdata *conn,
 #ifndef CURL_DISABLE_PROXY
   /* Send proxy authentication header if needed */
   if(conn->bits.httpproxy &&
-      (conn->bits.tunnel_proxy == proxytunnel)) {
+     (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
     result = output_auth_headers(conn, authproxy, request, path, TRUE);
     if(result)
       return result;
@@ -772,6 +809,22 @@ Curl_http_output_auth(struct connectdata *conn,
   return result;
 }
 
+#else
+/* when disabled */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+                      const char *request,
+                      const char *path,
+                      bool proxytunnel)
+{
+  (void)conn;
+  (void)request;
+  (void)path;
+  (void)proxytunnel;
+  return CURLE_OK;
+}
+#endif
+
 /*
  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
  * headers. They are dealt with both in the transfer.c main loop and in the
@@ -787,8 +840,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
   struct Curl_easy *data = conn->data;
 
 #ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy?
-    &data->state.proxyneg:&data->state.negotiate;
+  curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
+                                    &conn->http_negotiate_state;
 #endif
   unsigned long *availp;
   struct auth *authp;
@@ -827,21 +880,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
         authp->avail |= CURLAUTH_NEGOTIATE;
 
         if(authp->picked == CURLAUTH_NEGOTIATE) {
-          if(negdata->state == GSS_AUTHSENT ||
-             negdata->state == GSS_AUTHNONE) {
-            CURLcode result = Curl_input_negotiate(conn, proxy, auth);
-            if(!result) {
-              DEBUGASSERT(!data->req.newurl);
-              data->req.newurl = strdup(data->change.url);
-              if(!data->req.newurl)
-                return CURLE_OUT_OF_MEMORY;
-              data->state.authproblem = FALSE;
-              /* we received a GSS auth token and we dealt with it fine */
-              negdata->state = GSS_AUTHRECV;
-            }
-            else
-              data->state.authproblem = TRUE;
+          CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+          if(!result) {
+            DEBUGASSERT(!data->req.newurl);
+            data->req.newurl = strdup(data->change.url);
+            if(!data->req.newurl)
+              return CURLE_OUT_OF_MEMORY;
+            data->state.authproblem = FALSE;
+            /* we received a GSS auth token and we dealt with it fine */
+            *negstate = GSS_AUTHRECV;
           }
+          else
+            data->state.authproblem = TRUE;
         }
       }
     }
@@ -869,19 +919,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                 *availp |= CURLAUTH_NTLM_WB;
                 authp->avail |= CURLAUTH_NTLM_WB;
 
-                /* Get the challenge-message which will be passed to
-                 * ntlm_auth for generating the type 3 message later */
-                while(*auth && ISSPACE(*auth))
-                  auth++;
-                if(checkprefix("NTLM", auth)) {
-                  auth += strlen("NTLM");
-                  while(*auth && ISSPACE(*auth))
-                    auth++;
-                  if(*auth) {
-                    conn->challenge_header = strdup(auth);
-                    if(!conn->challenge_header)
-                      return CURLE_OUT_OF_MEMORY;
-                  }
+                result = Curl_input_ntlm_wb(conn, proxy, auth);
+                if(result) {
+                  infof(data, "Authentication problem. Ignoring this.\n");
+                  data->state.authproblem = TRUE;
                 }
               }
 #endif
@@ -1111,14 +1152,13 @@ void Curl_add_buffer_free(Curl_send_buffer **inp)
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
 
-                               /* add the number of sent bytes to this
-                                  counter */
-                              long *bytes_written,
+                              /* add the number of sent bytes to this
+                                 counter */
+                              curl_off_t *bytes_written,
 
-                               /* how much of the buffer contains body data */
+                              /* how much of the buffer contains body data */
                               size_t included_body_bytes,
                               int socketindex)
-
 {
   ssize_t amount;
   CURLcode result;
@@ -1214,7 +1254,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
     if(http) {
       /* if we sent a piece of the body here, up the byte counter for it
          accordingly */
-      http->writebytecount += bodylen;
+      data->req.writebytecount += bodylen;
+      Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
 
       if((size_t)amount != size) {
         /* The whole request could not be sent in one system call. We must
@@ -1255,7 +1296,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
            This needs FIXing.
         */
         return CURLE_SEND_ERROR;
-      Curl_pipeline_leave_write(conn);
     }
   }
   Curl_add_buffer_free(&in);
@@ -1432,12 +1472,14 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->data->set.haproxyprotocol) {
     /* add HAProxy PROXY protocol header */
     result = add_haproxy_protocol_header(conn);
     if(result)
       return result;
   }
+#endif
 
   if(conn->given->protocol & CURLPROTO_HTTPS) {
     /* perform SSL initialization */
@@ -1464,6 +1506,7 @@ static int http_getsock_do(struct connectdata *conn,
   return GETSOCK_WRITESOCK(0);
 }
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 {
   char proxy_header[128];
@@ -1479,14 +1522,14 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
     strcpy(tcp_version, "TCP4");
   }
 
-  snprintf(proxy_header,
-           sizeof(proxy_header),
-           "PROXY %s %s %s %li %li\r\n",
-           tcp_version,
-           conn->data->info.conn_local_ip,
-           conn->data->info.conn_primary_ip,
-           conn->data->info.conn_local_port,
-           conn->data->info.conn_primary_port);
+  msnprintf(proxy_header,
+            sizeof(proxy_header),
+            "PROXY %s %s %s %li %li\r\n",
+            tcp_version,
+            conn->data->info.conn_local_ip,
+            conn->data->info.conn_primary_ip,
+            conn->data->info.conn_local_port,
+            conn->data->info.conn_primary_port);
 
   req_buffer = Curl_add_buffer_init();
   if(!req_buffer)
@@ -1504,6 +1547,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 
   return result;
 }
+#endif
 
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done)
@@ -1547,20 +1591,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_unencode_cleanup(conn);
 
-#ifdef USE_SPNEGO
-  if(data->state.proxyneg.state == GSS_AUTHSENT ||
-     data->state.negotiate.state == GSS_AUTHSENT) {
-    /* add forbid re-use if http-code != 401/407 as a WA only needed for
-     * 401/407 that signal auth failure (empty) otherwise state will be RECV
-     * with current code.
-     * Do not close CONNECT_ONLY connections. */
-    if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
-       !data->set.connect_only)
-      streamclose(conn, "Negotiate transfer completed");
-    Curl_cleanup_negotiate(data);
-  }
-#endif
-
   /* set the proper values (possibly modified on POST) */
   conn->seek_func = data->set.seek_func; /* restore */
   conn->seek_client = data->set.seek_client; /* restore */
@@ -1576,16 +1606,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_mime_cleanpart(&http->form);
 
-  switch(data->set.httpreq) {
-  case HTTPREQ_PUT:
-  case HTTPREQ_POST_FORM:
-  case HTTPREQ_POST_MIME:
-    data->req.bytecount = http->readbytecount + http->writebytecount;
-    break;
-  default:
-    break;
-  }
-
   if(status)
     return status;
 
@@ -1593,7 +1613,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
                       entire operation is complete */
      !conn->bits.retry &&
      !data->set.connect_only &&
-     (http->readbytecount +
+     (data->req.bytecount +
       data->req.headerbytecount -
       data->req.deductheadercount) <= 0) {
     /* If this connection isn't simply closed to be retried, AND nothing was
@@ -1676,6 +1696,50 @@ enum proxy_use {
   HEADER_CONNECT  /* sending CONNECT to a proxy */
 };
 
+/* used to compile the provided trailers into one buffer
+   will return an error code if one of the headers is
+   not formatted correctly */
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle)
+{
+  char *ptr = NULL;
+  CURLcode result = CURLE_OK;
+  const char *endofline_native = NULL;
+  const char *endofline_network = NULL;
+
+  if(
+#ifdef CURL_DO_LINEEND_CONV
+     (handle->set.prefer_ascii) ||
+#endif
+     (handle->set.crlf)) {
+    /* \n will become \r\n later on */
+    endofline_native  = "\n";
+    endofline_network = "\x0a";
+  }
+  else {
+    endofline_native  = "\r\n";
+    endofline_network = "\x0d\x0a";
+  }
+
+  while(trailers) {
+    /* only add correctly formatted trailers */
+    ptr = strchr(trailers->data, ':');
+    if(ptr && *(ptr + 1) == ' ') {
+      result = Curl_add_bufferf(&buffer, "%s%s", trailers->data,
+                                endofline_native);
+      if(result)
+        return result;
+    }
+    else
+      infof(handle, "Malformatted trailing header ! Skipping trailer.");
+    trailers = trailers->next;
+  }
+  result = Curl_add_buffer(&buffer, endofline_network,
+                           strlen(endofline_network));
+  return result;
+}
+
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer)
@@ -1737,9 +1801,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
           }
           else {
             if(*(--ptr) == ';') {
-              /* send no-value custom header if terminated by semicolon */
-              *ptr = ':';
-              semicolonp = ptr;
+              /* copy the source */
+              semicolonp = strdup(headers->data);
+              if(!semicolonp) {
+                Curl_add_buffer_free(&req_buffer);
+                return CURLE_OUT_OF_MEMORY;
+              }
+              /* put a colon where the semicolon is */
+              semicolonp[ptr - headers->data] = ':';
+              /* point at the colon */
+              optr = &semicolonp [ptr - headers->data];
             }
           }
           ptr = optr;
@@ -1755,35 +1826,37 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
         if(*ptr || semicolonp) {
           /* only send this if the contents was non-blank or done special */
           CURLcode result = CURLE_OK;
+          char *compare = semicolonp ? semicolonp : headers->data;
 
           if(conn->allocptr.host &&
              /* a Host: header was sent already, don't pass on any custom Host:
                 header as that will produce *two* in the same request! */
-             checkprefix("Host:", headers->data))
+             checkprefix("Host:", compare))
             ;
           else if(data->set.httpreq == HTTPREQ_POST_FORM &&
                   /* this header (extended by formdata.c) is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
           else if(data->set.httpreq == HTTPREQ_POST_MIME &&
                   /* this header is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
           else if(conn->bits.authneg &&
                   /* while doing auth neg, don't allow the custom length since
                      we will force length zero then */
-                  checkprefix("Content-Length:", headers->data))
+                  checkprefix("Content-Length:", compare))
             ;
           else if(conn->allocptr.te &&
                   /* when asking for Transfer-Encoding, don't pass on a custom
                      Connection: */
-                  checkprefix("Connection:", headers->data))
+                  checkprefix("Connection:", compare))
             ;
           else if((conn->httpversion == 20) &&
-                  checkprefix("Transfer-Encoding:", headers->data))
+                  checkprefix("Transfer-Encoding:", compare))
             /* HTTP/2 doesn't support chunked requests */
             ;
-          else if(checkprefix("Authorization:", headers->data) &&
+          else if((checkprefix("Authorization:", compare) ||
+                   checkprefix("Cookie:", compare)) &&
                   /* be careful of sending this potentially sensitive header to
                      other hosts */
                   (data->state.this_is_a_follow &&
@@ -1792,10 +1865,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
                    !strcasecompare(data->state.first_host, conn->host.name)))
             ;
           else {
-            result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
+            result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare);
           }
           if(semicolonp)
-            *semicolonp = ';'; /* put back the semicolon */
+            free(semicolonp);
           if(result)
             return result;
         }
@@ -1807,6 +1880,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
   return CURLE_OK;
 }
 
+#ifndef CURL_DISABLE_PARSEDATE
 CURLcode Curl_add_timecondition(struct Curl_easy *data,
                                 Curl_send_buffer *req_buffer)
 {
@@ -1850,21 +1924,31 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
    */
 
   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-  snprintf(datestr, sizeof(datestr),
-           "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-           condp,
-           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-           tm->tm_mday,
-           Curl_month[tm->tm_mon],
-           tm->tm_year + 1900,
-           tm->tm_hour,
-           tm->tm_min,
-           tm->tm_sec);
+  msnprintf(datestr, sizeof(datestr),
+            "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+            condp,
+            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+            tm->tm_mday,
+            Curl_month[tm->tm_mon],
+            tm->tm_year + 1900,
+            tm->tm_hour,
+            tm->tm_min,
+            tm->tm_sec);
 
   result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
 
   return result;
 }
+#else
+/* disabled */
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+                                Curl_send_buffer *req_buffer)
+{
+  (void)data;
+  (void)req_buffer;
+  return CURLE_OK;
+}
+#endif
 
 /*
  * Curl_http() gets called from the generic multi_do() function when a HTTP
@@ -1916,6 +2000,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 #ifdef USE_NGHTTP2
       if(conn->data->set.httpversion ==
          CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+        if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+          /* We don't support HTTP/2 proxies yet. Also it's debatable whether
+             or not this setting should apply to HTTP/2 proxies. */
+          infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+          break;
+        }
+
         DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
         conn->httpversion = 20;
 
@@ -1947,7 +2038,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
     data->state.first_remote_port = conn->remote_port;
   }
-  http->writebytecount = http->readbytecount = 0;
 
   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
      data->set.upload) {
@@ -1995,11 +2085,21 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 
   /* setup the authentication headers */
-  result = Curl_http_output_auth(conn, request, path, FALSE);
-  if(result)
-    return result;
+  {
+    char *pq = NULL;
+    if(query && *query) {
+      pq = aprintf("%s?%s", path, query);
+      if(!pq)
+        return CURLE_OUT_OF_MEMORY;
+    }
+    result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
+    free(pq);
+    if(result)
+      return result;
+  }
 
-  if((data->state.authhost.multipass || data->state.authproxy.multipass) &&
+  if(((data->state.authhost.multipass && !data->state.authhost.done)
+      || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
      (httpreq != HTTPREQ_GET) &&
      (httpreq != HTTPREQ_HEAD)) {
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
@@ -2084,6 +2184,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     http->sendit = NULL;
   }
 
+#ifndef CURL_DISABLE_MIME
   if(http->sendit) {
     const char *cthdr = Curl_checkheaders(conn, "Content-Type");
 
@@ -2108,6 +2209,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       return result;
     http->postsize = Curl_mime_size(http->sendit);
   }
+#endif
 
   ptr = Curl_checkheaders(conn, "Transfer-Encoding");
   if(ptr) {
@@ -2293,8 +2395,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
             *p++ = '/';
           }
-          snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
-                   data->set.prefer_ascii ? 'a' : 'i');
+          msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+                    data->set.prefer_ascii ? 'a' : 'i');
         }
       }
       if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
@@ -2635,9 +2737,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending PUT request");
     else
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
       return result;
     break;
@@ -2657,12 +2758,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         failf(data, "Failed sending POST request");
       else
         /* setup variables for the upcoming transfer */
-        Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                            -1, NULL);
+        Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
       break;
     }
 
-    postsize = http->postsize;
+    data->state.infilesize = postsize = http->postsize;
 
     /* We only set Content-Length and allow a custom Content-Length if
        we don't upload data chunked, as RFC2616 forbids us to set both
@@ -2678,6 +2778,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         return result;
     }
 
+#ifndef CURL_DISABLE_MIME
     /* Output mime-generated headers. */
     {
       struct curl_slist *hdr;
@@ -2688,6 +2789,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           return result;
       }
     }
+#endif
 
     /* For really small posts we don't use Expect: headers at all, and for
        the somewhat bigger ones we allow the app to disable it. Just make
@@ -2726,9 +2828,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending POST request");
     else
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
       return result;
 
@@ -2882,9 +2983,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     if(result)
       failf(data, "Failed sending HTTP POST request");
     else
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
     break;
 
   default:
@@ -2900,33 +3000,30 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending HTTP request");
     else
       /* HTTP GET/HEAD download: */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                          http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
   }
   if(result)
     return result;
 
-  if(http->writebytecount) {
+  if(data->req.writebytecount) {
     /* if a request-body has been sent off, we make sure this progress is noted
        properly */
-    Curl_pgrsSetUploadCounter(data, http->writebytecount);
+    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
 
-    if(http->writebytecount >= postsize) {
+    if(data->req.writebytecount >= postsize) {
       /* already sent the entire request body, mark the "upload" as
          complete */
       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
-            http->writebytecount, postsize);
+            data->req.writebytecount, postsize);
       data->req.upload_done = TRUE;
       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
     }
-    else
-      data->req.writebytecount = http->writebytecount;
   }
 
   if((conn->httpversion == 20) && data->req.upload_chunky)
@@ -3161,6 +3258,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           k->header = FALSE;
           k->badheader = HEADER_ALLBAD;
           streamclose(conn, "bad HTTP: No end-of-message indicator");
+          if(!data->set.http09_allowed) {
+            failf(data, "Received HTTP/0.9 when not allowed\n");
+            return CURLE_UNSUPPORTED_PROTOCOL;
+          }
           break;
         }
       }
@@ -3194,6 +3295,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(st == STATUS_BAD) {
         streamclose(conn, "bad HTTP: No end-of-message indicator");
         /* this is not the beginning of a protocol first header line */
+        if(!data->set.http09_allowed) {
+          failf(data, "Received HTTP/0.9 when not allowed\n");
+          return CURLE_UNSUPPORTED_PROTOCOL;
+        }
         k->header = FALSE;
         if(*nread)
           /* since there's more, this is a partial bad header */
@@ -3306,14 +3411,31 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
 #if defined(USE_NTLM)
       if(conn->bits.close &&
          (((data->req.httpcode == 401) &&
-           (conn->ntlm.state == NTLMSTATE_TYPE2)) ||
+           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
           ((data->req.httpcode == 407) &&
-           (conn->proxyntlm.state == NTLMSTATE_TYPE2)))) {
+           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
         data->state.authproblem = TRUE;
       }
 #endif
-
+#if defined(USE_SPNEGO)
+      if(conn->bits.close &&
+        (((data->req.httpcode == 401) &&
+          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
+         ((data->req.httpcode == 407) &&
+          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
+        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+        data->state.authproblem = TRUE;
+      }
+      if((conn->http_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 401)) {
+        conn->http_negotiate_state = GSS_AUTHSUCC;
+      }
+      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 407)) {
+        conn->proxy_negotiate_state = GSS_AUTHSUCC;
+      }
+#endif
       /*
        * When all the headers have been parsed, see if we should give
        * up and return an error.
@@ -3549,6 +3671,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
             if(conn->httpversion != 20)
               infof(data, "Lying server, not serving HTTP/2\n");
           }
+          if(conn->httpversion < 20) {
+            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
+            infof(data, "Mark bundle as not supporting multiuse\n");
+          }
         }
         else if(!nc) {
           /* this is the real world, not a Nirvana
@@ -3586,7 +3712,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
         }
         else {
-          /* TODO: do we care about the other cases here? */
           nc = 0;
         }
       }
@@ -3639,26 +3764,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
         else if(conn->httpversion >= 11 &&
                 !conn->bits.close) {
-          /* If HTTP version is >= 1.1 and connection is persistent
-             server supports pipelining. */
+          /* If HTTP version is >= 1.1 and connection is persistent */
           DEBUGF(infof(data,
-                       "HTTP 1.1 or later with persistent connection, "
-                       "pipelining supported\n"));
-          /* Activate pipelining if needed */
-          if(conn->bundle) {
-            if(!Curl_pipeline_site_blacklisted(data, conn))
-              conn->bundle->multiuse = BUNDLE_PIPELINING;
-          }
+                       "HTTP 1.1 or later with persistent connection\n"));
         }
 
         switch(k->httpcode) {
-        case 204:
-          /* (quote from RFC2616, section 10.2.5): The server has
-           * fulfilled the request but does not need to return an
-           * entity-body ... The 204 response MUST NOT include a
-           * message-body, and thus is always terminated by the first
-           * empty line after the header fields. */
-          /* FALLTHROUGH */
         case 304:
           /* (quote from RFC2616, section 10.3.5): The 304 response
            * MUST NOT contain a message-body, and thus is always
@@ -3666,6 +3777,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
            * fields.  */
           if(data->set.timecondition)
             data->info.timecond = TRUE;
+          /* FALLTHROUGH */
+        case 204:
+          /* (quote from RFC2616, section 10.2.5): The server has
+           * fulfilled the request but does not need to return an
+           * entity-body ... The 204 response MUST NOT include a
+           * message-body, and thus is always terminated by the first
+           * empty line after the header fields. */
           k->size = 0;
           k->maxdownload = 0;
           k->ignorecl = TRUE; /* ignore Content-Length headers */
@@ -3733,19 +3851,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         data->info.contenttype = contenttype;
       }
     }
-    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);
-      }
-    }
     else if((conn->httpversion == 10) &&
             conn->bits.httpproxy &&
             Curl_compareheader(k->p,
@@ -3859,7 +3964,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
                          here, or else use real peer host name. */
                       conn->allocptr.cookiehost?
                       conn->allocptr.cookiehost:conn->host.name,
-                      data->state.up.path);
+                      data->state.up.path,
+                      (conn->handler->protocol&CURLPROTO_HTTPS)?
+                      TRUE:FALSE);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
 #endif
@@ -3888,6 +3995,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(result)
         return result;
     }
+  #ifdef USE_SPNEGO
+    else if(checkprefix("Persistent-Auth", k->p)) {
+      struct negotiatedata *negdata = &conn->negotiate;
+      struct auth *authp = &data->state.authhost;
+      if(authp->picked == CURLAUTH_NEGOTIATE) {
+        char *persistentauth = Curl_copy_header_value(k->p);
+        if(!persistentauth)
+          return CURLE_OUT_OF_MEMORY;
+        negdata->noauthpersist = checkprefix("false", persistentauth);
+        negdata->havenoauthpersist = TRUE;
+        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+          negdata->noauthpersist, persistentauth);
+        free(persistentauth);
+      }
+    }
+  #endif
     else if((k->httpcode >= 300 && k->httpcode < 400) &&
             checkprefix("Location:", k->p) &&
             !data->req.location) {
@@ -3915,6 +4038,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
       }
     }
+#ifdef USE_ALTSVC
+    /* If enabled, the header is incoming and this is over HTTPS */
+    else if(data->asi && checkprefix("Alt-Svc:", k->p) &&
+            ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+             /* allow debug builds to circumvent the HTTPS restriction */
+             getenv("CURL_ALTSVC_HTTP")
+#else
+             0
+#endif
+              )) {
+      /* the ALPN of the current request */
+      enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+      result = Curl_altsvc_parse(data, data->asi,
+                                 &k->p[ strlen("Alt-Svc:") ],
+                                 id, conn->host.name,
+                                 curlx_uitous(conn->remote_port));
+      if(result)
+        return result;
+    }
+#endif
     else if(conn->handler->protocol & CURLPROTO_RTSP) {
       result = Curl_rtsp_parseheader(conn, k->p);
       if(result)

+ 5 - 4
Utilities/cmcurl/lib/http.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
                          size_t size) WARN_UNUSED_RESULT;
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
-                              long *bytes_written,
+                              curl_off_t *bytes_written,
                               size_t included_body_bytes,
                               int socketindex);
 
@@ -74,6 +74,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer);
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle);
 
 /* protocol-specific functions set up to be called by the main engine */
 CURLcode Curl_http(struct connectdata *conn, bool *done);
@@ -136,8 +139,6 @@ struct HTTP {
 
   const char *p_pragma;      /* Pragma: string */
   const char *p_accept;      /* Accept: string */
-  curl_off_t readbytecount;
-  curl_off_t writebytecount;
 
   /* For FORM posting */
   curl_mimepart form;

+ 60 - 16
Utilities/cmcurl/lib/http2.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -111,8 +111,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
   int bitmap = GETSOCK_BLANK;
   (void)numsocks;
 
-  /* TODO We should check underlying socket state if it is SSL socket
-     because of renegotiation. */
   sock[0] = conn->sock[FIRSTSOCKET];
 
   /* in a HTTP/2 connection we can basically always get a frame so we should
@@ -350,14 +348,14 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
 int Curl_http2_ver(char *p, size_t len)
 {
   nghttp2_info *h2 = nghttp2_version(0);
-  return snprintf(p, len, " nghttp2/%s", h2->version_str);
+  return msnprintf(p, len, " nghttp2/%s", h2->version_str);
 }
 
 /* HTTP/2 error code to name based on the Error Code Registry.
 https://tools.ietf.org/html/rfc7540#page-77
 nghttp2_error_code enums are identical.
 */
-const char *Curl_http2_strerror(uint32_t err)
+static const char *http2_strerror(uint32_t err)
 {
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
   const char *str[] = {
@@ -618,6 +616,18 @@ static int push_promise(struct Curl_easy *data,
   return rv;
 }
 
+/*
+ * multi_connchanged() is called to tell that there is a connection in
+ * this multi handle that has changed state (multiplexing become possible, the
+ * number of allowed streams changed or similar), and a subsequent use of this
+ * multi handle should move CONNECT_PEND handles back to CONNECT to have them
+ * retry.
+ */
+static void multi_connchanged(struct Curl_multi *multi)
+{
+  multi->recheckstate = TRUE;
+}
+
 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
                          void *userp)
 {
@@ -650,7 +660,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
         infof(conn->data,
               "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
               httpc->settings.max_concurrent_streams);
-        Curl_multi_connchanged(conn->data->multi);
+        multi_connchanged(conn->data->multi);
       }
     }
     return 0;
@@ -800,7 +810,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
     H2BUGF(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;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
     return NGHTTP2_ERR_PAUSE;
   }
@@ -808,7 +818,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   /* pause execution of nghttp2 if we received data for another handle
      in order to process them first. */
   if(conn->data != data_s) {
-    data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
     return NGHTTP2_ERR_PAUSE;
   }
@@ -837,7 +847,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
       return 0;
     }
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
-                 Curl_http2_strerror(error_code), error_code, stream_id));
+                 http2_strerror(error_code), error_code, stream_id));
     stream = data_s->req.protop;
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -854,6 +864,10 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
             stream_id);
       DEBUGASSERT(0);
     }
+    if(stream_id == httpc->pause_stream_id) {
+      H2BUGF(infof(data_s, "Stopped the pause stream!\n"));
+      httpc->pause_stream_id = 0;
+    }
     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
     stream->stream_id = 0; /* cleared */
   }
@@ -953,6 +967,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
     char *h;
 
+    if(!strcmp(":authority", (const char *)name)) {
+      /* pseudo headers are lower case */
+      int rc = 0;
+      char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
+      if(!check)
+        /* no memory */
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+      if(!Curl_strcasecompare(check, (const char *)value)) {
+        /* This is push is not for the same authority that was asked for in
+         * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
+         * PUSH_PROMISE for which the server is not authoritative as a stream
+         * error of type PROTOCOL_ERROR."
+         */
+        (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+                                        stream_id, NGHTTP2_PROTOCOL_ERROR);
+        rc = NGHTTP2_ERR_CALLBACK_FAILURE;
+      }
+      free(check);
+      if(rc)
+        return rc;
+    }
+
     if(!stream->push_headers) {
       stream->push_headers_alloc = 10;
       stream->push_headers = malloc(stream->push_headers_alloc *
@@ -1193,7 +1229,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
 /*
  * Initialize nghttp2 for a Curl connection
  */
-CURLcode Curl_http2_init(struct connectdata *conn)
+static CURLcode http2_init(struct connectdata *conn)
 {
   if(!conn->proto.httpc.h2) {
     int rc;
@@ -1427,7 +1463,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
-          stream->stream_id, Curl_http2_strerror(httpc->error_code),
+          stream->stream_id, http2_strerror(httpc->error_code),
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
     return -1;
@@ -1809,9 +1845,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
 {
   /*
-   * BIG TODO: Currently, we send request in this function, but this
-   * function is also used to send request body. It would be nice to
-   * add dedicated function for request.
+   * Currently, we send request in this function, but this function is also
+   * used to send request body. It would be nice to add dedicated function for
+   * request.
    */
   int rv;
   struct http_conn *httpc = &conn->proto.httpc;
@@ -2137,7 +2173,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   else
     conn->handler = &Curl_handler_http2;
 
-  result = Curl_http2_init(conn);
+  result = http2_init(conn);
   if(result) {
     Curl_add_buffer_free(&stream->header_recvbuf);
     return result;
@@ -2159,7 +2195,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
 
   infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
-  Curl_multi_connchanged(conn->data->multi);
+  multi_connchanged(conn->data->multi);
 
   return CURLE_OK;
 }
@@ -2367,6 +2403,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
     Curl_http2_remove_child(data->set.stream_depends_on, data);
 }
 
+/* Only call this function for a transfer that already got a HTTP/2
+   CURLE_HTTP2_STREAM error! */
+bool Curl_h2_http_1_1_error(struct connectdata *conn)
+{
+  struct http_conn *httpc = &conn->proto.httpc;
+  return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
+}
+
 #else /* !USE_NGHTTP2 */
 
 /* Satisfy external references even if http2 is not compiled in. */

+ 5 - 2
Utilities/cmcurl/lib/http2.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,8 +59,10 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
 void Curl_http2_remove_child(struct Curl_easy *parent,
                              struct Curl_easy *child);
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
+
+/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
+bool Curl_h2_http_1_1_error(struct connectdata *conn);
 #else /* USE_NGHTTP2 */
-#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -74,6 +76,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #define Curl_http2_add_child(x, y, z)
 #define Curl_http2_remove_child(x, y)
 #define Curl_http2_cleanup_dependencies(x)
+#define Curl_h2_http_1_1_error(x) 0
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */

+ 3 - 2
Utilities/cmcurl/lib/http_digest.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
 #include "strcase.h"
 #include "vauth/vauth.h"
 #include "http_digest.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -171,7 +172,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   return CURLE_OK;
 }
 
-void Curl_digest_cleanup(struct Curl_easy *data)
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data)
 {
   Curl_auth_digest_cleanup(&data->state.digest);
   Curl_auth_digest_cleanup(&data->state.proxydigest);

+ 6 - 6
Utilities/cmcurl/lib/http_digest.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,6 +23,8 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
 /* this is for digest header input */
 CURLcode Curl_input_digest(struct connectdata *conn,
                            bool proxy, const char *header);
@@ -33,10 +35,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
                             const unsigned char *request,
                             const unsigned char *uripath);
 
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-void Curl_digest_cleanup(struct Curl_easy *data);
-#else
-#define Curl_digest_cleanup(x) Curl_nop_stmt
-#endif
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data);
+
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */
 
 #endif /* HEADER_CURL_HTTP_DIGEST_H */

+ 107 - 25
Utilities/cmcurl/lib/http_negotiate.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
   /* Point to the correct struct with this */
   struct negotiatedata *neg_ctx;
+  curlnegotiate state;
 
   if(proxy) {
     userp = conn->http_proxy.user;
@@ -56,7 +57,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     host = conn->http_proxy.host.name;
-    neg_ctx = &data->state.proxyneg;
+    neg_ctx = &conn->proxyneg;
+    state = conn->proxy_negotiate_state;
   }
   else {
     userp = conn->user;
@@ -64,7 +66,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_SERVICE_NAME] ?
               data->set.str[STRING_SERVICE_NAME] : "HTTP";
     host = conn->host.name;
-    neg_ctx = &data->state.negotiate;
+    neg_ctx = &conn->negotiate;
+    state = conn->http_negotiate_state;
   }
 
   /* Not set means empty */
@@ -80,59 +83,138 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     header++;
 
   len = strlen(header);
+  neg_ctx->havenegdata = len != 0;
   if(!len) {
-    /* Is this the first call in a new negotiation? */
-    if(neg_ctx->context) {
-      /* The server rejected our authentication and hasn't suppled any more
+    if(state == GSS_AUTHSUCC) {
+      infof(conn->data, "Negotiate auth restarted\n");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    else if(state != GSS_AUTHNONE) {
+      /* The server rejected our authentication and hasn't supplied any more
       negotiation mechanisms */
+      Curl_http_auth_cleanup_negotiate(conn);
       return CURLE_LOGIN_DENIED;
     }
   }
 
+  /* Supports SSL channel binding for Windows ISS extended protection */
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  neg_ctx->sslContext = conn->sslContext;
+#endif
+
   /* Initialize the security context and decode our challenge */
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
                                            host, header, neg_ctx);
 
   if(result)
-    Curl_auth_spnego_cleanup(neg_ctx);
+    Curl_http_auth_cleanup_negotiate(conn);
 
   return result;
 }
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 {
-  struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg :
-    &conn->data->state.negotiate;
+  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
+    &conn->negotiate;
+  struct auth *authp = proxy ? &conn->data->state.authproxy :
+    &conn->data->state.authhost;
+  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
+                                 &conn->http_negotiate_state;
   char *base64 = NULL;
   size_t len = 0;
   char *userp;
   CURLcode result;
 
-  result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len);
-  if(result)
-    return result;
+  authp->done = FALSE;
 
-  userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
-                  base64);
+  if(*state == GSS_AUTHRECV) {
+    if(neg_ctx->havenegdata) {
+      neg_ctx->havemultiplerequests = TRUE;
+    }
+  }
+  else if(*state == GSS_AUTHSUCC) {
+    if(!neg_ctx->havenoauthpersist) {
+      neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests;
+    }
+  }
 
-  if(proxy) {
-    Curl_safefree(conn->allocptr.proxyuserpwd);
-    conn->allocptr.proxyuserpwd = userp;
+  if(neg_ctx->noauthpersist ||
+    (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
+
+    if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
+      infof(conn->data, "Curl_output_negotiate, "
+       "no persistent authentication: cleanup existing context");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    if(!neg_ctx->context) {
+      result = Curl_input_negotiate(conn, proxy, "Negotiate");
+      if(result == CURLE_LOGIN_DENIED) {
+        /* negotiate auth failed, let's continue unauthenticated to stay
+         * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
+        conn->data->state.authproblem = TRUE;
+        return CURLE_OK;
+      }
+      else if(result)
+        return result;
+    }
+
+    result = Curl_auth_create_spnego_message(conn->data,
+      neg_ctx, &base64, &len);
+    if(result)
+      return result;
+
+    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+      base64);
+
+    if(proxy) {
+      Curl_safefree(conn->allocptr.proxyuserpwd);
+      conn->allocptr.proxyuserpwd = userp;
+    }
+    else {
+      Curl_safefree(conn->allocptr.userpwd);
+      conn->allocptr.userpwd = userp;
+    }
+
+    free(base64);
+
+    if(userp == NULL) {
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    *state = GSS_AUTHSENT;
+  #ifdef HAVE_GSSAPI
+    if(neg_ctx->status == GSS_S_COMPLETE ||
+       neg_ctx->status == GSS_S_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #else
+  #ifdef USE_WINDOWS_SSPI
+    if(neg_ctx->status == SEC_E_OK ||
+       neg_ctx->status == SEC_I_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #endif
+  #endif
   }
-  else {
-    Curl_safefree(conn->allocptr.userpwd);
-    conn->allocptr.userpwd = userp;
+
+  if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) {
+    /* connection is already authenticated,
+     * don't send a header in future requests */
+    authp->done = TRUE;
   }
 
-  free(base64);
+  neg_ctx->havenegdata = FALSE;
 
-  return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+  return CURLE_OK;
 }
 
-void Curl_cleanup_negotiate(struct Curl_easy *data)
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn)
 {
-  Curl_auth_spnego_cleanup(&data->state.negotiate);
-  Curl_auth_spnego_cleanup(&data->state.proxyneg);
+  conn->http_negotiate_state = GSS_AUTHNONE;
+  conn->proxy_negotiate_state = GSS_AUTHNONE;
+
+  Curl_auth_cleanup_spnego(&conn->negotiate);
+  Curl_auth_cleanup_spnego(&conn->proxyneg);
 }
 
 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */

+ 4 - 4
Utilities/cmcurl/lib/http_negotiate.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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 @@
  *
  ***************************************************************************/
 
-#ifdef USE_SPNEGO
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
 
 /* this is for Negotiate header input */
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
@@ -31,8 +31,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 /* this is for creating Negotiate header output */
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
-void Curl_cleanup_negotiate(struct Curl_easy *data);
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
 
-#endif /* USE_SPNEGO */
+#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
 
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */

+ 24 - 16
Utilities/cmcurl/lib/http_ntlm.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,9 +68,11 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
 {
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
+  curlntlm *state;
   CURLcode result = CURLE_OK;
 
   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+  state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
 
   if(checkprefix("NTLM", header)) {
     header += strlen("NTLM");
@@ -83,25 +85,25 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
       if(result)
         return result;
 
-      ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+      *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
     }
     else {
-      if(ntlm->state == NTLMSTATE_LAST) {
+      if(*state == NTLMSTATE_LAST) {
         infof(conn->data, "NTLM auth restarted\n");
-        Curl_http_ntlm_cleanup(conn);
+        Curl_http_auth_cleanup_ntlm(conn);
       }
-      else if(ntlm->state == NTLMSTATE_TYPE3) {
+      else if(*state == NTLMSTATE_TYPE3) {
         infof(conn->data, "NTLM handshake rejected\n");
-        Curl_http_ntlm_cleanup(conn);
-        ntlm->state = NTLMSTATE_NONE;
+        Curl_http_auth_cleanup_ntlm(conn);
+        *state = NTLMSTATE_NONE;
         return CURLE_REMOTE_ACCESS_DENIED;
       }
-      else if(ntlm->state >= NTLMSTATE_TYPE1) {
+      else if(*state >= NTLMSTATE_TYPE1) {
         infof(conn->data, "NTLM handshake failure (internal error)\n");
         return CURLE_REMOTE_ACCESS_DENIED;
       }
 
-      ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+      *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
     }
   }
 
@@ -129,6 +131,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
 
   DEBUGASSERT(conn);
@@ -147,6 +150,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     hostname = conn->http_proxy.host.name;
     ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
   }
   else {
@@ -157,6 +161,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
     hostname = conn->host.name;
     ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
   }
   authp->done = FALSE;
@@ -175,9 +180,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     if(s_hSecDll == NULL)
       return err;
   }
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  ntlm->sslContext = conn->sslContext;
+#endif
 #endif
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
     /* Create a type-1 message */
@@ -219,7 +227,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
 
-      ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+      *state = NTLMSTATE_TYPE3; /* we send a type-3 */
       authp->done = TRUE;
     }
     break;
@@ -227,7 +235,7 @@ 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;
+    *state = NTLMSTATE_LAST;
     /* FALLTHROUGH */
   case NTLMSTATE_LAST:
     Curl_safefree(*allocuserpwd);
@@ -238,13 +246,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   return CURLE_OK;
 }
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
 {
-  Curl_auth_ntlm_cleanup(&conn->ntlm);
-  Curl_auth_ntlm_cleanup(&conn->proxyntlm);
+  Curl_auth_cleanup_ntlm(&conn->ntlm);
+  Curl_auth_cleanup_ntlm(&conn->proxyntlm);
 
 #if defined(NTLM_WB_ENABLED)
-  Curl_ntlm_wb_cleanup(conn);
+  Curl_http_auth_cleanup_ntlm_wb(conn);
 #endif
 }
 

+ 5 - 5
Utilities/cmcurl/lib/http_ntlm.h

@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_CURL_HTTP_NTLM_H
+#define HEADER_CURL_HTTP_NTLM_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,8 +33,8 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
 /* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM */
 
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_CURL_HTTP_NTLM_H */

+ 2 - 2
Utilities/cmcurl/lib/http_proxy.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -643,7 +643,7 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 void Curl_connect_free(struct Curl_easy *data)
 {
-  struct connectdata *conn = data->easy_conn;
+  struct connectdata *conn = data->conn;
   struct http_connect_state *s = conn->connect_state;
   if(s) {
     free(s);

+ 14 - 45
Utilities/cmcurl/lib/if2ip.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -96,26 +96,8 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 
 #if defined(HAVE_GETIFADDRS)
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  bool result = FALSE;
-
-  struct ifaddrs *iface, *head;
-
-  if(getifaddrs(&head) >= 0) {
-    for(iface = head; iface != NULL; iface = iface->ifa_next) {
-      if(strcasecompare(iface->ifa_name, interf)) {
-        result = TRUE;
-        break;
-      }
-    }
-    freeifaddrs(head);
-  }
-  return result;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
   struct ifaddrs *iface, *head;
@@ -127,7 +109,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
     !defined(ENABLE_IPV6)
-  (void) remote_scope_id;
+  (void) local_scope_id;
 #endif
 
   if(getifaddrs(&head) >= 0) {
@@ -141,7 +123,9 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
             char ipstr[64];
 #ifdef ENABLE_IPV6
             if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
               unsigned int scopeid = 0;
+#endif
               unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
 
               if(ifscope != remote_scope) {
@@ -161,15 +145,16 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                             ->sin6_scope_id;
 
               /* If given, scope id should match. */
-              if(remote_scope_id && scopeid != remote_scope_id) {
+              if(local_scope_id && scopeid != local_scope_id) {
                 if(res == IF2IP_NOT_FOUND)
                   res = IF2IP_AF_NOT_SUPPORTED;
 
                 continue;
               }
-#endif
+
               if(scopeid)
-                snprintf(scope, sizeof(scope), "%%%u", scopeid);
+                  msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+#endif
             }
             else
 #endif
@@ -177,7 +162,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                   &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
             res = IF2IP_FOUND;
             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
-            snprintf(buf, buf_size, "%s%s", ip, scope);
+            msnprintf(buf, buf_size, "%s%s", ip, scope);
             break;
           }
         }
@@ -196,17 +181,8 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  /* This is here just to support the old interfaces */
-  char buf[256];
-
-  return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) ==
-          IF2IP_NOT_FOUND) ? FALSE : TRUE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
   struct ifreq req;
@@ -216,7 +192,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
   size_t len;
 
   (void)remote_scope;
-  (void)remote_scope_id;
+  (void)local_scope_id;
 
   if(!interf || (af != AF_INET))
     return IF2IP_NOT_FOUND;
@@ -251,20 +227,13 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #else
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  (void) interf;
-
-  return FALSE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
     (void) af;
     (void) remote_scope;
-    (void) remote_scope_id;
+    (void) local_scope_id;
     (void) interf;
     (void) buf;
     (void) buf_size;

+ 2 - 4
Utilities/cmcurl/lib/if2ip.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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 @@
 
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
 
-bool Curl_if_is_interface_name(const char *interf);
-
 typedef enum {
   IF2IP_NOT_FOUND = 0, /* Interface not found */
   IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
@@ -41,7 +39,7 @@ typedef enum {
 } if2ip_result_t;
 
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size);
 
 #ifdef __INTERIX

+ 19 - 22
Utilities/cmcurl/lib/imap.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
  * RFC4959 IMAP Extension for SASL Initial Client Response
  * RFC5092 IMAP URL Scheme
  * RFC6749 OAuth 2.0 Authorization Framework
+ * RFC8314 Use of TLS for Email Submission and Access
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  *
  ***************************************************************************/
@@ -316,7 +317,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
      a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
      APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
      some e-mail servers ignore this and only send a single + instead. */
-  if(imap && !imap->custom && ((len == 3 && !memcmp("+", line, 1)) ||
+  if(imap && !imap->custom && ((len == 3 && line[0] == '+') ||
      (len >= 2 && !memcmp("+ ", line, 2)))) {
     switch(imapc->state) {
       /* States which are interested in continuation responses */
@@ -1042,7 +1043,7 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
     line[len] = '\0';
   }
   else if(imapcode != IMAP_RESP_OK)
-    result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+    result = CURLE_QUOTE_ERROR;
   else
     /* End of DO phase */
     state(conn, IMAP_STOP);
@@ -1114,7 +1115,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
   if(imapcode != '*') {
     Curl_pgrsSetDownloadSize(data, -1);
     state(conn, IMAP_STOP);
-    return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
+    return CURLE_REMOTE_FILE_NOT_FOUND;
   }
 
   /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
@@ -1177,11 +1178,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
 
     if(data->req.bytecount == size)
       /* The entire data is already transferred! */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
     else {
       /* IMAP download */
       data->req.maxdownload = size;
-      Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
     }
   }
   else {
@@ -1231,7 +1232,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* IMAP upload */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
     /* End of DO phase */
     state(conn, IMAP_STOP);
@@ -1362,19 +1363,20 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_pp_statemach(&imapc->pp, FALSE);
+  result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE);
   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
 
   return result;
 }
 
-static CURLcode imap_block_statemach(struct connectdata *conn)
+static CURLcode imap_block_statemach(struct connectdata *conn,
+                                     bool disconnecting)
 {
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
 
   while(imapc->state != IMAP_STOP && !result)
-    result = Curl_pp_statemach(&imapc->pp, TRUE);
+    result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);
 
   return result;
 }
@@ -1490,14 +1492,9 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
         state(conn, IMAP_APPEND_FINAL);
     }
 
-    /* Run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the imap_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-    */
+    /* Run the state-machine */
     if(!result)
-      result = imap_block_statemach(conn);
+      result = imap_block_statemach(conn, FALSE);
   }
 
   /* Cleanup our per-request based variables */
@@ -1635,7 +1632,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
      point! */
   if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
     if(!imap_perform_logout(conn))
-      (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
+      (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */
 
   /* Disconnect from the server */
   Curl_pp_disconnect(&imapc->pp);
@@ -1659,7 +1656,7 @@ static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
 
   if(imap->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
 
   return CURLE_OK;
 }
@@ -1749,8 +1746,8 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
   imapc->cmdid = (imapc->cmdid + 1) % 1000;
 
   /* Calculate the tag based on the connection ID and command ID */
-  snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
-           'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+  msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+            'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
 
   /* Prefix the format with the tag */
   taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
@@ -1793,7 +1790,7 @@ static char *imap_atom(const char *str, bool escape_only)
     return NULL;
 
   /* Look for "atom-specials", counting the backslash and quote characters as
-     these will need escapping */
+     these will need escaping */
   p1 = str;
   while(*p1) {
     if(*p1 == '\\')

+ 6 - 6
Utilities/cmcurl/lib/inet_ntop.c

@@ -55,11 +55,11 @@ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
   DEBUGASSERT(size >= 16);
 
   tmp[0] = '\0';
-  (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
-                 ((int)((unsigned char)src[0])) & 0xff,
-                 ((int)((unsigned char)src[1])) & 0xff,
-                 ((int)((unsigned char)src[2])) & 0xff,
-                 ((int)((unsigned char)src[3])) & 0xff);
+  (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+                  ((int)((unsigned char)src[0])) & 0xff,
+                  ((int)((unsigned char)src[1])) & 0xff,
+                  ((int)((unsigned char)src[2])) & 0xff,
+                  ((int)((unsigned char)src[3])) & 0xff);
 
   len = strlen(tmp);
   if(len == 0 || len >= size) {
@@ -148,7 +148,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
       tp += strlen(tp);
       break;
     }
-    tp += snprintf(tp, 5, "%lx", words[i]);
+    tp += msnprintf(tp, 5, "%lx", words[i]);
   }
 
   /* Was it a trailing run of 0x00's?

+ 2 - 1
Utilities/cmcurl/lib/inet_pton.c

@@ -153,7 +153,7 @@ inet_pton6(const char *src, unsigned char *dst)
   static const char xdigits_l[] = "0123456789abcdef",
     xdigits_u[] = "0123456789ABCDEF";
   unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
-  const char *xdigits, *curtok;
+  const char *curtok;
   int ch, saw_xdigit;
   size_t val;
 
@@ -168,6 +168,7 @@ inet_pton6(const char *src, unsigned char *dst)
   saw_xdigit = 0;
   val = 0;
   while((ch = *src++) != '\0') {
+    const char *xdigits;
     const char *pch;
 
     pch = strchr((xdigits = xdigits_l), ch);

+ 13 - 9
Utilities/cmcurl/lib/ldap.c

@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -744,7 +744,7 @@ quit:
 #endif
 
   /* no data to transfer */
-  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, -1, -1, FALSE, -1);
   connclose(conn, "LDAP connection always disable re-use");
 
   return result;
@@ -839,6 +839,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 {
   int rc = LDAP_SUCCESS;
   char *path;
+  char *query;
   char *p;
   char *q;
   size_t i;
@@ -846,7 +847,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!conn->data ||
      !conn->data->state.up.path ||
      conn->data->state.up.path[0] != '/' ||
-     !strcasecompare("LDAP", conn->data->state.up.scheme))
+     !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
     return LDAP_INVALID_SYNTAX;
 
   ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -858,11 +859,14 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!path)
     return LDAP_NO_MEMORY;
 
-  /* Parse the DN (Distinguished Name) */
-  q = strchr(p, '?');
-  if(q)
-    *q++ = '\0';
+  /* Duplicate the query */
+  q = query = strdup(conn->data->state.up.query);
+  if(!query) {
+    free(path);
+    return LDAP_NO_MEMORY;
+  }
 
+  /* Parse the DN (Distinguished Name) */
   if(*p) {
     char *dn = p;
     char *unescaped;
@@ -1039,6 +1043,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 quit:
   free(path);
+  free(query);
 
   return rc;
 }
@@ -1064,8 +1069,6 @@ static int _ldap_url_parse(const struct connectdata *conn,
 
 static void _ldap_free_urldesc(LDAPURLDesc *ludp)
 {
-  size_t i;
-
   if(!ludp)
     return;
 
@@ -1073,6 +1076,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
   free(ludp->lud_filter);
 
   if(ludp->lud_attrs) {
+    size_t i;
     for(i = 0; i < ludp->lud_attrs_dups; i++)
       free(ludp->lud_attrs[i]);
     free(ludp->lud_attrs);

+ 6 - 6
Utilities/cmcurl/lib/libcurl.rc

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,22 +22,22 @@
 #include <winver.h>
 #include "../include/curl/curlver.h"
 
-LANGUAGE  0x09,0x01
+LANGUAGE  0, 0
 
 #define RC_VERSION  LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
 
 VS_VERSION_INFO VERSIONINFO
   FILEVERSION     RC_VERSION
   PRODUCTVERSION  RC_VERSION
-  FILEFLAGSMASK   0x3fL
+  FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK
 #if defined(DEBUGBUILD) || defined(_DEBUG)
-  FILEFLAGS 1
+  FILEFLAGS VS_FF_DEBUG
 #else
-  FILEFLAGS 0
+  FILEFLAGS 0L
 #endif
   FILEOS      VOS__WINDOWS32
   FILETYPE    VFT_DLL
-  FILESUBTYPE 0x0L
+  FILESUBTYPE 0L
 
 BEGIN
   BLOCK "StringFileInfo"

+ 60 - 54
Utilities/cmcurl/lib/md4.c

@@ -1,4 +1,5 @@
 /*
+ * !checksrc! disable COPYRIGHT
  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
  * MD4 Message-Digest Algorithm (RFC 1320).
  *
@@ -37,9 +38,11 @@
 
 #include "curl_setup.h"
 
-/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
- * MD4 hash algorithm, so we have a local implementation of it */
+/* The NSS, OS/400, and when not included, OpenSSL and mbed TLS crypto
+ * libraries do not provide the MD4 hash algorithm, so we use this
+ * implementation of it */
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 #include "curl_md4.h"
@@ -112,7 +115,6 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 {
   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;
 
@@ -122,6 +124,8 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
 
   do {
+    MD4_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_b = b;
     saved_c = c;
@@ -129,59 +133,59 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 
 /* 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)
+    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)
+    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;
+    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;
@@ -211,7 +215,7 @@ static void MD4_Init(MD4_CTX *ctx)
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
   MD4_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -222,7 +226,7 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
 
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
@@ -303,5 +307,7 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Final(output, &ctx);
 }
+
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */

+ 84 - 90
Utilities/cmcurl/lib/md5.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,19 +39,19 @@
 
 typedef struct md5_ctx MD5_CTX;
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
   md5_init(ctx);
 }
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        unsigned int inputLen)
 {
   md5_update(ctx, inputLen, input);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
   md5_digest(ctx, 16, digest);
 }
@@ -65,25 +65,25 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
 
 typedef gcry_md_hd_t MD5_CTX;
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
   gcry_md_open(ctx, GCRY_MD_MD5, 0);
 }
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        unsigned int inputLen)
 {
   gcry_md_write(*ctx, input, inputLen);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
   memcpy(digest, gcry_md_read(*ctx, 0), 16);
   gcry_md_close(*ctx);
 }
 
-#elif defined(USE_OPENSSL)
+#elif defined(USE_OPENSSL) && !defined(USE_AMISSL)
 /* When OpenSSL is available we use the MD5-function from OpenSSL */
 #include <openssl/md5.h>
 #include "curl_memory.h"
@@ -124,7 +124,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
   CC_MD5_Final(digest, ctx);
 }
 
-#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
+#elif defined(WIN32) && !defined(CURL_WINDOWS_APP)
 
 #include <wincrypt.h>
 #include "curl_memory.h"
@@ -163,13 +163,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
     CryptReleaseContext(ctx->hCryptProv, 0);
 }
 
-#elif defined(USE_AXTLS)
-#include <axTLS/config.h>
-#include <axTLS/os_int.h>
-#include <axTLS/crypto.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
 #else
 /* When no other crypto library is available we use this code segment */
 /*
@@ -282,7 +275,6 @@ 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;
 
@@ -292,6 +284,8 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
 
   do {
+    MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_b = b;
     saved_c = c;
@@ -299,77 +293,77 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 
 /* 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)
+    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)
+    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)
+    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;
+    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;
@@ -399,7 +393,7 @@ static void MD5_Init(MD5_CTX *ctx)
 static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
 {
   MD5_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -410,7 +404,7 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
 
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
@@ -552,23 +546,23 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
   return ctxt;
 }
 
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len)
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len)
 {
   (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
 
-  return 0;
+  return CURLE_OK;
 }
 
-int Curl_MD5_final(MD5_context *context, unsigned char *result)
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result)
 {
   (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
 
   free(context->md5_hashctx);
   free(context);
 
-  return 0;
+  return CURLE_OK;
 }
 
 #endif /* CURL_DISABLE_CRYPTO_AUTH */

+ 69 - 85
Utilities/cmcurl/lib/memdebug.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -100,30 +100,29 @@ struct memdebug {
  * Don't use these with multithreaded test programs!
  */
 
-#define logfile curl_debuglogfile
-FILE *curl_debuglogfile = NULL;
+FILE *curl_dbg_logfile = NULL;
 static bool memlimit = FALSE; /* enable memory limit */
 static long memsize = 0;  /* set number of mallocs allowed */
 
 /* this sets the log file name */
-void curl_memdebug(const char *logname)
+void curl_dbg_memdebug(const char *logname)
 {
-  if(!logfile) {
+  if(!curl_dbg_logfile) {
     if(logname && *logname)
-      logfile = fopen(logname, FOPEN_WRITETEXT);
+      curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT);
     else
-      logfile = stderr;
+      curl_dbg_logfile = stderr;
 #ifdef MEMDEBUG_LOG_SYNC
     /* Flush the log file after every line so the log isn't lost in a crash */
-    if(logfile)
-      setbuf(logfile, (char *)NULL);
+    if(curl_dbg_logfile)
+      setbuf(curl_dbg_logfile, (char *)NULL);
 #endif
   }
 }
 
 /* This function sets the number of malloc() calls that should return
    successfully! */
-void curl_memlimit(long limit)
+void curl_dbg_memlimit(long limit)
 {
   if(!memlimit) {
     memlimit = TRUE;
@@ -140,12 +139,12 @@ static bool countcheck(const char *func, int line, const char *source)
     if(!memsize) {
       if(source) {
         /* log to file */
-        curl_memlog("LIMIT %s:%d %s reached memlimit\n",
-                    source, line, func);
+        curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
+                     source, line, func);
         /* log to stderr also */
         fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
                 source, line, func);
-        fflush(logfile); /* because it might crash now */
+        fflush(curl_dbg_logfile); /* because it might crash now */
       }
       errno = ENOMEM;
       return TRUE; /* RETURN ERROR! */
@@ -159,7 +158,7 @@ static bool countcheck(const char *func, int line, const char *source)
   return FALSE; /* allow this */
 }
 
-void *curl_domalloc(size_t wantedsize, int line, const char *source)
+void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
 {
   struct memdebug *mem;
   size_t size;
@@ -180,15 +179,15 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
   }
 
   if(source)
-    curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
-                source, line, wantedsize,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n",
+                 source, line, wantedsize,
+                 mem ? (void *)mem->mem : (void *)0);
 
   return (mem ? mem->mem : NULL);
 }
 
-void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
-                    int line, const char *source)
+void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
+                      int line, const char *source)
 {
   struct memdebug *mem;
   size_t size, user_size;
@@ -208,14 +207,14 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
     mem->size = user_size;
 
   if(source)
-    curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
-                source, line, wanted_elements, wanted_size,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n",
+                 source, line, wanted_elements, wanted_size,
+                 mem ? (void *)mem->mem : (void *)0);
 
   return (mem ? mem->mem : NULL);
 }
 
-char *curl_dostrdup(const char *str, int line, const char *source)
+char *curl_dbg_strdup(const char *str, int line, const char *source)
 {
   char *mem;
   size_t len;
@@ -227,19 +226,19 @@ char *curl_dostrdup(const char *str, int line, const char *source)
 
   len = strlen(str) + 1;
 
-  mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */
   if(mem)
     memcpy(mem, str, len);
 
   if(source)
-    curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
-                source, line, (const void *)str, len, (const void *)mem);
+    curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n",
+                 source, line, (const void *)str, len, (const void *)mem);
 
   return mem;
 }
 
 #if defined(WIN32) && defined(UNICODE)
-wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
+wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source)
 {
   wchar_t *mem;
   size_t wsiz, bsiz;
@@ -252,12 +251,12 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
   wsiz = wcslen(str) + 1;
   bsiz = wsiz * sizeof(wchar_t);
 
-  mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */
   if(mem)
     memcpy(mem, str, bsiz);
 
   if(source)
-    curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
+    curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
                 source, line, (void *)str, bsiz, (void *)mem);
 
   return mem;
@@ -266,8 +265,8 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
 
 /* We provide a realloc() that accepts a NULL as pointer, which then
    performs a malloc(). In order to work with ares. */
-void *curl_dorealloc(void *ptr, size_t wantedsize,
-                     int line, const char *source)
+void *curl_dbg_realloc(void *ptr, size_t wantedsize,
+                      int line, const char *source)
 {
   struct memdebug *mem = NULL;
 
@@ -293,7 +292,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
 
   mem = (Curl_crealloc)(mem, size);
   if(source)
-    curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
+    curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n",
                 source, line, (void *)ptr, wantedsize,
                 mem ? (void *)mem->mem : (void *)0);
 
@@ -305,11 +304,10 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
   return NULL;
 }
 
-void curl_dofree(void *ptr, int line, const char *source)
+void curl_dbg_free(void *ptr, int line, const char *source)
 {
-  struct memdebug *mem;
-
   if(ptr) {
+    struct memdebug *mem;
 
 #ifdef __INTEL_COMPILER
 #  pragma warning(push)
@@ -331,11 +329,11 @@ void curl_dofree(void *ptr, int line, const char *source)
   }
 
   if(source)
-    curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
+    curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
 }
 
-curl_socket_t curl_socket(int domain, int type, int protocol,
-                          int line, const char *source)
+curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                             int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socket() = %d\n" :
@@ -351,44 +349,44 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
   sockfd = socket(domain, type, protocol);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
   return sockfd;
 }
 
-SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                           SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                           SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
-                           const char *source)
+SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                            SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                            SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
   SEND_TYPE_RETV rc;
   if(countcheck("send", line, source))
     return -1;
   rc = send(sockfd, buf, len, flags);
   if(source)
-    curl_memlog("SEND %s:%d send(%lu) = %ld\n",
+    curl_dbg_log("SEND %s:%d send(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
   return rc;
 }
 
-RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
-                           RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
-                           const char *source)
+RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
+                            RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
   RECV_TYPE_RETV rc;
   if(countcheck("recv", line, source))
     return -1;
   rc = recv(sockfd, buf, len, flags);
   if(source)
-    curl_memlog("RECV %s:%d recv(%lu) = %ld\n",
+    curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
   return rc;
 }
 
 #ifdef HAVE_SOCKETPAIR
-int curl_socketpair(int domain, int type, int protocol,
-                    curl_socket_t socket_vector[2],
-                    int line, const char *source)
+int curl_dbg_socketpair(int domain, int type, int protocol,
+                       curl_socket_t socket_vector[2],
+                       int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socketpair() = %d %d\n" :
@@ -399,14 +397,14 @@ int curl_socketpair(int domain, int type, int protocol,
   int res = socketpair(domain, type, protocol, socket_vector);
 
   if(source && (0 == res))
-    curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+    curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]);
 
   return res;
 }
 #endif
 
-curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
-                          int line, const char *source)
+curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
+                             int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d accept() = %d\n" :
@@ -420,13 +418,13 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
   curl_socket_t sockfd = accept(s, addr, addrlen);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
   return sockfd;
 }
 
 /* separate function to allow libcurl to mark a "faked" close */
-void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
+void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d sclose(%d)\n":
@@ -435,54 +433,40 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
     "FD %s:%d sclose(%zd)\n";
 
   if(source)
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 }
 
 /* this is our own defined way to close sockets on *ALL* platforms */
-int curl_sclose(curl_socket_t sockfd, int line, const char *source)
+int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source)
 {
   int res = sclose(sockfd);
-  curl_mark_sclose(sockfd, line, source);
+  curl_dbg_mark_sclose(sockfd, line, source);
   return res;
 }
 
-FILE *curl_fopen(const char *file, const char *mode,
-                 int line, const char *source)
+FILE *curl_dbg_fopen(const char *file, const char *mode,
+                    int line, const char *source)
 {
   FILE *res = fopen(file, mode);
 
   if(source)
-    curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
+    curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
                 source, line, file, mode, (void *)res);
 
   return res;
 }
 
-#ifdef HAVE_FDOPEN
-FILE *curl_fdopen(int filedes, const char *mode,
-                  int line, const char *source)
-{
-  FILE *res = fdopen(filedes, mode);
-
-  if(source)
-    curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
-                source, line, filedes, mode, (void *)res);
-
-  return res;
-}
-#endif
-
-int curl_fclose(FILE *file, int line, const char *source)
+int curl_dbg_fclose(FILE *file, int line, const char *source)
 {
   int res;
 
   DEBUGASSERT(file != NULL);
 
-  res = fclose(file);
-
   if(source)
-    curl_memlog("FILE %s:%d fclose(%p)\n",
-                source, line, (void *)file);
+    curl_dbg_log("FILE %s:%d fclose(%p)\n",
+                 source, line, (void *)file);
+
+  res = fclose(file);
 
   return res;
 }
@@ -490,13 +474,13 @@ int curl_fclose(FILE *file, int line, const char *source)
 #define LOGLINE_BUFSIZE  1024
 
 /* this does the writing to the memory tracking log file */
-void curl_memlog(const char *format, ...)
+void curl_dbg_log(const char *format, ...)
 {
   char *buf;
   int nchars;
   va_list ap;
 
-  if(!logfile)
+  if(!curl_dbg_logfile)
     return;
 
   buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
@@ -504,14 +488,14 @@ void curl_memlog(const char *format, ...)
     return;
 
   va_start(ap, format);
-  nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+  nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
   va_end(ap);
 
   if(nchars > LOGLINE_BUFSIZE - 1)
     nchars = LOGLINE_BUFSIZE - 1;
 
   if(nchars > 0)
-    fwrite(buf, 1, (size_t)nchars, logfile);
+    fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile);
 
   (Curl_cfree)(buf);
 }

+ 59 - 64
Utilities/cmcurl/lib/memdebug.h

@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,97 +30,92 @@
 
 #define CURL_MT_LOGFNAME_BUFSIZE 512
 
-#define logfile curl_debuglogfile
-
-extern FILE *logfile;
+extern FILE *curl_dbg_logfile;
 
 /* memory functions */
-CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
-CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line,
-                                const char *source);
-CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
-                                 const char *source);
-CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
-CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
-#if defined(WIN32) && defined(UNICODE)
-CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
+CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source);
+CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line,
+                                  const char *source);
+CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line,
                                    const char *source);
+CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
+CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src);
+#if defined(WIN32) && defined(UNICODE)
+CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line,
+                                     const char *source);
 #endif
 
-CURL_EXTERN void curl_memdebug(const char *logname);
-CURL_EXTERN void curl_memlimit(long limit);
-CURL_EXTERN void curl_memlog(const char *format, ...);
+CURL_EXTERN void curl_dbg_memdebug(const char *logname);
+CURL_EXTERN void curl_dbg_memlimit(long limit);
+CURL_EXTERN void curl_dbg_log(const char *format, ...);
 
 /* file descriptor manipulators */
-CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
-                                      int line, const char *source);
-CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
-                                  int line, const char *source);
-CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
-                            int line, const char *source);
-CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
+CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                                          int line, const char *source);
+CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd,
                                       int line, const char *source);
-#ifdef HAVE_SOCKETPAIR
-CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
-                                curl_socket_t socket_vector[2],
+CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd,
                                 int line, const char *source);
+CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen,
+                                          int line, const char *source);
+#ifdef HAVE_SOCKETPAIR
+CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol,
+                                    curl_socket_t socket_vector[2],
+                                    int line, const char *source);
 #endif
 
 /* send/receive sockets */
-CURL_EXTERN SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                                       SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                                       SEND_TYPE_ARG3 len,
-                                       SEND_TYPE_ARG4 flags, int line,
-                                       const char *source);
-CURL_EXTERN RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd,
-                                       RECV_TYPE_ARG2 buf, RECV_TYPE_ARG3 len,
-                                       RECV_TYPE_ARG4 flags, int line,
-                                       const char *source);
+CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                                         SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                                         SEND_TYPE_ARG3 len,
+                                         SEND_TYPE_ARG4 flags, int line,
+                                         const char *source);
+CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd,
+                                         RECV_TYPE_ARG2 buf,
+                                         RECV_TYPE_ARG3 len,
+                                         RECV_TYPE_ARG4 flags, int line,
+                                         const char *source);
 
 /* FILE functions */
-CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
-                             const char *source);
-#ifdef HAVE_FDOPEN
-CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line,
-                              const char *source);
-#endif
-CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
+CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
+                                 const char *source);
+CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
 
 #ifndef MEMDEBUG_NODEFINES
 
 /* Set this symbol on the command-line, recompile all lib-sources */
 #undef strdup
-#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
-#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
-#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
-#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
-#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
-#define send(a,b,c,d) curl_dosend(a,b,c,d, __LINE__, __FILE__)
-#define recv(a,b,c,d) curl_dorecv(a,b,c,d, __LINE__, __FILE__)
+#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
+#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__)
+#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__)
+#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__)
+#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__)
+#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
+#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
 
 #ifdef WIN32
 #  ifdef UNICODE
 #    undef wcsdup
-#    define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _wcsdup
-#    define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #  else
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
 #  endif
 #endif
 
 #undef socket
 #define socket(domain,type,protocol)\
- curl_socket(domain, type, protocol, __LINE__, __FILE__)
+ curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__)
 #undef accept /* for those with accept as a macro */
 #define accept(sock,addr,len)\
- curl_accept(sock, addr, len, __LINE__, __FILE__)
+ curl_dbg_accept(sock, addr, len, __LINE__, __FILE__)
 #ifdef HAVE_SOCKETPAIR
 #define socketpair(domain,type,protocol,socket_vector)\
- curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
+ curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
 #endif
 
 #ifdef HAVE_GETADDRINFO
@@ -129,31 +124,31 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
    our macro as for other platforms. Instead, we redefine the new name they
    define getaddrinfo to become! */
 #define ogetaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #else
 #undef getaddrinfo
 #define getaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #endif
 #endif /* HAVE_GETADDRINFO */
 
 #ifdef HAVE_FREEADDRINFO
 #undef freeaddrinfo
 #define freeaddrinfo(data) \
-  curl_dofreeaddrinfo(data, __LINE__, __FILE__)
+  curl_dbg_freeaddrinfo(data, __LINE__, __FILE__)
 #endif /* HAVE_FREEADDRINFO */
 
 /* sclose is probably already defined, redefine it! */
 #undef sclose
-#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
+#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__)
 
-#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__)
+#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__)
 
 #undef fopen
-#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
+#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__)
 #undef fdopen
-#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__)
-#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
+#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__)
+#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__)
 
 #endif /* MEMDEBUG_NODEFINES */
 

+ 9 - 85
Utilities/cmcurl/lib/mime.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,8 +29,8 @@
 #include "urldata.h"
 #include "sendf.h"
 
-#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
-    !defined(CURL_DISABLE_IMAP)
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
@@ -821,8 +821,10 @@ static size_t readback_part(curl_mimepart *part,
     struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
     switch(part->state.state) {
     case MIMESTATE_BEGIN:
-      mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
-                                 MIMESTATE_CURLHEADERS, part->curlheaders);
+      mimesetstate(&part->state,
+                   (part->flags & MIME_BODY_ONLY)?
+                     MIMESTATE_BODY: MIMESTATE_CURLHEADERS,
+                   part->curlheaders);
       break;
     case MIMESTATE_USERHEADERS:
       if(!hdr) {
@@ -1122,8 +1124,6 @@ void curl_mime_free(curl_mime *mime)
       Curl_mime_cleanpart(part);
       free(part);
     }
-
-    free(mime->boundary);
     free(mime);
   }
 }
@@ -1220,18 +1220,10 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
     mime->firstpart = NULL;
     mime->lastpart = NULL;
 
-    /* Get a part boundary. */
-    mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1);
-    if(!mime->boundary) {
-      free(mime);
-      return NULL;
-    }
-
     memset(mime->boundary, '-', 24);
-    if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+    if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24],
                      MIME_RAND_BOUNDARY_CHARS + 1)) {
       /* failed to get random separator, bail out */
-      free(mime->boundary);
       free(mime);
       return NULL;
     }
@@ -1909,72 +1901,4 @@ CURLcode curl_mime_headers(curl_mimepart *part,
   return CURLE_NOT_BUILT_IN;
 }
 
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
-{
-  (void) part;
-  (void) easy;
-}
-
-void Curl_mime_cleanpart(curl_mimepart *part)
-{
-  (void) part;
-}
-
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
-{
-  (void) dst;
-  (void) src;
-  return CURLE_OK;    /* Nothing to duplicate: always succeed. */
-}
-
-CURLcode Curl_mime_set_subparts(curl_mimepart *part,
-                                curl_mime *subparts, int take_ownership)
-{
-  (void) part;
-  (void) subparts;
-  (void) take_ownership;
-  return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
-                                   const char *contenttype,
-                                   const char *disposition,
-                                   enum mimestrategy strategy)
-{
-  (void) part;
-  (void) contenttype;
-  (void) disposition;
-  (void) strategy;
-  return CURLE_NOT_BUILT_IN;
-}
-
-curl_off_t Curl_mime_size(curl_mimepart *part)
-{
-  (void) part;
-  return (curl_off_t) -1;
-}
-
-size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
-{
-  (void) buffer;
-  (void) size;
-  (void) nitems;
-  (void) instream;
-  return 0;
-}
-
-CURLcode Curl_mime_rewind(curl_mimepart *part)
-{
-  (void) part;
-  return CURLE_NOT_BUILT_IN;
-}
-
-/* VARARGS2 */
-CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
-{
-  (void) slp;
-  (void) fmt;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#endif /* if disabled */

+ 24 - 3
Utilities/cmcurl/lib/mime.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+
 #define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
 #define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
 #define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
@@ -69,7 +71,7 @@ enum mimestrategy {
 typedef struct {
   const char *   name;          /* Encoding name. */
   size_t         (*encodefunc)(char *buffer, size_t size, bool ateof,
-                             curl_mimepart *part);  /* Encoded read. */
+                               curl_mimepart *part);  /* Encoded read. */
   curl_off_t     (*sizefunc)(curl_mimepart *part);  /* Encoded size. */
 }  mime_encoder;
 
@@ -88,13 +90,16 @@ typedef struct {
   size_t offset;              /* State-dependent offset. */
 }  mime_state;
 
+/* minimum buffer size for the boundary string */
+#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
+
 /* A mime multipart. */
 struct curl_mime_s {
   struct Curl_easy *easy;          /* The associated easy handle. */
   curl_mimepart *parent;           /* Parent part. */
   curl_mimepart *firstpart;        /* First part. */
   curl_mimepart *lastpart;         /* Last part. */
-  char *boundary;                  /* The part boundary. */
+  char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */
   mime_state state;                /* Current readback state. */
 };
 
@@ -122,6 +127,8 @@ struct curl_mimepart_s {
   mime_encoder_state encstate;     /* Data encoder state. */
 };
 
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 /* Prototypes. */
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
@@ -140,4 +147,18 @@ CURLcode Curl_mime_rewind(curl_mimepart *part);
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
 const char *Curl_mime_contenttype(const char *filename);
 
+#else
+/* if disabled */
+#define Curl_mime_initpart(x,y)
+#define Curl_mime_cleanpart(x)
+#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
+#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
+#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN
+#define Curl_mime_size(x) (curl_off_t) -1
+#define Curl_mime_read NULL
+#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_mime_add_header(x,y,...) CURLE_NOT_BUILT_IN
+#endif
+
+
 #endif /* HEADER_CURL_MIME_H */

+ 1 - 1
Utilities/cmcurl/lib/mprintf.c

@@ -835,7 +835,7 @@ static int dprintf_formatf(
           while(width-- > 0)
             OUTCHAR(' ');
 
-        while((len-- > 0) && *str)
+        for(; len && *str; len--)
           OUTCHAR(*str++);
         if(p->flags&FLAGS_LEFT)
           while(width-- > 0)

File diff suppressed because it is too large
+ 197 - 296
Utilities/cmcurl/lib/multi.c


+ 14 - 34
Utilities/cmcurl/lib/multihandle.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -46,18 +46,16 @@ typedef enum {
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_PROTOCONNECT, /* 7 - 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_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_PERFORM,      /* 12 - transfer data */
+  CURLM_STATE_TOOFAST,      /* 13 - wait because limit-rate exceeded */
+  CURLM_STATE_DONE,         /* 14 - post data transfer operation */
+  CURLM_STATE_COMPLETED,    /* 15 - operation complete */
+  CURLM_STATE_MSGSENT,      /* 16 - the operation complete message is sent */
+  CURLM_STATE_LAST          /* 17 - not a true state, never use this */
 } CURLMstate;
 
 /* we support N sockets per easy handle. Set the corresponding bit to what
@@ -66,7 +64,7 @@ typedef enum {
 #define GETSOCK_READABLE (0x00ff)
 #define GETSOCK_WRITABLE (0xff00)
 
-#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX)
+#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
 
 /* This is the struct known as CURLM on the outside */
 struct Curl_multi {
@@ -112,8 +110,8 @@ struct Curl_multi {
      same actual socket) */
   struct curl_hash sockhash;
 
-  /* pipelining wanted bits (CURLPIPE*) */
-  long pipelining;
+  /* multiplexing wanted */
+  bool multiplexing;
 
   bool recheckstate; /* see Curl_multi_connchanged */
 
@@ -129,24 +127,6 @@ struct Curl_multi {
   long max_total_connections; /* if >0, a fixed limit of the maximum number
                                  of connections in total */
 
-  long max_pipeline_length; /* if >0, maximum number of requests in a
-                               pipeline */
-
-  long content_length_penalty_size; /* a connection with a
-                                       content-length bigger than
-                                       this is not considered
-                                       for pipelining */
-
-  long chunk_length_penalty_size; /* a connection with a chunk length
-                                     bigger than this is not
-                                     considered for pipelining */
-
-  struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted
-                                           from pipelining */
-
-  struct curl_llist pipelining_server_bl; /* List of server types that are
-                                             blacklisted from pipelining */
-
   /* timer callback and user data pointer for the *socket() API */
   curl_multi_timer_callback timer_cb;
   void *timer_userp;

+ 16 - 17
Utilities/cmcurl/lib/multiif.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,10 @@ void Curl_updatesocket(struct Curl_easy *data);
 void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
 void Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
-bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
-void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_detach_connnection(struct Curl_easy *data);
+void Curl_attach_connnection(struct Curl_easy *data,
+                             struct connectdata *conn);
+bool Curl_multiplex_wanted(const struct Curl_multi *multi);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
 bool Curl_is_in_callback(struct Curl_easy *easy);
 
@@ -62,22 +64,11 @@ void Curl_multi_dump(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_CONTENT_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */
-struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */
-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);
+void Curl_multiuse_state(struct connectdata *conn,
+                         int bundlestate); /* use BUNDLE_* defines */
 
 /*
  * Curl_multi_closed()
@@ -89,7 +80,7 @@ void Curl_multi_connchanged(struct Curl_multi *multi);
  * socket again and it gets the same file descriptor number.
  */
 
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s);
 
 /*
  * Add a handle and move it into PERFORM state at once. For pushed streams.
@@ -97,4 +88,12 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
                                  struct Curl_easy *data,
                                  struct connectdata *conn);
+
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
+                          struct curl_waitfd extra_fds[],
+                          unsigned int extra_nfds,
+                          int timeout_ms,
+                          int *ret,
+                          bool *gotsocket); /* if any socket was checked */
+
 #endif /* HEADER_CURL_MULTIIF_H */

+ 13 - 3
Utilities/cmcurl/lib/netrc.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -53,6 +54,8 @@ enum host_lookup_state {
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *netrcfile)
 {
   FILE *file;
@@ -164,7 +167,7 @@ int Curl_parsenetrc(const char *host,
             if(specific_login) {
               state_our_login = strcasecompare(login, tok);
             }
-            else {
+            else if(!login || strcmp(login, tok)) {
               if(login_alloc) {
                 free(login);
                 login_alloc = FALSE;
@@ -179,7 +182,8 @@ int Curl_parsenetrc(const char *host,
             state_login = 0;
           }
           else if(state_password) {
-            if(state_our_login || !specific_login) {
+            if((state_our_login || !specific_login)
+                && (!password || strcmp(password, tok))) {
               if(password_alloc) {
                 free(password);
                 password_alloc = FALSE;
@@ -211,15 +215,19 @@ int Curl_parsenetrc(const char *host,
 
     out:
     if(!retcode) {
+      *login_changed = FALSE;
+      *password_changed = FALSE;
       if(login_alloc) {
         if(*loginp)
           free(*loginp);
         *loginp = login;
+        *login_changed = TRUE;
       }
       if(password_alloc) {
         if(*passwordp)
           free(*passwordp);
         *passwordp = password;
+        *password_changed = TRUE;
       }
     }
     else {
@@ -233,3 +241,5 @@ int Curl_parsenetrc(const char *host,
 
   return retcode;
 }
+
+#endif

+ 10 - 1
Utilities/cmcurl/lib/netrc.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,15 +22,24 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
+
 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *filename);
   /* Assume: (*passwordp)[0]=0, host[0] != 0.
    * If (*loginp)[0] = 0, search for login and password within a machine
    * section in the netrc.
    * If (*loginp)[0] != 0, search for password within machine and login.
    */
+#else
+/* disabled */
+#define Curl_parsenetrc(a,b,c,d,e,f) 1
+#endif
 
 #endif /* HEADER_CURL_NETRC_H */

+ 2 - 2
Utilities/cmcurl/lib/non-ascii.c

@@ -78,7 +78,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
 
 /*
  * Curl_convert_to_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
 CURLcode Curl_convert_to_network(struct Curl_easy *data,
                                  char *buffer, size_t length)
@@ -144,7 +144,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
 
 /*
  * Curl_convert_from_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
 CURLcode Curl_convert_from_network(struct Curl_easy *data,
                                    char *buffer, size_t length)

+ 4 - 9
Utilities/cmcurl/lib/openldap.c

@@ -6,7 +6,7 @@
  *                 \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010, Howard Chu, <[email protected]>
- * Copyright (C) 2011 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -196,9 +196,6 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
   li->proto = proto;
   conn->proto.generic = li;
   connkeep(conn, "OpenLDAP default");
-  /* TODO:
-   * - provide option to choose SASL Binds instead of Simple
-   */
   return CURLE_OK;
 }
 
@@ -220,8 +217,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
   ptr = hosturl + 4;
   if(conn->handler->flags & PROTOPT_SSL)
     *ptr++ = 's';
-  snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
-           conn->host.name, conn->remote_port);
+  msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+            conn->host.name, conn->remote_port);
 
 #ifdef CURL_OPENLDAP_DEBUG
   static int do_trace = 0;
@@ -414,7 +411,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
     return CURLE_OUT_OF_MEMORY;
   lr->msgid = msgid;
   data->req.protop = lr;
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   return CURLE_OK;
 }
@@ -510,8 +507,6 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
     lr->nument++;
     rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
     if(rc < 0) {
-      /* TODO: verify that this is really how this return code should be
-         handled */
       *err = CURLE_RECV_ERROR;
       return -1;
     }

+ 26 - 15
Utilities/cmcurl/lib/parsedate.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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,20 +82,6 @@
 #include "warnless.h"
 #include "parsedate.h"
 
-const char * const Curl_wkday[] =
-{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
-static const char * const weekday[] =
-{ "Monday", "Tuesday", "Wednesday", "Thursday",
-  "Friday", "Saturday", "Sunday" };
-const char * const Curl_month[]=
-{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-struct tzinfo {
-  char name[5];
-  int offset; /* +/- in minutes */
-};
-
 /*
  * parsedate()
  *
@@ -114,6 +100,22 @@ static int parsedate(const char *date, time_t *output);
 #define PARSEDATE_LATER  1
 #define PARSEDATE_SOONER 2
 
+#ifndef CURL_DISABLE_PARSEDATE
+
+const char * const Curl_wkday[] =
+{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+static const char * const weekday[] =
+{ "Monday", "Tuesday", "Wednesday", "Thursday",
+  "Friday", "Saturday", "Sunday" };
+const char * const Curl_month[]=
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+struct tzinfo {
+  char name[5];
+  int offset; /* +/- in minutes */
+};
+
 /* Here's a bunch of frequently used time zone names. These were supported
    by the old getdate parser. */
 #define tDAYZONE -60       /* offset for daylight savings time */
@@ -555,6 +557,15 @@ static int parsedate(const char *date, time_t *output)
 
   return PARSEDATE_OK;
 }
+#else
+/* disabled */
+static int parsedate(const char *date, time_t *output)
+{
+  (void)date;
+  *output = 0;
+  return PARSEDATE_OK; /* a lie */
+}
+#endif
 
 time_t curl_getdate(const char *p, const time_t *now)
 {

Some files were not shown because too many files changed in this diff