Browse Source

Merge topic 'update-curl' into release-4.0

80ec307900 curl: Set build options the way we need for CMake
ba77812035 Merge branch 'upstream-curl' into update-curl
1865f86e28 curl 2025-02-13 (57495c64)
302d842f6e curl: Update script to get curl 8.12.1

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !10342
Brad King 8 months ago
parent
commit
6597a470c7
80 changed files with 634 additions and 792 deletions
  1. 1 0
      Source/Modules/CMakeBuildUtilities.cmake
  2. 1 1
      Utilities/Release/linux/aarch64/cache.txt
  3. 1 1
      Utilities/Release/linux/x86_64/cache.txt
  4. 1 1
      Utilities/Scripts/update-curl.bash
  5. 2 2
      Utilities/cmcurl/CMake/CurlTests.c
  6. 1 0
      Utilities/cmcurl/CMake/FindBrotli.cmake
  7. 1 0
      Utilities/cmcurl/CMake/FindCares.cmake
  8. 1 0
      Utilities/cmcurl/CMake/FindLibgsasl.cmake
  9. 1 0
      Utilities/cmcurl/CMake/FindLibidn2.cmake
  10. 1 0
      Utilities/cmcurl/CMake/FindLibpsl.cmake
  11. 1 0
      Utilities/cmcurl/CMake/FindLibrtmp.cmake
  12. 1 0
      Utilities/cmcurl/CMake/FindLibssh.cmake
  13. 1 0
      Utilities/cmcurl/CMake/FindLibssh2.cmake
  14. 1 0
      Utilities/cmcurl/CMake/FindLibuv.cmake
  15. 1 0
      Utilities/cmcurl/CMake/FindMbedTLS.cmake
  16. 1 0
      Utilities/cmcurl/CMake/FindNettle.cmake
  17. 1 0
      Utilities/cmcurl/CMake/FindQuiche.cmake
  18. 1 0
      Utilities/cmcurl/CMake/FindRustls.cmake
  19. 1 0
      Utilities/cmcurl/CMake/FindWolfSSL.cmake
  20. 1 0
      Utilities/cmcurl/CMake/FindZstd.cmake
  21. 3 0
      Utilities/cmcurl/CMake/Macros.cmake
  22. 3 0
      Utilities/cmcurl/CMake/OtherTests.cmake
  23. 1 1
      Utilities/cmcurl/CMake/PickyWarnings.cmake
  24. 1 1
      Utilities/cmcurl/CMake/Utilities.cmake
  25. 3 3
      Utilities/cmcurl/CMake/win32-cache.cmake
  26. 151 132
      Utilities/cmcurl/CMakeLists.txt
  27. 3 3
      Utilities/cmcurl/include/curl/curlver.h
  28. 10 0
      Utilities/cmcurl/lib/CMakeLists.txt
  29. 3 0
      Utilities/cmcurl/lib/asyn-ares.c
  30. 22 25
      Utilities/cmcurl/lib/asyn-thread.c
  31. 3 4
      Utilities/cmcurl/lib/asyn.h
  32. 0 1
      Utilities/cmcurl/lib/cf-h1-proxy.c
  33. 1 1
      Utilities/cmcurl/lib/cf-h2-proxy.c
  34. 5 11
      Utilities/cmcurl/lib/cf-https-connect.c
  35. 3 4
      Utilities/cmcurl/lib/cf-socket.c
  36. 1 5
      Utilities/cmcurl/lib/cfilters.c
  37. 5 6
      Utilities/cmcurl/lib/conncache.c
  38. 14 18
      Utilities/cmcurl/lib/connect.c
  39. 7 12
      Utilities/cmcurl/lib/content_encoding.c
  40. 1 1
      Utilities/cmcurl/lib/cookie.c
  41. 3 0
      Utilities/cmcurl/lib/curl_config.h.cmake
  42. 10 2
      Utilities/cmcurl/lib/curl_setup.h
  43. 4 8
      Utilities/cmcurl/lib/curl_trc.c
  44. 2 10
      Utilities/cmcurl/lib/ftp.c
  45. 4 6
      Utilities/cmcurl/lib/http.c
  46. 0 2
      Utilities/cmcurl/lib/http1.c
  47. 26 32
      Utilities/cmcurl/lib/imap.c
  48. 6 0
      Utilities/cmcurl/lib/inet_ntop.h
  49. 6 0
      Utilities/cmcurl/lib/inet_pton.h
  50. 1 53
      Utilities/cmcurl/lib/ldap.c
  51. 2 2
      Utilities/cmcurl/lib/mime.c
  52. 5 15
      Utilities/cmcurl/lib/multi.c
  53. 68 37
      Utilities/cmcurl/lib/netrc.c
  54. 12 3
      Utilities/cmcurl/lib/netrc.h
  55. 27 41
      Utilities/cmcurl/lib/pop3.c
  56. 4 11
      Utilities/cmcurl/lib/setopt.c
  57. 9 0
      Utilities/cmcurl/lib/smb.c
  58. 21 32
      Utilities/cmcurl/lib/smtp.c
  59. 4 12
      Utilities/cmcurl/lib/telnet.c
  60. 0 6
      Utilities/cmcurl/lib/transfer.c
  61. 12 16
      Utilities/cmcurl/lib/url.c
  62. 1 1
      Utilities/cmcurl/lib/urlapi.c
  63. 0 2
      Utilities/cmcurl/lib/urldata.h
  64. 9 9
      Utilities/cmcurl/lib/vquic/curl_msh3.c
  65. 4 4
      Utilities/cmcurl/lib/vquic/curl_ngtcp2.c
  66. 3 7
      Utilities/cmcurl/lib/vquic/curl_osslq.c
  67. 4 4
      Utilities/cmcurl/lib/vquic/curl_quiche.c
  68. 0 4
      Utilities/cmcurl/lib/vquic/vquic-tls.c
  69. 1 1
      Utilities/cmcurl/lib/vquic/vquic.c
  70. 2 35
      Utilities/cmcurl/lib/vssh/libssh.c
  71. 21 101
      Utilities/cmcurl/lib/vssh/libssh2.c
  72. 11 41
      Utilities/cmcurl/lib/vssh/ssh.h
  73. 1 5
      Utilities/cmcurl/lib/vtls/gtls.c
  74. 5 9
      Utilities/cmcurl/lib/vtls/mbedtls.c
  75. 16 22
      Utilities/cmcurl/lib/vtls/openssl.c
  76. 7 8
      Utilities/cmcurl/lib/vtls/schannel.c
  77. 5 3
      Utilities/cmcurl/lib/vtls/vtls.c
  78. 52 9
      Utilities/cmcurl/lib/vtls/vtls_scache.c
  79. 1 1
      Utilities/cmcurl/lib/vtls/wolfssl.c
  80. 4 5
      Utilities/cmlibarchive/CMakeLists.txt

+ 1 - 0
Source/Modules/CMakeBuildUtilities.cmake

@@ -159,6 +159,7 @@ else()
     set(CURL_CA_BUNDLE "" CACHE FILEPATH "Path to SSL CA Certificate Bundle")
     set(CURL_CA_PATH "" CACHE PATH "Path to SSL CA Certificate Directory")
     mark_as_advanced(CURL_CA_BUNDLE CURL_CA_PATH)
+    find_package(OpenSSL)
   endif()
   if(NOT CMAKE_USE_SYSTEM_NGHTTP2)
     # Tell curl's FindNGHTTP2 module to use our library.

+ 1 - 1
Utilities/Release/linux/aarch64/cache.txt

@@ -8,7 +8,7 @@ CMAKE_EXE_LINKER_FLAGS:STRING=-static-libstdc++ -static-libgcc
 
 # Enable ssl support in curl
 CMAKE_USE_OPENSSL:BOOL=ON
-OPENSSL_CRYPTO_LIBRARY:STRING=/opt/openssl/lib/libcrypto.a;-pthread
+OPENSSL_CRYPTO_LIBRARY:STRING=/opt/openssl/lib/libcrypto.a
 OPENSSL_INCLUDE_DIR:PATH=/opt/openssl/include
 OPENSSL_SSL_LIBRARY:FILEPATH=/opt/openssl/lib/libssl.a
 

+ 1 - 1
Utilities/Release/linux/x86_64/cache.txt

@@ -8,7 +8,7 @@ CMAKE_EXE_LINKER_FLAGS:STRING=-static-libstdc++ -static-libgcc
 
 # Enable ssl support in curl
 CMAKE_USE_OPENSSL:BOOL=ON
-OPENSSL_CRYPTO_LIBRARY:STRING=/opt/openssl/lib/libcrypto.a;-pthread
+OPENSSL_CRYPTO_LIBRARY:STRING=/opt/openssl/lib/libcrypto.a
 OPENSSL_INCLUDE_DIR:PATH=/opt/openssl/include
 OPENSSL_SSL_LIBRARY:FILEPATH=/opt/openssl/lib/libssl.a
 

+ 1 - 1
Utilities/Scripts/update-curl.bash

@@ -8,7 +8,7 @@ readonly name="curl"
 readonly ownership="Curl Upstream <[email protected]>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-8_12_0"
+readonly tag="curl-8_12_1"
 readonly shortlog=false
 readonly paths="
   CMake/*

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

@@ -70,7 +70,7 @@ int main(void)
 #include <netdb.h>
 int main(void)
 {
-  char *address = "example.com";
+  const char *address = "example.com";
   int length = 0;
   int type = 0;
   struct hostent h;
@@ -167,7 +167,7 @@ int main(void) { return 0; }
 int main(void)
 {
   /* ioctlsocket source code */
-  int socket;
+  int socket = -1;
   unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
   ;
   return 0;

+ 1 - 0
Utilities/cmcurl/CMake/FindBrotli.cmake

@@ -51,6 +51,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(BROTLI_FOUND AND BROTLIDEC_FOUND)
+  set(Brotli_FOUND TRUE)
   list(APPEND BROTLIDEC_LIBRARIES ${BROTLI_LIBRARIES})  # order is significant: brotlidec then brotlicommon
   list(REVERSE BROTLIDEC_LIBRARIES)
   list(REMOVE_DUPLICATES BROTLIDEC_LIBRARIES)

+ 1 - 0
Utilities/cmcurl/CMake/FindCares.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(CARES_FOUND)
+  set(Cares_FOUND TRUE)
   string(REPLACE ";" " " CARES_CFLAGS "${CARES_CFLAGS}")
   message(STATUS "Found Cares (via pkg-config): ${CARES_INCLUDE_DIRS} (found version \"${CARES_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibgsasl.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBGSASL_FOUND)
+  set(Libgsasl_FOUND TRUE)
   string(REPLACE ";" " " LIBGSASL_CFLAGS "${LIBGSASL_CFLAGS}")
   message(STATUS "Found Libgsasl (via pkg-config): ${LIBGSASL_INCLUDE_DIRS} (found version \"${LIBGSASL_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibidn2.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBIDN2_FOUND)
+  set(Libidn2_FOUND TRUE)
   string(REPLACE ";" " " LIBIDN2_CFLAGS "${LIBIDN2_CFLAGS}")
   message(STATUS "Found Libidn2 (via pkg-config): ${LIBIDN2_INCLUDE_DIRS} (found version \"${LIBIDN2_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibpsl.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBPSL_FOUND AND LIBPSL_INCLUDE_DIRS)
+  set(Libpsl_FOUND TRUE)
   string(REPLACE ";" " " LIBPSL_CFLAGS "${LIBPSL_CFLAGS}")
   message(STATUS "Found Libpsl (via pkg-config): ${LIBPSL_INCLUDE_DIRS} (found version \"${LIBPSL_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibrtmp.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBRTMP_FOUND AND LIBRTMP_INCLUDE_DIRS)
+  set(Librtmp_FOUND TRUE)
   string(REPLACE ";" " " LIBRTMP_CFLAGS "${LIBRTMP_CFLAGS}")
   message(STATUS "Found Librtmp (via pkg-config): ${LIBRTMP_INCLUDE_DIRS} (found version \"${LIBRTMP_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibssh.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBSSH_FOUND)
+  set(Libssh_FOUND TRUE)
   string(REPLACE ";" " " LIBSSH_CFLAGS "${LIBSSH_CFLAGS}")
   message(STATUS "Found Libssh (via pkg-config): ${LIBSSH_INCLUDE_DIRS} (found version \"${LIBSSH_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibssh2.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBSSH2_FOUND AND LIBSSH2_INCLUDE_DIRS)
+  set(Libssh2_FOUND TRUE)
   string(REPLACE ";" " " LIBSSH2_CFLAGS "${LIBSSH2_CFLAGS}")
   message(STATUS "Found Libssh2 (via pkg-config): ${LIBSSH2_INCLUDE_DIRS} (found version \"${LIBSSH2_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindLibuv.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(LIBUV_FOUND)
+  set(Libuv_FOUND TRUE)
   string(REPLACE ";" " " LIBUV_CFLAGS "${LIBUV_CFLAGS}")
   message(STATUS "Found Libuv (via pkg-config): ${LIBUV_INCLUDE_DIRS} (found version \"${LIBUV_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindMbedTLS.cmake

@@ -60,6 +60,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(MBEDTLS_FOUND AND MBEDX509_FOUND AND MBEDCRYPTO_FOUND)
+  set(MbedTLS_FOUND TRUE)
   list(APPEND MBEDTLS_LIBRARIES ${MBEDX509_LIBRARIES} ${MBEDCRYPTO_LIBRARIES})
   list(REVERSE MBEDTLS_LIBRARIES)
   list(REMOVE_DUPLICATES MBEDTLS_LIBRARIES)

+ 1 - 0
Utilities/cmcurl/CMake/FindNettle.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(NETTLE_FOUND)
+  set(Nettle_FOUND TRUE)
   string(REPLACE ";" " " NETTLE_CFLAGS "${NETTLE_CFLAGS}")
   message(STATUS "Found Nettle (via pkg-config): ${NETTLE_INCLUDE_DIRS} (found version \"${NETTLE_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindQuiche.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(QUICHE_FOUND)
+  set(Quiche_FOUND TRUE)
   string(REPLACE ";" " " QUICHE_CFLAGS "${QUICHE_CFLAGS}")
   message(STATUS "Found Quiche (via pkg-config): ${QUICHE_INCLUDE_DIRS} (found version \"${QUICHE_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindRustls.cmake

@@ -48,6 +48,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(RUSTLS_FOUND)
+  set(Rustls_FOUND TRUE)
   string(REPLACE ";" " " RUSTLS_CFLAGS "${RUSTLS_CFLAGS}")
   message(STATUS "Found Rustls (via pkg-config): ${RUSTLS_INCLUDE_DIRS} (found version \"${RUSTLS_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindWolfSSL.cmake

@@ -57,6 +57,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(WOLFSSL_FOUND)
+  set(WolfSSL_FOUND TRUE)
   string(REPLACE ";" " " WOLFSSL_CFLAGS "${WOLFSSL_CFLAGS}")
   message(STATUS "Found WolfSSL (via pkg-config): ${WOLFSSL_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")")
 else()

+ 1 - 0
Utilities/cmcurl/CMake/FindZstd.cmake

@@ -57,6 +57,7 @@ if(CURL_USE_PKGCONFIG AND
 endif()
 
 if(ZSTD_FOUND)
+  set(Zstd_FOUND TRUE)
   string(REPLACE ";" " " ZSTD_CFLAGS "${ZSTD_CFLAGS}")
   message(STATUS "Found Zstd (via pkg-config): ${ZSTD_INCLUDE_DIRS} (found version \"${ZSTD_VERSION}\")")
 else()

+ 3 - 0
Utilities/cmcurl/CMake/Macros.cmake

@@ -34,11 +34,14 @@ macro(check_include_file_concat_curl _file _variable)
   endif()
 endmacro()
 
+set(CURL_TEST_DEFINES "")  # Initialize global variable
+
 # For other curl specific tests, use this macro.
 # Return result in variable: CURL_TEST_OUTPUT
 macro(curl_internal_test _curl_test)
   if(NOT DEFINED "${_curl_test}")
     string(REPLACE ";" " " _cmake_required_definitions "${CMAKE_REQUIRED_DEFINITIONS}")
+    set(_curl_test_add_libraries "")
     if(CMAKE_REQUIRED_LIBRARIES)
       set(_curl_test_add_libraries
         "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")

+ 3 - 0
Utilities/cmcurl/CMake/OtherTests.cmake

@@ -65,6 +65,9 @@ endif()
 set(_source_epilogue "#undef inline")
 curl_add_header_include(HAVE_SYS_TIME_H "sys/time.h")
 check_c_source_compiles("${_source_epilogue}
+  #ifdef _MSC_VER
+  #include <winsock2.h>
+  #endif
   #include <time.h>
   int main(void)
   {

+ 1 - 1
Utilities/cmcurl/CMake/PickyWarnings.cmake

@@ -274,6 +274,6 @@ endif()
 
 if(_picky)
   string(REPLACE ";" " " _picky "${_picky}")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_picky}")
+  string(APPEND CMAKE_C_FLAGS " ${_picky}")
   message(STATUS "Picky compiler options: ${_picky}")
 endif()

+ 1 - 1
Utilities/cmcurl/CMake/Utilities.cmake

@@ -47,7 +47,7 @@ function(curl_dumpvars)
     if(_var_advanced)
       set(_var_advanced " [adv]")
     endif()
-    message("${_var}${_var_type}${_var_advanced} = ${${_var}}")
+    message("${_var}${_var_type}${_var_advanced} = '${${_var}}'")
   endforeach()
   message("::endgroup::")
 endfunction()

+ 3 - 3
Utilities/cmcurl/CMake/win32-cache.cmake

@@ -74,12 +74,12 @@ else()
     set(HAVE_UNISTD_H 0)
     set(HAVE_STDDEF_H 1)  # detected by CMake internally in check_type_size()
     set(HAVE_STDATOMIC_H 0)
-    if(NOT MSVC_VERSION LESS 1600)
+    if(MSVC_VERSION GREATER_EQUAL 1600)
       set(HAVE_STDINT_H 1)  # detected by CMake internally in check_type_size()
     else()
       set(HAVE_STDINT_H 0)  # detected by CMake internally in check_type_size()
     endif()
-    if(NOT MSVC_VERSION LESS 1800)
+    if(MSVC_VERSION GREATER_EQUAL 1800)
       set(HAVE_STDBOOL_H 1)
       set(HAVE_STRTOLL 1)
     else()
@@ -87,7 +87,7 @@ else()
       set(HAVE_STRTOLL 0)
     endif()
     set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
-    if(NOT MSVC_VERSION LESS 1900)
+    if(MSVC_VERSION GREATER_EQUAL 1900)
       set(HAVE_SNPRINTF 1)
     else()
       set(HAVE_SNPRINTF 0)

+ 151 - 132
Utilities/cmcurl/CMakeLists.txt

@@ -1,4 +1,5 @@
 # Set curl options as needed for CMake build
+set(_CURL_QUICK_DETECT ON)
 set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe")
 set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports")
 set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
@@ -235,13 +236,13 @@ if(NOT "$ENV{CURL_BUILDINFO}$ENV{CURL_CI}$ENV{CI}" STREQUAL "")
       else()
         set(_cache_var_type ":${_cache_var_type}")
       endif()
-      set(_cmake_args "${_cmake_args} -D${_cache_var}${_cache_var_type}=\"${_cache_var_value}\"")
+      string(APPEND _cmake_args " -D${_cache_var}${_cache_var_type}=\"${_cache_var_value}\"")
     endif()
   endforeach()
 endif()
 endif() # XXX(cmake): end
 
-set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
 include(Utilities)
 include(Macros)
 include(CMakeDependentOption)
@@ -289,49 +290,49 @@ endif()
 
 set(_target_flags "")
 if(APPLE)
-  set(_target_flags "${_target_flags} APPLE")
+  string(APPEND _target_flags " APPLE")
 endif()
 if(UNIX)
-  set(_target_flags "${_target_flags} UNIX")
+  string(APPEND _target_flags " UNIX")
 endif()
 if(BSD)
-  set(_target_flags "${_target_flags} BSD")
+  string(APPEND _target_flags " BSD")
 endif()
 if(ANDROID)
-  set(_target_flags "${_target_flags} ANDROID-${ANDROID_PLATFORM_LEVEL}")
+  string(APPEND _target_flags " ANDROID-${ANDROID_PLATFORM_LEVEL}")
 endif()
 if(WIN32)
-  set(_target_flags "${_target_flags} WIN32")
+  string(APPEND _target_flags " WIN32")
 endif()
 if(WINDOWS_STORE)
-  set(_target_flags "${_target_flags} UWP")
+  string(APPEND _target_flags " UWP")
 endif()
 if(CYGWIN)
-  set(_target_flags "${_target_flags} CYGWIN")
+  string(APPEND _target_flags " CYGWIN")
 endif()
 if(MSYS)
-  set(_target_flags "${_target_flags} MSYS")
+  string(APPEND _target_flags " MSYS")
 endif()
 if(DOS)
-  set(_target_flags "${_target_flags} DOS")
+  string(APPEND _target_flags " DOS")
 endif()
 if(AMIGA)
-  set(_target_flags "${_target_flags} AMIGA")
+  string(APPEND _target_flags " AMIGA")
 endif()
 if(CMAKE_COMPILER_IS_GNUCC)
-  set(_target_flags "${_target_flags} GCC")
+  string(APPEND _target_flags " GCC")
 endif()
 if(MINGW)
-  set(_target_flags "${_target_flags} MINGW")
+  string(APPEND _target_flags " MINGW")
 endif()
 if(MSVC)
-  set(_target_flags "${_target_flags} MSVC-${MSVC_VERSION}")
+  string(APPEND _target_flags " MSVC-${MSVC_VERSION}")
 endif()
 if(VCPKG_TOOLCHAIN)
-  set(_target_flags "${_target_flags} VCPKG")
+  string(APPEND _target_flags " VCPKG")
 endif()
 if(CMAKE_CROSSCOMPILING)
-  set(_target_flags "${_target_flags} CROSS")
+  string(APPEND _target_flags " CROSS")
 endif()
 if(0) # XXX(cmake): not needed for build within cmake
 message(STATUS "CMake platform flags:${_target_flags}")
@@ -379,8 +380,8 @@ if(WIN32)
   option(CURL_STATIC_CRT "Build libcurl with static CRT with MSVC (/MT)" OFF)
   if(CURL_STATIC_CRT AND MSVC)
     set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -MT")
-    set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -MTd")
+    string(APPEND CMAKE_C_FLAGS_RELEASE " -MT")
+    string(APPEND CMAKE_C_FLAGS_DEBUG " -MTd")
   endif()
 
   option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF)
@@ -395,7 +396,11 @@ if(WIN32)
   endif()
 
   if(0) # XXX(cmake): not needed for build within cmake
-  list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")  # Apply to all feature checks
+  # Apply to all feature checks
+  list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
+  if(MSVC)
+    list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_CRT_NONSTDC_NO_DEPRECATE")  # for strdup() detection
+  endif()
 
   set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
   if(CURL_TARGET_WINDOWS_VERSION)
@@ -446,7 +451,7 @@ include(PickyWarnings)
 endif() # XXX(cmake): end
 
 if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE")  # Required for sendmmsg()
+  string(APPEND CMAKE_C_FLAGS " -D_GNU_SOURCE")  # Required for sendmmsg()
 endif()
 
 option(ENABLE_DEBUG "Enable curl debug features (for developing curl itself)" OFF)
@@ -455,10 +460,6 @@ if(ENABLE_DEBUG)
 endif()
 option(ENABLE_CURLDEBUG "Enable TrackMemory debug feature" ${ENABLE_DEBUG})
 
-if(MSVC)
-  set(ENABLE_CURLDEBUG OFF)  # FIXME: TrackMemory + MSVC fails test 558 and 1330. Tested with static build, Debug mode.
-endif()
-
 if(ENABLE_DEBUG)
   set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "DEBUGBUILD")
 endif()
@@ -542,7 +543,7 @@ if(ENABLE_ARES)
   list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${CARES_PC_REQUIRES})
   link_directories(${CARES_LIBRARY_DIRS})
   if(CARES_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CARES_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${CARES_CFLAGS}")
   endif()
 endif()
 
@@ -679,35 +680,6 @@ if(WINDOWS_STORE)
   set(CURL_DISABLE_TELNET ON)  # telnet code needs fixing to compile for UWP.
 endif()
 
-option(ENABLE_IPV6 "Enable IPv6 support" ON)
-mark_as_advanced(ENABLE_IPV6)
-if(ENABLE_IPV6 AND NOT WIN32)
-  include(CheckStructHasMember)
-  check_struct_has_member("struct sockaddr_in6" "sin6_addr" "netinet/in.h" HAVE_SOCKADDR_IN6_SIN6_ADDR)
-  check_struct_has_member("struct sockaddr_in6" "sin6_scope_id" "netinet/in.h" HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
-  if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR)
-    if(NOT DOS AND NOT AMIGA)
-      message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support")
-    endif()
-    # Force the feature off as this name is used as guard macro...
-    set(ENABLE_IPV6 OFF CACHE BOOL "Enable IPv6 support" FORCE)
-  endif()
-
-  if(APPLE AND NOT ENABLE_ARES)
-    set(_use_core_foundation_and_core_services ON)
-
-    find_library(SYSTEMCONFIGURATION_FRAMEWORK NAMES "SystemConfiguration")
-    mark_as_advanced(SYSTEMCONFIGURATION_FRAMEWORK)
-    if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
-      message(FATAL_ERROR "SystemConfiguration framework not found")
-    endif()
-    list(APPEND CURL_LIBS "-framework SystemConfiguration")
-  endif()
-endif()
-if(ENABLE_IPV6)
-  set(USE_IPV6 ON)
-endif()
-
 if(0) # XXX(cmake): not needed for build within cmake
 find_package(Perl)
 
@@ -740,7 +712,7 @@ endif() # XXX(cmake): end
 
 # Disable warnings on Borland to avoid changing 3rd party code.
 if(BORLAND)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
+  string(APPEND CMAKE_C_FLAGS " -w-")
 endif()
 
 # If we are on AIX, do the _ALL_SOURCE magic
@@ -766,15 +738,18 @@ include(CheckSymbolExists)
 include(CheckTypeSize)
 include(CheckCSourceCompiles)
 
-if(WIN32)
-  # Preload settings on Windows
-  include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/win32-cache.cmake")
-elseif(APPLE)
-  # Fast-track predictable feature detections
-  set(HAVE_EVENTFD 0)
-  set(HAVE_GETPASS_R 0)
-  set(HAVE_SENDMMSG 0)
-elseif(AMIGA)
+option(_CURL_QUICK_DETECT "Fast-track known feature detection results (Windows, some Apple)" ON)
+if(_CURL_QUICK_DETECT)
+  if(WIN32)
+    include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/win32-cache.cmake")
+  elseif(APPLE)
+    set(HAVE_EVENTFD 0)
+    set(HAVE_GETPASS_R 0)
+    set(HAVE_SENDMMSG 0)
+  endif()
+endif()
+
+if(AMIGA)
   set(HAVE_GETADDRINFO 0)  # Breaks the build when detected and used.
 endif()
 if(DOS OR AMIGA)
@@ -817,12 +792,40 @@ elseif(AMIGA)
 elseif(NOT WIN32 AND NOT APPLE)
   check_library_exists("socket" "connect" "" HAVE_LIBSOCKET)
   if(HAVE_LIBSOCKET)
-    set(CURL_LIBS "socket;${CURL_LIBS}")
+    set(CURL_LIBS "socket" ${CURL_LIBS})
   endif()
 endif()
 
-if(WIN32)
-  list(APPEND CURL_LIBS "ws2_32" "bcrypt")
+option(ENABLE_IPV6 "Enable IPv6 support" ON)
+mark_as_advanced(ENABLE_IPV6)
+if(ENABLE_IPV6)
+  include(CheckStructHasMember)
+  if(WIN32)
+    check_struct_has_member("struct sockaddr_in6" "sin6_scope_id" "winsock2.h;ws2tcpip.h" HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+  else()
+    check_struct_has_member("struct sockaddr_in6" "sin6_addr" "netinet/in.h" HAVE_SOCKADDR_IN6_SIN6_ADDR)
+    check_struct_has_member("struct sockaddr_in6" "sin6_scope_id" "netinet/in.h" HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+    if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR)
+      if(NOT DOS AND NOT AMIGA)
+        message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support")
+      endif()
+      set(ENABLE_IPV6 OFF CACHE BOOL "Enable IPv6 support" FORCE)  # Force the feature off as we use this name as guard macro
+    endif()
+
+    if(APPLE AND NOT ENABLE_ARES)
+      set(_use_core_foundation_and_core_services ON)
+
+      find_library(SYSTEMCONFIGURATION_FRAMEWORK NAMES "SystemConfiguration")
+      mark_as_advanced(SYSTEMCONFIGURATION_FRAMEWORK)
+      if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
+        message(FATAL_ERROR "SystemConfiguration framework not found")
+      endif()
+      list(APPEND CURL_LIBS "-framework SystemConfiguration")
+    endif()
+  endif()
+endif()
+if(ENABLE_IPV6)
+  set(USE_IPV6 ON)
 endif()
 
 if(0) # XXX(cmake): not needed for build within cmake
@@ -944,8 +947,9 @@ if(CURL_USE_OPENSSL)
   set(_ssl_enabled ON)
   set(USE_OPENSSL ON)
 
-  list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
-  include_directories(${OPENSSL_INCLUDE_DIR})
+  # Depend on OpenSSL via imported targets. This allows our dependents to
+  # get our dependencies transitively.
+  list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto)
   list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "openssl")
 
   if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
@@ -954,7 +958,7 @@ if(CURL_USE_OPENSSL)
   set(_curl_ca_bundle_supported TRUE)
 
   cmake_push_check_state()
-  list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+  list(APPEND CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
   if(NOT DEFINED HAVE_BORINGSSL)
     check_symbol_exists("OPENSSL_IS_BORINGSSL" "openssl/base.h" HAVE_BORINGSSL)
   endif()
@@ -1010,7 +1014,7 @@ if(CURL_USE_MBEDTLS)
   include_directories(SYSTEM ${MBEDTLS_INCLUDE_DIRS})
   link_directories(${MBEDTLS_LIBRARY_DIRS})
   if(MBEDTLS_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MBEDTLS_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${MBEDTLS_CFLAGS}")
   endif()
 
   if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "mbedtls")
@@ -1046,7 +1050,7 @@ if(CURL_USE_WOLFSSL)
   include_directories(SYSTEM ${WOLFSSL_INCLUDE_DIRS})
   link_directories(${WOLFSSL_LIBRARY_DIRS})
   if(WOLFSSL_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WOLFSSL_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${WOLFSSL_CFLAGS}")
   endif()
 
   if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "wolfssl")
@@ -1061,6 +1065,10 @@ if(CURL_USE_GNUTLS)
     pkg_check_modules(GNUTLS "gnutls")
     if(GNUTLS_FOUND)
       set(GNUTLS_LIBRARIES ${GNUTLS_LINK_LIBRARIES})
+      string(REPLACE ";" " " GNUTLS_CFLAGS "${GNUTLS_CFLAGS}")
+      if(GNUTLS_CFLAGS)
+        string(APPEND CMAKE_C_FLAGS " ${GNUTLS_CFLAGS}")
+      endif()
     endif()
   endif()
   if(NOT GNUTLS_FOUND)
@@ -1070,12 +1078,12 @@ if(CURL_USE_GNUTLS)
   set(_ssl_enabled ON)
   set(USE_GNUTLS ON)
   list(APPEND CURL_LIBS ${GNUTLS_LIBRARIES} ${NETTLE_LIBRARIES})
-  list(APPEND CURL_LIBDIRS ${NETTLE_LIBRARY_DIRS})
+  list(APPEND CURL_LIBDIRS ${GNUTLS_LIBRARY_DIRS} ${NETTLE_LIBRARY_DIRS})
   list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "gnutls" ${NETTLE_PC_REQUIRES})
   include_directories(SYSTEM ${GNUTLS_INCLUDE_DIRS} ${NETTLE_INCLUDE_DIRS})
   link_directories(${NETTLE_LIBRARY_DIRS})
   if(NETTLE_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NETTLE_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${NETTLE_CFLAGS}")
   endif()
 
   if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "gnutls")
@@ -1102,7 +1110,7 @@ if(CURL_USE_RUSTLS)
   include_directories(SYSTEM ${RUSTLS_INCLUDE_DIRS})
   link_directories(${RUSTLS_LIBRARY_DIRS})
   if(RUSTLS_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RUSTLS_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${RUSTLS_CFLAGS}")
   endif()
 
   if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "rustls")
@@ -1142,7 +1150,7 @@ if(BROTLI_FOUND)
   include_directories(SYSTEM ${BROTLI_INCLUDE_DIRS})
   link_directories(${BROTLI_LIBRARY_DIRS})
   if(BROTLI_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${BROTLI_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${BROTLI_CFLAGS}")
   endif()
 endif()
 
@@ -1157,7 +1165,7 @@ if(ZSTD_FOUND)
     include_directories(SYSTEM ${ZSTD_INCLUDE_DIRS})
     link_directories(${ZSTD_LIBRARY_DIRS})
     if(ZSTD_CFLAGS)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ZSTD_CFLAGS}")
+      string(APPEND CMAKE_C_FLAGS " ${ZSTD_CFLAGS}")
     endif()
   else()
     message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.")
@@ -1168,10 +1176,14 @@ endif()
 macro(curl_openssl_check_symbol_exists _symbol _files _variable)
   cmake_push_check_state()
   if(USE_OPENSSL)
-    list(APPEND CMAKE_REQUIRED_INCLUDES   "${OPENSSL_INCLUDE_DIR}")
-    list(APPEND CMAKE_REQUIRED_LIBRARIES  "${OPENSSL_LIBRARIES}")
+    list(APPEND CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
+    list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DOPENSSL_SUPPRESS_DEPRECATED")  # for SSL_CTX_set_srp_username deprecated since 3.0.0
     if(HAVE_LIBZ)
-      list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
+      if(CMAKE_USE_SYSTEM_ZLIB)
+        list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB)
+      else()
+        list(APPEND CMAKE_REQUIRED_LIBRARIES cmzlib)
+      endif()
     endif()
     if(WIN32)
       list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
@@ -1183,8 +1195,7 @@ macro(curl_openssl_check_symbol_exists _symbol _files _variable)
     list(APPEND CMAKE_REQUIRED_LIBRARIES  "${WOLFSSL_LIBRARIES}")
     curl_required_libpaths("${WOLFSSL_LIBRARY_DIRS}")
     if(HAVE_LIBZ)
-      list(APPEND CMAKE_REQUIRED_INCLUDES  "${ZLIB_INCLUDE_DIRS}")  # Public wolfSSL headers require zlib headers
-      list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
+      list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB)  # Public wolfSSL headers also require zlib headers
     endif()
     if(WIN32)
       list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32")
@@ -1276,7 +1287,7 @@ if(USE_NGHTTP2)
     include_directories(SYSTEM ${NGHTTP2_INCLUDE_DIRS})
     link_directories(${NGHTTP2_LIBRARY_DIRS})
     if(NGHTTP2_CFLAGS)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NGHTTP2_CFLAGS}")
+      string(APPEND CMAKE_C_FLAGS " ${NGHTTP2_CFLAGS}")
     endif()
   else()
     set(USE_NGHTTP2 OFF)
@@ -1308,7 +1319,7 @@ if(USE_NGTCP2)
   include_directories(SYSTEM ${NGTCP2_INCLUDE_DIRS})
   link_directories(${NGTCP2_LIBRARY_DIRS})
   if(NGTCP2_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NGTCP2_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${NGTCP2_CFLAGS}")
   endif()
 
   find_package(NGHTTP3 REQUIRED)
@@ -1319,7 +1330,7 @@ if(USE_NGTCP2)
   include_directories(SYSTEM ${NGHTTP3_INCLUDE_DIRS})
   link_directories(${NGHTTP3_LIBRARY_DIRS})
   if(NGHTTP3_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NGHTTP3_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${NGHTTP3_CFLAGS}")
   endif()
 endif()
 
@@ -1339,7 +1350,7 @@ if(USE_QUICHE)
   include_directories(SYSTEM ${QUICHE_INCLUDE_DIRS})
   link_directories(${QUICHE_LIBRARY_DIRS})
   if(QUICHE_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${QUICHE_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${QUICHE_CFLAGS}")
   endif()
   if(NOT DEFINED HAVE_QUICHE_CONN_SET_QLOG_FD)
     cmake_push_check_state()
@@ -1368,7 +1379,7 @@ if(USE_MSH3)
   include_directories(SYSTEM ${MSH3_INCLUDE_DIRS})
   link_directories(${MSH3_LIBRARY_DIRS})
   if(MSH3_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MSH3_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${MSH3_CFLAGS}")
   endif()
 endif()
 
@@ -1409,20 +1420,20 @@ if(NOT CURL_DISABLE_LDAP)
     # Check for LDAP
     cmake_push_check_state()
     if(USE_OPENSSL)
-      list(APPEND CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
+      list(APPEND CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
     endif()
     find_package(LDAP)
     if(LDAP_FOUND)
       set(HAVE_LBER_H 1)
-      set(CURL_LIBS "${LDAP_LIBRARIES};${CURL_LIBS}")
+      set(CURL_LIBS ${LDAP_LIBRARIES} ${CURL_LIBS})
       list(APPEND CURL_LIBDIRS ${LDAP_LIBRARY_DIRS})
       if(LDAP_PC_REQUIRES)
-        set(LIBCURL_PC_REQUIRES_PRIVATE "${LDAP_PC_REQUIRES};${LIBCURL_PC_REQUIRES_PRIVATE}")
+        set(LIBCURL_PC_REQUIRES_PRIVATE ${LDAP_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
       endif()
       include_directories(SYSTEM ${LDAP_INCLUDE_DIRS})
       link_directories(${LDAP_LIBRARY_DIRS})
       if(LDAP_CFLAGS)
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LDAP_CFLAGS}")
+        string(APPEND CMAKE_C_FLAGS " ${LDAP_CFLAGS}")
       endif()
 
       # LDAP feature checks
@@ -1438,7 +1449,6 @@ if(NOT CURL_DISABLE_LDAP)
 
       if(HAVE_LDAP_INIT_FD)
         set(USE_OPENLDAP ON)
-        add_definitions("-DLDAP_DEPRECATED=1")
       endif()
       if(NOT CURL_DISABLE_LDAPS)
         set(HAVE_LDAP_SSL ON)
@@ -1492,13 +1502,13 @@ set(HAVE_LIBIDN2 OFF)
 if(USE_LIBIDN2 AND NOT USE_APPLE_IDN AND NOT USE_WIN32_IDN)
   find_package(Libidn2 QUIET)
   if(LIBIDN2_FOUND)
-    set(CURL_LIBS "${LIBIDN2_LIBRARIES};${CURL_LIBS}")
+    set(CURL_LIBS ${LIBIDN2_LIBRARIES} ${CURL_LIBS})
     list(APPEND CURL_LIBDIRS ${LIBIDN2_LIBRARY_DIRS})
-    set(LIBCURL_PC_REQUIRES_PRIVATE "${LIBIDN2_PC_REQUIRES};${LIBCURL_PC_REQUIRES_PRIVATE}")
+    set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBIDN2_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
     include_directories(SYSTEM ${LIBIDN2_INCLUDE_DIRS})
     link_directories(${LIBIDN2_LIBRARY_DIRS})
     if(LIBIDN2_CFLAGS)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBIDN2_CFLAGS}")
+      string(APPEND CMAKE_C_FLAGS " ${LIBIDN2_CFLAGS}")
     endif()
     set(HAVE_IDN2_H 1)
     set(HAVE_LIBIDN2 1)
@@ -1518,7 +1528,7 @@ if(CURL_USE_LIBPSL)
   include_directories(SYSTEM ${LIBPSL_INCLUDE_DIRS})
   link_directories(${LIBPSL_LIBRARY_DIRS})
   if(LIBPSL_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBPSL_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${LIBPSL_CFLAGS}")
   endif()
   set(USE_LIBPSL ON)
 endif()
@@ -1531,13 +1541,13 @@ set(USE_LIBSSH2 OFF)
 if(CURL_USE_LIBSSH2)
   find_package(Libssh2)
   if(LIBSSH2_FOUND)
-    list(APPEND CURL_LIBS ${LIBSSH2_LIBRARIES})
+    set(CURL_LIBS ${LIBSSH2_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
     list(APPEND CURL_LIBDIRS ${LIBSSH2_LIBRARY_DIRS})
-    list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH2_PC_REQUIRES})
+    set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH2_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
     include_directories(SYSTEM ${LIBSSH2_INCLUDE_DIRS})
     link_directories(${LIBSSH2_LIBRARY_DIRS})
     if(LIBSSH2_CFLAGS)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBSSH2_CFLAGS}")
+      string(APPEND CMAKE_C_FLAGS " ${LIBSSH2_CFLAGS}")
     endif()
     set(USE_LIBSSH2 ON)
   endif()
@@ -1548,13 +1558,13 @@ option(CURL_USE_LIBSSH "Use libssh" OFF)
 mark_as_advanced(CURL_USE_LIBSSH)
 if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
   find_package(Libssh REQUIRED)
-  list(APPEND CURL_LIBS ${LIBSSH_LIBRARIES})
+  set(CURL_LIBS ${LIBSSH_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
   list(APPEND CURL_LIBDIRS ${LIBSSH_LIBRARY_DIRS})
-  list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH_PC_REQUIRES})
+  set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
   include_directories(SYSTEM ${LIBSSH_INCLUDE_DIRS})
   link_directories(${LIBSSH_LIBRARY_DIRS})
   if(LIBSSH_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBSSH_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${LIBSSH_CFLAGS}")
   endif()
   set(USE_LIBSSH ON)
 endif()
@@ -1567,7 +1577,7 @@ if(NOT USE_LIBSSH2 AND NOT USE_LIBSSH AND CURL_USE_WOLFSSH)
   if(USE_WOLFSSL)
     find_package(WolfSSH)
     if(WOLFSSH_FOUND)
-      list(APPEND CURL_LIBS ${WOLFSSH_LIBRARIES})
+      set(CURL_LIBS ${WOLFSSH_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
       include_directories(SYSTEM ${WOLFSSH_INCLUDE_DIRS})
       set(USE_WOLFSSH ON)
     endif()
@@ -1586,7 +1596,7 @@ if(CURL_USE_GSASL)
   include_directories(SYSTEM ${LIBGSASL_INCLUDE_DIRS})
   link_directories(${LIBGSASL_LIBRARY_DIRS})
   if(LIBGSASL_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBGSASL_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${LIBGSASL_CFLAGS}")
   endif()
   set(USE_GSASL ON)
 endif()
@@ -1605,7 +1615,7 @@ if(CURL_USE_GSSAPI)
     include_directories(SYSTEM ${GSS_INCLUDE_DIRS})
     link_directories(${GSS_LIBRARY_DIRS})
     if(GSS_CFLAGS)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_CFLAGS}")
+      string(APPEND CMAKE_C_FLAGS " ${GSS_CFLAGS}")
     endif()
 
     if(GSS_FLAVOUR STREQUAL "GNU")
@@ -1631,7 +1641,7 @@ if(CURL_USE_GSSAPI)
         endif()
 
         if(NOT DEFINED HAVE_GSS_C_NT_HOSTBASED_SERVICE)
-          set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${GSS_CFLAGS}")
+          string(APPEND CMAKE_REQUIRED_FLAGS " ${GSS_CFLAGS}")
           list(APPEND CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
           curl_required_libpaths("${GSS_LIBRARY_DIRS}")
           check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" "${_include_list}" HAVE_GSS_C_NT_HOSTBASED_SERVICE)
@@ -1661,7 +1671,7 @@ if(CURL_USE_LIBUV)
   include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
   link_directories(${LIBUV_LIBRARY_DIRS})
   if(LIBUV_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBUV_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${LIBUV_CFLAGS}")
   endif()
   set(USE_LIBUV ON)
   set(HAVE_UV_H ON)
@@ -1676,7 +1686,7 @@ if(USE_LIBRTMP)
   include_directories(SYSTEM ${LIBRTMP_INCLUDE_DIRS})
   link_directories(${LIBRTMP_LIBRARY_DIRS})
   if(LIBRTMP_CFLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRTMP_CFLAGS}")
+    string(APPEND CMAKE_C_FLAGS " ${LIBRTMP_CFLAGS}")
   endif()
 endif()
 
@@ -1875,7 +1885,7 @@ foreach(_variable IN ITEMS
     HAVE_UNISTD_H
     )
   if(${_variable})
-    set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${_variable}")
+    string(APPEND CURL_TEST_DEFINES " -D${_variable}")
   endif()
 endforeach()
 
@@ -1946,14 +1956,15 @@ check_function_exists("eventfd"       HAVE_EVENTFD)
 check_symbol_exists("ftruncate"       "unistd.h" HAVE_FTRUNCATE)
 check_symbol_exists("getpeername"     "${CURL_INCLUDES}" HAVE_GETPEERNAME)  # winsock2.h unistd.h proto/bsdsocket.h
 check_symbol_exists("getsockname"     "${CURL_INCLUDES}" HAVE_GETSOCKNAME)  # winsock2.h unistd.h proto/bsdsocket.h
-check_function_exists("if_nametoindex"  HAVE_IF_NAMETOINDEX)  # winsock2.h net/if.h
 check_function_exists("getrlimit"       HAVE_GETRLIMIT)
 check_function_exists("setlocale"       HAVE_SETLOCALE)
 check_function_exists("setmode"         HAVE_SETMODE)
 check_function_exists("setrlimit"       HAVE_SETRLIMIT)
 
 if(NOT WIN32)
-  check_function_exists("sched_yield"   HAVE_SCHED_YIELD)
+  check_function_exists("if_nametoindex"  HAVE_IF_NAMETOINDEX)  # iphlpapi.h (Windows non-UWP), net/if.h
+  check_function_exists("realpath"        HAVE_REALPATH)
+  check_function_exists("sched_yield"     HAVE_SCHED_YIELD)
   check_symbol_exists("strcasecmp"      "string.h" HAVE_STRCASECMP)
   check_symbol_exists("stricmp"         "string.h" HAVE_STRICMP)
   check_symbol_exists("strcmpi"         "string.h" HAVE_STRCMPI)
@@ -1971,15 +1982,16 @@ if(NOT _ssl_enabled)
   check_symbol_exists("arc4random" "${CURL_INCLUDES};stdlib.h" HAVE_ARC4RANDOM)
 endif()
 
-if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
-  # Earlier MSVC compilers had faulty snprintf implementations
-  check_function_exists("snprintf" HAVE_SNPRINTF)
+if(NOT MSVC)
+  check_function_exists("snprintf" HAVE_SNPRINTF)  # to match detection method in ./configure
+elseif(MSVC_VERSION GREATER_EQUAL 1900)  # Earlier MSVC compilers had faulty snprintf implementations
+  check_symbol_exists("snprintf" "stdio.h" HAVE_SNPRINTF)  # snprintf may be a compatibility macro, not an exported function
 endif()
 if(APPLE)
   check_function_exists("mach_absolute_time" HAVE_MACH_ABSOLUTE_TIME)
 endif()
-check_symbol_exists("inet_ntop" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_NTOP)  # arpa/inet.h
-check_symbol_exists("inet_pton" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_PTON)  # arpa/inet.h
+check_symbol_exists("inet_ntop" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_NTOP)  # arpa/inet.h netinet/in.h sys/socket.h
+check_symbol_exists("inet_pton" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_PTON)  # arpa/inet.h netinet/in.h sys/socket.h
 
 check_symbol_exists("fsetxattr" "sys/xattr.h" HAVE_FSETXATTR)
 if(HAVE_FSETXATTR)
@@ -2124,7 +2136,7 @@ if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
     # The Mac version of GCC warns about use of long double. Disable it.
     get_source_file_property(_mprintf_compile_flags "mprintf.c" COMPILE_FLAGS)
     if(_mprintf_compile_flags)
-      set(_mprintf_compile_flags "${_mprintf_compile_flags} -Wno-long-double")
+      string(APPEND _mprintf_compile_flags " -Wno-long-double")
     else()
       set(_mprintf_compile_flags "-Wno-long-double")
     endif()
@@ -2143,13 +2155,15 @@ include(CMake/OtherTests.cmake)
 add_definitions("-DHAVE_CONFIG_H")
 
 if(WIN32)
+  list(APPEND CURL_LIBS "ws2_32" "bcrypt")
+
   # _fseeki64() requires VS2005
   if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1400))
     set(USE_WIN32_LARGE_FILES ON)
   endif()
 
   # Use the manifest embedded in the Windows Resource
-  set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
+  string(APPEND CMAKE_RC_FLAGS " -DCURL_EMBED_MANIFEST")
 
   # We use crypto functions that are not available for UWP apps
   if(NOT WINDOWS_STORE)
@@ -2164,26 +2178,25 @@ endif()
 
 if(MSVC)
   # Disable default manifest added by CMake
-  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -MANIFEST:NO")
+  string(APPEND CMAKE_EXE_LINKER_FLAGS " -MANIFEST:NO")
 
   if(CMAKE_C_FLAGS MATCHES "[/-]W[0-4]")
     string(REGEX REPLACE "[/-]W[0-4]" "-W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
   else()
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W4")
+    string(APPEND CMAKE_C_FLAGS " -W4")
   endif()
 
   # Use multithreaded compilation on VS2008+
   if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER_EQUAL 1500)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP")
+    string(APPEND CMAKE_C_FLAGS " -MP")
   endif()
 endif()
 
 if(CURL_WERROR)
   if(MSVC)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -WX")
+    string(APPEND CMAKE_C_FLAGS " -WX")
   else()
-    # This assumes clang or gcc style options
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+    string(APPEND CMAKE_C_FLAGS " -Werror")  # This assumes clang or gcc style options
   endif()
 endif()
 
@@ -2352,7 +2365,7 @@ curl_add_if("brotli"        HAVE_BROTLI)
 curl_add_if("gsasl"         USE_GSASL)
 curl_add_if("zstd"          HAVE_ZSTD)
 curl_add_if("AsynchDNS"     USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
-curl_add_if("asyn-rr"       USE_ARES AND ENABLE_THREADED_RESOLVER)
+curl_add_if("asyn-rr"       USE_ARES AND ENABLE_THREADED_RESOLVER AND USE_HTTPSRR)
 curl_add_if("IDN"           (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR
                             USE_WIN32_IDN OR
                             USE_APPLE_IDN)
@@ -2427,7 +2440,6 @@ if(NOT CURL_DISABLE_INSTALL)
 
   # curl-config needs the following options to be set.
   set(CC                      "${CMAKE_C_COMPILER}")
-  # TODO: probably put a -D... options here?
   set(CONFIGURE_OPTIONS       "")
   set(CURLVERSION             "${_curl_version}")
   set(VERSIONNUM              "${_curl_version_num}")
@@ -2471,18 +2483,18 @@ if(NOT CURL_DISABLE_INSTALL)
   endforeach()
 
   # Avoid getting unnecessary -L options for known system directories.
-  set(_sys_libdirs "")
+  set(_sys_libdirs "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
   foreach(_libdir IN LISTS CMAKE_SYSTEM_PREFIX_PATH)
     if(_libdir MATCHES "/$")
-      set(_libdir "${_libdir}lib")
+      string(APPEND _libdir "lib")
     else()
-      set(_libdir "${_libdir}/lib")
+      string(APPEND _libdir "/lib")
     endif()
     if(IS_DIRECTORY "${_libdir}")
       list(APPEND _sys_libdirs "${_libdir}")
     endif()
     if(DEFINED CMAKE_LIBRARY_ARCHITECTURE)
-      set(_libdir "${_libdir}/${CMAKE_LIBRARY_ARCHITECTURE}")
+      string(APPEND _libdir "/${CMAKE_LIBRARY_ARCHITECTURE}")
       if(IS_DIRECTORY "${_libdir}")
         list(APPEND _sys_libdirs "${_libdir}")
       endif()
@@ -2490,6 +2502,9 @@ if(NOT CURL_DISABLE_INSTALL)
   endforeach()
 
   foreach(_libdir IN LISTS _custom_libdirs CURL_LIBDIRS)
+    if(NOT CMAKE_VERSION VERSION_LESS 3.20)
+      cmake_path(SET _libdir NORMALIZE "${_libdir}")
+    endif()
     list(FIND _sys_libdirs "${_libdir}" _libdir_index)
     if(_libdir_index LESS 0)
       list(APPEND _ldflags "-L${_libdir}")
@@ -2498,7 +2513,7 @@ if(NOT CURL_DISABLE_INSTALL)
 
   set(_implicit_libs "")
   if(NOT MINGW AND NOT UNIX)
-    set(_implicit_libs ${CMAKE_C_IMPLICIT_LINK_LIBRARIES})
+    set(_implicit_libs "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}")
   endif()
 
   foreach(_lib IN LISTS _implicit_libs _custom_libs CURL_LIBS)
@@ -2524,6 +2539,9 @@ if(NOT CURL_DISABLE_INSTALL)
       get_filename_component(_libdir ${_lib} DIRECTORY)
       get_filename_component(_libname ${_lib} NAME_WE)
       if(_libname MATCHES "^lib")
+        if(NOT CMAKE_VERSION VERSION_LESS 3.20)
+          cmake_path(SET _libdir NORMALIZE "${_libdir}")
+        endif()
         list(FIND _sys_libdirs "${_libdir}" _libdir_index)
         if(_libdir_index LESS 0)
           list(APPEND _ldflags "-L${_libdir}")
@@ -2694,6 +2712,7 @@ if(NOT CURL_DISABLE_INSTALL)
 endif()
 
 # Save build info for test runner to pick up and log
+set(_cmake_sysroot "")
 if(CMAKE_OSX_SYSROOT)
   set(_cmake_sysroot ${CMAKE_OSX_SYSROOT})
 elseif(CMAKE_SYSROOT)

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

@@ -32,13 +32,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "8.12.0"
+#define LIBCURL_VERSION "8.12.1"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 8
 #define LIBCURL_VERSION_MINOR 12
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -59,7 +59,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 0x080c00
+#define LIBCURL_VERSION_NUM 0x080c01
 
 /*
  * This is the date and time when the full source package was created. The

+ 10 - 0
Utilities/cmcurl/lib/CMakeLists.txt

@@ -94,6 +94,9 @@ if(CURL_BUILD_TESTING)
   )
   target_compile_definitions(curlu PUBLIC "UNITTESTS" "CURL_STATICLIB")
   target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+  # There is plenty of parallelism when building the testdeps target.
+  # Override the curlu batch size with the maximum to optimize performance.
+  set_target_properties(curlu PROPERTIES UNITY_BUILD_BATCH_SIZE 0)
 endif()
 
 if(ENABLE_CURLDEBUG)
@@ -104,6 +107,13 @@ endif()
 
 ## Library definition
 
+if(NOT DEFINED IMPORT_LIB_SUFFIX)
+  set(IMPORT_LIB_SUFFIX "")
+endif()
+if(NOT DEFINED STATIC_LIB_SUFFIX)
+  set(STATIC_LIB_SUFFIX "")
+endif()
+
 # Add "_imp" as a suffix before the extension to avoid conflicting with
 # the statically linked "libcurl.lib" (typically with MSVC)
 if(WIN32 AND

+ 3 - 0
Utilities/cmcurl/lib/asyn-ares.c

@@ -109,6 +109,9 @@ int Curl_ares_perform(ares_channel channel,
   int i;
   int num = 0;
 
+  if(!channel)
+    return 0;
+
   bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
 
   for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {

+ 22 - 25
Utilities/cmcurl/lib/asyn-thread.c

@@ -138,14 +138,14 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
   return Curl_resolver_init(easy, to);
 }
 
-static void destroy_async_data(struct Curl_async *);
+static void destroy_async_data(struct Curl_easy *);
 
 /*
  * Cancel all possibly still on-going resolves for this connection.
  */
 void Curl_resolver_cancel(struct Curl_easy *data)
 {
-  destroy_async_data(&data->state.async);
+  destroy_async_data(data);
 }
 
 /* This function is used to init a threaded resolve */
@@ -282,14 +282,6 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
   struct thread_data *td = tsd->td;
   char service[12];
   int rc;
-#ifndef CURL_DISABLE_SOCKETPAIR
-#ifdef USE_EVENTFD
-  const void *buf;
-  const uint64_t val = 1;
-#else
-  char buf[1];
-#endif
-#endif
 
   msnprintf(service, sizeof(service), "%d", tsd->port);
 
@@ -315,9 +307,9 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
 #ifndef CURL_DISABLE_SOCKETPAIR
     if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
 #ifdef USE_EVENTFD
-      buf = &val;
+      const uint64_t buf[1] = { 1 };
 #else
-      buf[0] = 1;
+      const char buf[1] = { 1 };
 #endif
       /* DNS has been resolved, signal client task */
       if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
@@ -377,18 +369,22 @@ CURL_STDCALL gethostbyname_thread(void *arg)
 /*
  * destroy_async_data() cleans up async resolver data and thread handle.
  */
-static void destroy_async_data(struct Curl_async *async)
+static void destroy_async_data(struct Curl_easy *data)
 {
+  struct Curl_async *async;
+  DEBUGASSERT(data);
+  async = &data->state.async;
+  DEBUGASSERT(async);
   if(async->tdata) {
     struct thread_data *td = async->tdata;
     bool done;
 #ifndef CURL_DISABLE_SOCKETPAIR
     curl_socket_t sock_rd = td->tsd.sock_pair[0];
-    struct Curl_easy *data = td->tsd.data;
 #endif
 
 #ifdef USE_HTTPSRR_ARES
-    ares_destroy(data->state.async.tdata->channel);
+    if(data->state.async.tdata->channel)
+      ares_destroy(data->state.async.tdata->channel);
 #endif
     /*
      * if the thread is still blocking in the resolve syscall, detach it and
@@ -495,12 +491,12 @@ static bool init_resolve_thread(struct Curl_easy *data,
   }
 #ifdef USE_HTTPSRR_ARES
   if(resolve_httpsrr(data, asp))
-    goto err_exit;
+    infof(data, "Failed HTTPS RR operation");
 #endif
   return TRUE;
 
 err_exit:
-  destroy_async_data(asp);
+  destroy_async_data(data);
 
 errno_exit:
   errno = err;
@@ -539,7 +535,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
     /* a name was not resolved, report error */
     result = Curl_resolver_error(data);
 
-  destroy_async_data(&data->state.async);
+  destroy_async_data(data);
 
   if(!data->state.async.dns && report)
     connclose(data->conn, "asynch resolve failed");
@@ -617,7 +613,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
 
     if(!data->state.async.dns) {
       CURLcode result = Curl_resolver_error(data);
-      destroy_async_data(&data->state.async);
+      destroy_async_data(data);
       return result;
     }
 #ifdef USE_HTTPSRR_ARES
@@ -625,13 +621,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
       struct Curl_https_rrinfo *lhrr =
         Curl_memdup(&td->hinfo, sizeof(struct Curl_https_rrinfo));
       if(!lhrr) {
-        destroy_async_data(&data->state.async);
+        destroy_async_data(data);
         return CURLE_OUT_OF_MEMORY;
       }
       data->state.async.dns->hinfo = lhrr;
     }
 #endif
-    destroy_async_data(&data->state.async);
+    destroy_async_data(data);
     *entry = data->state.async.dns;
   }
   else {
@@ -665,15 +661,17 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
   timediff_t milli;
   timediff_t ms;
   struct resdata *reslv = (struct resdata *)data->state.async.resolver;
-  int socketi = 0;
 #ifndef CURL_DISABLE_SOCKETPAIR
   struct thread_data *td = data->state.async.tdata;
+#endif
+#if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES)
+  int socketi = 0;
 #else
   (void)socks;
 #endif
 
 #ifdef USE_HTTPSRR_ARES
-  if(data->state.async.tdata) {
+  if(data->state.async.tdata && data->state.async.tdata->channel) {
     ret_val = Curl_ares_getsock(data, data->state.async.tdata->channel, socks);
     for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
       if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
@@ -685,8 +683,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
   if(td) {
     /* return read fd to client for polling the DNS resolution status */
     socks[socketi] = td->tsd.sock_pair[0];
-    td->tsd.data = data;
-    ret_val = GETSOCK_READSOCK(socketi);
+    ret_val |= GETSOCK_READSOCK(socketi);
   }
   else {
 #endif

+ 3 - 4
Utilities/cmcurl/lib/asyn.h

@@ -40,20 +40,19 @@ struct Curl_dns_entry;
 /* Data for synchronization between resolver thread and its parent */
 struct thread_sync_data {
   curl_mutex_t *mtx;
-  bool done;
-  int port;
   char *hostname;        /* hostname to resolve, Curl_async.hostname
                             duplicate */
 #ifndef CURL_DISABLE_SOCKETPAIR
-  struct Curl_easy *data;
   curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
 #endif
-  int sock_error;
   struct Curl_addrinfo *res;
 #ifdef HAVE_GETADDRINFO
   struct addrinfo hints;
 #endif
   struct thread_data *td; /* for thread-self cleanup */
+  int port;
+  int sock_error;
+  bool done;
 };
 
 struct thread_data {

+ 0 - 1
Utilities/cmcurl/lib/cf-h1-proxy.c

@@ -660,7 +660,6 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
     cf->ctx = ts;
   }
 
-  /* TODO: can we do blocking? */
   /* We want "seamless" operations through HTTP proxy tunnel */
 
   result = H1_CONNECT(cf, data, ts);

+ 1 - 1
Utilities/cmcurl/lib/cf-h2-proxy.c

@@ -1408,7 +1408,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
   ssize_t nwritten;
   CURLcode result;
 
-  (void)eos; /* TODO, maybe useful for blocks? */
+  (void)eos;
   if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
     *err = CURLE_SEND_ERROR;
     return -1;

+ 5 - 11
Utilities/cmcurl/lib/cf-https-connect.c

@@ -42,11 +42,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 typedef enum {
   CF_HC_INIT,
   CF_HC_CONNECT,
@@ -592,8 +587,8 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
 
   DEBUGASSERT(alpnids);
   DEBUGASSERT(alpn_count);
-  DEBUGASSERT(alpn_count <= ARRAYSIZE(ctx->ballers));
-  if(!alpn_count || (alpn_count > ARRAYSIZE(ctx->ballers))) {
+  DEBUGASSERT(alpn_count <= CURL_ARRAYSIZE(ctx->ballers));
+  if(!alpn_count || (alpn_count > CURL_ARRAYSIZE(ctx->ballers))) {
     failf(data, "https-connect filter create with unsupported %zu ALPN ids",
           alpn_count);
     return CURLE_FAILED_INIT;
@@ -607,7 +602,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
   ctx->remotehost = remotehost;
   for(i = 0; i < alpn_count; ++i)
     cf_hc_baller_assign(&ctx->ballers[i], alpnids[i]);
-  for(; i < ARRAYSIZE(ctx->ballers); ++i)
+  for(; i < CURL_ARRAYSIZE(ctx->ballers); ++i)
     ctx->ballers[i].alpn_id = ALPN_none;
   ctx->baller_count = alpn_count;
 
@@ -663,8 +658,8 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
       if(conn->dns_entry && conn->dns_entry->hinfo &&
          !conn->dns_entry->hinfo->no_def_alpn) {
         size_t i, j;
-        for(i = 0; i < ARRAYSIZE(conn->dns_entry->hinfo->alpns) &&
-                   alpn_count < ARRAYSIZE(alpn_ids); ++i) {
+        for(i = 0; i < CURL_ARRAYSIZE(conn->dns_entry->hinfo->alpns) &&
+                   alpn_count < CURL_ARRAYSIZE(alpn_ids); ++i) {
           bool present = FALSE;
           enum alpnid alpn = conn->dns_entry->hinfo->alpns[i];
           for(j = 0; j < alpn_count; ++j) {
@@ -701,7 +696,6 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
       break;
     case CURL_HTTP_VERSION_3:
       /* We assume that silently not even trying H3 is ok here */
-      /* TODO: should we fail instead? */
       if(Curl_conn_may_http3(data, conn) == CURLE_OK)
         alpn_ids[alpn_count++] = ALPN_h3;
       alpn_ids[alpn_count++] = ALPN_h2;

+ 3 - 4
Utilities/cmcurl/lib/cf-socket.c

@@ -1325,7 +1325,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
     return CURLE_OK;
   }
 
-  /* TODO: need to support blocking connect? */
   if(blocking)
     return CURLE_UNSUPPORTED_PROTOCOL;
 
@@ -1432,7 +1431,7 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
     /* A listening socket filter needs to be connected before the accept
      * for some weird FTP interaction. This should be rewritten, so that
      * FTP no longer does the socket checks and accept calls and delegates
-     * all that to the filter. TODO. */
+     * all that to the filter. */
     if(ctx->listening) {
       Curl_pollset_set_in_only(data, ps, ctx->sock);
       CURL_TRC_CF(data, cf, "adjust_pollset, listening, POLLIN fd=%"
@@ -1850,7 +1849,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
   /* QUIC needs a connected socket, nonblocking */
   DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
 
-  rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,  /* NOLINT FIXME */
+  rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,  /* NOLINT */
                (curl_socklen_t)ctx->addr.addrlen);
   if(-1 == rc) {
     return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
@@ -2213,7 +2212,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
   cf_tcp_accept_connect,
   cf_socket_close,
   cf_socket_shutdown,
-  cf_socket_get_host,              /* TODO: not accurate */
+  cf_socket_get_host,
   cf_socket_adjust_pollset,
   cf_socket_data_pending,
   cf_socket_send,

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

@@ -41,10 +41,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 static void cf_cntrl_update_info(struct Curl_easy *data,
                                  struct connectdata *conn);
 
@@ -724,7 +720,7 @@ static CURLcode cf_cntrl_all(struct connectdata *conn,
   CURLcode result = CURLE_OK;
   size_t i;
 
-  for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
     result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
                                 event, arg1, arg2);
     if(!ignore_result && result)

+ 5 - 6
Utilities/cmcurl/lib/conncache.c

@@ -166,11 +166,11 @@ int Curl_cpool_init(struct cpool *cpool,
   if(!cpool->idata)
     return 1; /* bad */
   cpool->idata->state.internal = TRUE;
-  /* TODO: this is quirky. We need an internal handle for certain
-   * operations, but we do not add it to the multi (if there is one).
-   * But we give it the multi so that socket event operations can work.
-   * Probably better to have an internal handle owned by the multi that
-   * can be used for cpool operations. */
+  /* This is quirky. We need an internal handle for certain operations, but we
+   * do not add it to the multi (if there is one). We give it the multi so
+   * that socket event operations can work. Probably better to have an
+   * internal handle owned by the multi that can be used for cpool
+   * operations. */
   cpool->idata->multi = multi;
 #ifdef DEBUGBUILD
   if(getenv("CURL_DEBUG"))
@@ -1302,7 +1302,6 @@ static int conn_upkeep(struct Curl_easy *data,
                        void *param)
 {
   struct curltime *now = param;
-  /* TODO, shall we reap connections that return an error here? */
   Curl_conn_upkeep(data, conn, now);
   return 0; /* continue iteration */
 }

+ 14 - 18
Utilities/cmcurl/lib/connect.c

@@ -85,10 +85,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #if !defined(CURL_DISABLE_ALTSVC) || defined(USE_HTTPSRR)
 
 enum alpnid Curl_alpn2alpnid(char *name, size_t len)
@@ -644,7 +640,7 @@ evaluate:
   *connected = FALSE; /* a negative world view is best */
   now = Curl_now();
   ongoing = not_started = 0;
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
 
     if(!baller || baller->is_done)
@@ -705,7 +701,7 @@ evaluate:
   if(not_started > 0) {
     int added = 0;
 
-    for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+    for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
       struct eyeballer *baller = ctx->baller[i];
 
       if(!baller || baller->has_started)
@@ -739,7 +735,7 @@ evaluate:
   /* all ballers have failed to connect. */
   CURL_TRC_CF(data, cf, "all eyeballers failed");
   result = CURLE_COULDNT_CONNECT;
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
     if(!baller)
       continue;
@@ -884,7 +880,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGASSERT(ctx);
   DEBUGASSERT(data);
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     baller_free(ctx->baller[i], data);
     ctx->baller[i] = NULL;
   }
@@ -907,7 +903,7 @@ static CURLcode cf_he_shutdown(struct Curl_cfilter *cf,
 
   /* shutdown all ballers that have not done so already. If one fails,
    * continue shutting down others until all are shutdown. */
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
     bool bdone = FALSE;
     if(!baller || !baller->cf || baller->shutdown)
@@ -918,12 +914,12 @@ static CURLcode cf_he_shutdown(struct Curl_cfilter *cf,
   }
 
   *done = TRUE;
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     if(ctx->baller[i] && !ctx->baller[i]->shutdown)
       *done = FALSE;
   }
   if(*done) {
-    for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+    for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
       if(ctx->baller[i] && ctx->baller[i]->result)
         result = ctx->baller[i]->result;
     }
@@ -940,7 +936,7 @@ static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
   size_t i;
 
   if(!cf->connected) {
-    for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+    for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
       struct eyeballer *baller = ctx->baller[i];
       if(!baller || !baller->cf)
         continue;
@@ -962,7 +958,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
     return CURLE_OK;
   }
 
-  (void)blocking; /* TODO: do we want to support this? */
+  (void)blocking;
   DEBUGASSERT(ctx);
   *done = FALSE;
 
@@ -1037,7 +1033,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf,
   if(cf->connected)
     return cf->next->cft->has_data_pending(cf->next, data);
 
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
     if(!baller || !baller->cf)
       continue;
@@ -1056,7 +1052,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
   size_t i;
 
   memset(&tmax, 0, sizeof(tmax));
-  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+  for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
 
     memset(&t, 0, sizeof(t));
@@ -1081,7 +1077,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
       int reply_ms = -1;
       size_t i;
 
-      for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+      for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
         struct eyeballer *baller = ctx->baller[i];
         int breply_ms;
 
@@ -1215,7 +1211,7 @@ struct transport_provider transport_providers[] = {
 static cf_ip_connect_create *get_cf_create(int transport)
 {
   size_t i;
-  for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) {
     if(transport == transport_providers[i].transport)
       return transport_providers[i].cf_create;
   }
@@ -1469,7 +1465,7 @@ void Curl_debug_set_transport_provider(int transport,
                                        cf_ip_connect_create *cf_create)
 {
   size_t i;
-  for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) {
     if(transport == transport_providers[i].transport) {
       transport_providers[i].cf_create = cf_create;
       return;

+ 7 - 12
Utilities/cmcurl/lib/content_encoding.c

@@ -69,6 +69,10 @@
 
 #ifdef HAVE_LIBZ
 
+#if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
+#error "requires zlib 1.2.0.4 or newer"
+#endif
+
 typedef enum {
   ZLIB_UNINIT,               /* uninitialized */
   ZLIB_INIT,                 /* initialized */
@@ -309,24 +313,15 @@ static CURLcode gzip_do_init(struct Curl_easy *data,
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
-  const char *v = zlibVersion();
 
   /* Initialize zlib */
   z->zalloc = (alloc_func) zalloc_cb;
   z->zfree = (free_func) zfree_cb;
 
-  if(strcmp(v, "1.2.0.4") >= 0) {
-    /* zlib version >= 1.2.0.4 supports transparent gzip decompressing */
-    if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
-      return process_zlib_error(data, z);
-    }
-    zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
-  }
-  else {
-    failf(data, "too old zlib version: %s", v);
-    return CURLE_FAILED_INIT;
-  }
+  if(inflateInit2(z, MAX_WBITS + 32) != Z_OK)
+    return process_zlib_error(data, z);
 
+  zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
   return CURLE_OK;
 }
 

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

@@ -879,7 +879,7 @@ parse_netscape(struct Cookie *co,
       /*
        * flag: A TRUE/FALSE value indicating if all machines within a given
        * domain can access the variable. Set TRUE when the cookie says
-       * .domain.com and to false when the domain is complete www.domain.com
+       * .example.com and to false when the domain is complete www.example.com
        */
       co->tailmatch = !!strncasecompare(ptr, "TRUE", len);
       break;

+ 3 - 0
Utilities/cmcurl/lib/curl_config.h.cmake

@@ -428,6 +428,9 @@
 /* If you have poll */
 #cmakedefine HAVE_POLL 1
 
+/* If you have realpath */
+#cmakedefine HAVE_REALPATH 1
+
 /* Define to 1 if you have the <poll.h> header file. */
 #cmakedefine HAVE_POLL_H 1
 

+ 10 - 2
Utilities/cmcurl/lib/curl_setup.h

@@ -948,6 +948,8 @@ endings either CRLF or LF so 't' is appropriate.
    as their argument */
 #define STRCONST(x) x,sizeof(x)-1
 
+#define CURL_ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+
 /* Some versions of the Android NDK is missing the declaration */
 #if defined(HAVE_GETPWUID_R) && \
   defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
@@ -998,10 +1000,16 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
 #  endif
 #endif
 
+#ifdef USE_OPENSSL
 /* OpenSSLv3 marks DES, MD5 and ENGINE functions deprecated but we have no
    replacements (yet) so tell the compiler to not warn for them. */
-#ifdef USE_OPENSSL
-#define OPENSSL_SUPPRESS_DEPRECATED
+#  define OPENSSL_SUPPRESS_DEPRECATED
+#  ifdef _WIN32
+/* Silence LibreSSL warnings about wincrypt.h collision. Works in 3.8.2+ */
+#    ifndef LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING
+#    define LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING
+#    endif
+#  endif
 #endif
 
 #if defined(CURL_INLINE)

+ 4 - 8
Utilities/cmcurl/lib/curl_trc.c

@@ -53,10 +53,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 void Curl_debug(struct Curl_easy *data, curl_infotype type,
                 char *ptr, size_t size)
 {
@@ -349,13 +345,13 @@ static void trc_apply_level_by_name(const char * const token, int lvl)
 {
   size_t i;
 
-  for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) {
     if(strcasecompare(token, trc_cfts[i].cft->name)) {
       trc_cfts[i].cft->log_level = lvl;
       break;
     }
   }
-  for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) {
     if(strcasecompare(token, trc_feats[i].feat->name)) {
       trc_feats[i].feat->log_level = lvl;
       break;
@@ -367,11 +363,11 @@ static void trc_apply_level_by_category(int category, int lvl)
 {
   size_t i;
 
-  for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) {
     if(!category || (trc_cfts[i].category & category))
       trc_cfts[i].cft->log_level = lvl;
   }
-  for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) {
     if(!category || (trc_feats[i].category & category))
       trc_feats[i].feat->log_level = lvl;
   }

+ 2 - 10
Utilities/cmcurl/lib/ftp.c

@@ -4108,11 +4108,6 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4706) /* assignment within conditional expression */
-#endif
-
 /***********************************************************************
  *
  * ftp_parse_url_path()
@@ -4203,7 +4198,8 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
         }
 
         /* parse the URL path into separate path components */
-        while((slashPos = strchr(curPos, '/'))) {
+        /* !checksrc! disable EQUALSNULL 1 */
+        while((slashPos = strchr(curPos, '/')) != NULL) {
           size_t compLen = slashPos - curPos;
 
           /* path starts with a slash: add that as a directory */
@@ -4267,10 +4263,6 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
   return CURLE_OK;
 }
 
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
 /* call this when the DO phase has completed */
 static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
 {

+ 4 - 6
Utilities/cmcurl/lib/http.c

@@ -495,7 +495,6 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
             ongoing_auth ? " send, " : "");
     /* We decided to abort the ongoing transfer */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
-    /* FIXME: questionable manipulation here, can we do this differently? */
     data->req.size = 0; /* do not download any more than 0 bytes */
   }
   return CURLE_OK;
@@ -2477,7 +2476,7 @@ static CURLcode http_range(struct Curl_easy *data,
       }
       else if(data->state.resume_from) {
         /* This is because "resume" was selected */
-        /* TODO: not sure if we want to send this header during authentication
+        /* Not sure if we want to send this header during authentication
          * negotiation, but test1084 checks for it. In which case we have a
          * "null" client reader installed that gives an unexpected length. */
         curl_off_t total_len = data->req.authneg ?
@@ -3597,10 +3596,9 @@ static CURLcode http_on_response(struct Curl_easy *data,
       }
 #endif
       else {
-        /* We silently accept this as the final response.
-         * TODO: this looks, uhm, wrong. What are we switching to if we
-         * did not ask for an Upgrade? Maybe the application provided an
-         * `Upgrade: xxx` header? */
+        /* We silently accept this as the final response. What are we
+         * switching to if we did not ask for an Upgrade? Maybe the
+         * application provided an `Upgrade: xxx` header? */
         k->header = FALSE;
       }
       break;

+ 0 - 2
Utilities/cmcurl/lib/http1.c

@@ -167,8 +167,6 @@ static CURLcode start_req(struct h1_req_parser *parser,
   if(!target_len || !hv_len)
     goto out;
 
-  /* TODO: we do not check HTTP_VERSION for conformity, should
-   + do that when STRICT option is supplied. */
   (void)hv;
 
   /* The TARGET can be (rfc 9112, ch. 3.2):

+ 26 - 32
Utilities/cmcurl/lib/imap.c

@@ -193,19 +193,6 @@ static const struct SASLproto saslimap = {
 };
 
 
-#ifdef USE_SSL
-static void imap_to_imaps(struct connectdata *conn)
-{
-  /* Change the connection handler */
-  conn->handler = &Curl_handler_imaps;
-
-  /* Set the connection's upgraded to TLS flag */
-  conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define imap_to_imaps(x) Curl_nop_stmt
-#endif
-
 /***********************************************************************
  *
  * imap_matchresp()
@@ -474,6 +461,7 @@ static CURLcode imap_perform_starttls(struct Curl_easy *data)
 static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
                                          struct connectdata *conn)
 {
+#ifdef USE_SSL
   /* Start the SSL connection */
   struct imap_conn *imapc = &conn->proto.imapc;
   CURLcode result;
@@ -483,21 +471,27 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
     if(result)
       goto out;
+    /* Change the connection handler */
+    conn->handler = &Curl_handler_imaps;
+    conn->bits.tls_upgraded = TRUE;
   }
 
+  DEBUGASSERT(!imapc->ssldone);
   result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-  if(!result) {
+  DEBUGF(infof(data, "imap_perform_upgrade_tls, connect -> %d, %d",
+         result, ssldone));
+  if(!result && ssldone) {
     imapc->ssldone = ssldone;
-    if(imapc->state != IMAP_UPGRADETLS)
-      imap_state(data, IMAP_UPGRADETLS);
-
-    if(imapc->ssldone) {
-      imap_to_imaps(conn);
-      result = imap_perform_capability(data, conn);
-    }
+     /* perform CAPA now, changes imapc->state out of IMAP_UPGRADETLS */
+     result = imap_perform_capability(data, conn);
   }
 out:
   return result;
+#else
+  (void)data;
+  (void)conn;
+  return CURLE_NOT_BUILT_IN;
+#endif
 }
 
 /***********************************************************************
@@ -998,7 +992,7 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
       result = imap_perform_authentication(data, conn);
   }
   else
-    result = imap_perform_upgrade_tls(data, conn);
+    imap_state(data, IMAP_UPGRADETLS);
 
   return result;
 }
@@ -1307,8 +1301,12 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
   (void)data;
 
   /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
-  if(imapc->state == IMAP_UPGRADETLS)
-    return imap_perform_upgrade_tls(data, conn);
+upgrade_tls:
+  if(imapc->state == IMAP_UPGRADETLS) {
+    result = imap_perform_upgrade_tls(data, conn);
+    if(result || (imapc->state == IMAP_UPGRADETLS))
+      return result;
+  }
 
   /* Flush any data that needs to be sent */
   if(pp->sendleft)
@@ -1339,6 +1337,10 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
 
     case IMAP_STARTTLS:
       result = imap_state_starttls_resp(data, imapcode, imapc->state);
+      /* During UPGRADETLS, leave the read loop as we need to connect
+       * (e.g. TLS handshake) before we continue sending/receiving. */
+      if(!result && (imapc->state == IMAP_UPGRADETLS))
+        goto upgrade_tls;
       break;
 
     case IMAP_AUTHENTICATE:
@@ -1392,14 +1394,6 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
   struct connectdata *conn = data->conn;
   struct imap_conn *imapc = &conn->proto.imapc;
 
-  if(Curl_conn_is_ssl(conn, FIRSTSOCKET) && !imapc->ssldone) {
-    bool ssldone = FALSE;
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-    imapc->ssldone = ssldone;
-    if(result || !ssldone)
-      return result;
-  }
-
   result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
   *done = (imapc->state == IMAP_STOP);
 

+ 6 - 0
Utilities/cmcurl/lib/inet_ntop.h

@@ -29,6 +29,12 @@
 char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
 
 #ifdef HAVE_INET_NTOP
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif

+ 6 - 0
Utilities/cmcurl/lib/inet_pton.h

@@ -29,6 +29,12 @@
 int Curl_inet_pton(int, const char *, void *);
 
 #ifdef HAVE_INET_PTON
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif

+ 1 - 53
Utilities/cmcurl/lib/ldap.c

@@ -389,55 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 #else
     int ldap_option;
     char *ldap_ca = conn->ssl_config.CAfile;
-#if defined(CURL_HAS_NOVELL_LDAPSDK)
-    rc = ldapssl_client_init(NULL, NULL);
-    if(rc != LDAP_SUCCESS) {
-      failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
-      result = CURLE_SSL_CERTPROBLEM;
-      goto quit;
-    }
-    if(conn->ssl_config.verifypeer) {
-      /* Novell SDK supports DER or BASE64 files. */
-      int cert_type = LDAPSSL_CERT_FILETYPE_B64;
-      if((data->set.ssl.cert_type) &&
-         (strcasecompare(data->set.ssl.cert_type, "DER")))
-        cert_type = LDAPSSL_CERT_FILETYPE_DER;
-      if(!ldap_ca) {
-        failf(data, "LDAP local: ERROR %s CA cert not set",
-              (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
-        result = CURLE_SSL_CERTPROBLEM;
-        goto quit;
-      }
-      infof(data, "LDAP local: using %s CA cert '%s'",
-            (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
-            ldap_ca);
-      rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
-      if(rc != LDAP_SUCCESS) {
-        failf(data, "LDAP local: ERROR setting %s CA cert: %s",
-              (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
-              ldap_err2string(rc));
-        result = CURLE_SSL_CERTPROBLEM;
-        goto quit;
-      }
-      ldap_option = LDAPSSL_VERIFY_SERVER;
-    }
-    else
-      ldap_option = LDAPSSL_VERIFY_NONE;
-    rc = ldapssl_set_verify_mode(ldap_option);
-    if(rc != LDAP_SUCCESS) {
-      failf(data, "LDAP local: ERROR setting cert verify mode: %s",
-              ldap_err2string(rc));
-      result = CURLE_SSL_CERTPROBLEM;
-      goto quit;
-    }
-    server = ldapssl_init(host, conn->primary.remote_port, 1);
-    if(!server) {
-      failf(data, "LDAP local: Cannot connect to %s:%u",
-            conn->host.dispname, conn->primary.remote_port);
-      result = CURLE_COULDNT_CONNECT;
-      goto quit;
-    }
-#elif defined(LDAP_OPT_X_TLS)
+#ifdef LDAP_OPT_X_TLS
     if(conn->ssl_config.verifypeer) {
       /* OpenLDAP SDK supports BASE64 files. */
       if((data->set.ssl.cert_type) &&
@@ -758,10 +710,6 @@ quit:
     ldap_free_urldesc(ludp);
   if(server)
     ldap_unbind_s(server);
-#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
-  if(ldap_ssl)
-    ldapssl_client_deinit();
-#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
 
   FREE_ON_WINLDAP(host);
 

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

@@ -1598,8 +1598,8 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
 
   (void) size;   /* Always 1. */
 
-  /* TODO: this loop is broken. If `nitems` is <= 4, some encoders will
-   * return STOP_FILLING without adding any data and this loops infinitely. */
+  /* If `nitems` is <= 4, some encoders will return STOP_FILLING without
+   * adding any data and this loops infinitely. */
   do {
     hasread = FALSE;
     ret = readback_part(part, buffer, nitems, &hasread);

+ 5 - 15
Utilities/cmcurl/lib/multi.c

@@ -1538,15 +1538,6 @@ CURLMcode curl_multi_wakeup(CURLM *m)
      Curl_multi struct that are constant */
   struct Curl_multi *multi = m;
 
-#if defined(ENABLE_WAKEUP) && !defined(USE_WINSOCK)
-#ifdef USE_EVENTFD
-  const void *buf;
-  const uint64_t val = 1;
-#else
-  char buf[1];
-#endif
-#endif
-
   /* GOOD_MULTI_HANDLE can be safely called */
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -1560,15 +1551,14 @@ CURLMcode curl_multi_wakeup(CURLM *m)
      making it safe to access from another thread after the init part
      and before cleanup */
   if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
+    while(1) {
 #ifdef USE_EVENTFD
-    buf = &val;
-    /* eventfd has a stringent rule of requiring the 8-byte buffer when
-       calling write(2) on it, which makes the sizeof(buf) below fine since
-       this is only used on 64-bit systems and then the pointer is 64-bit */
+      /* eventfd has a stringent rule of requiring the 8-byte buffer when
+         calling write(2) on it */
+      const uint64_t buf[1] = { 1 };
 #else
-    buf[0] = 1;
+      const char buf[1] = { 1 };
 #endif
-    while(1) {
       /* swrite() is not thread-safe in general, because concurrent calls
          can have their messages interleaved, but in this case the content
          of the messages does not matter, which makes it ok to call.

+ 68 - 37
Utilities/cmcurl/lib/netrc.c

@@ -59,23 +59,26 @@ enum found_state {
 #define FOUND_LOGIN    1
 #define FOUND_PASSWORD 2
 
-#define NETRC_FILE_MISSING 1
-#define NETRC_FAILED -1
-#define NETRC_SUCCESS 0
-
 #define MAX_NETRC_LINE 16384
 #define MAX_NETRC_FILE (128*1024)
 #define MAX_NETRC_TOKEN 4096
 
-static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
+/* convert a dynbuf call CURLcode error to a NETRCcode error */
+#define curl2netrc(result)                     \
+  (((result) == CURLE_OUT_OF_MEMORY) ?         \
+   NETRC_OUT_OF_MEMORY : NETRC_SYNTAX_ERROR)
+
+static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf)
 {
-  CURLcode result = CURLE_OK;
+  NETRCcode ret = NETRC_FILE_MISSING; /* if it cannot open the file */
   FILE *file = fopen(filename, FOPEN_READTEXT);
   struct dynbuf linebuf;
   Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
 
   if(file) {
+    ret = NETRC_OK;
     while(Curl_get_line(&linebuf, file)) {
+      CURLcode result;
       const char *line = Curl_dyn_ptr(&linebuf);
       /* skip comments on load */
       while(ISBLANK(*line))
@@ -83,27 +86,29 @@ static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
       if(*line == '#')
         continue;
       result = Curl_dyn_add(filebuf, line);
-      if(result)
+      if(result) {
+        ret = curl2netrc(result);
         goto done;
+      }
     }
   }
 done:
   Curl_dyn_free(&linebuf);
   if(file)
     fclose(file);
-  return result;
+  return ret;
 }
 
 /*
  * Returns zero on success.
  */
-static int parsenetrc(struct store_netrc *store,
-                      const char *host,
-                      char **loginp, /* might point to a username */
-                      char **passwordp,
-                      const char *netrcfile)
+static NETRCcode parsenetrc(struct store_netrc *store,
+                            const char *host,
+                            char **loginp, /* might point to a username */
+                            char **passwordp,
+                            const char *netrcfile)
 {
-  int retcode = NETRC_FILE_MISSING;
+  NETRCcode retcode = NETRC_NO_MATCH;
   char *login = *loginp;
   char *password = NULL;
   bool specific_login = !!login; /* points to something */
@@ -120,8 +125,9 @@ static int parsenetrc(struct store_netrc *store,
   Curl_dyn_init(&token, MAX_NETRC_TOKEN);
 
   if(!store->loaded) {
-    if(file2memory(netrcfile, filebuf))
-      return NETRC_FAILED;
+    NETRCcode ret = file2memory(netrcfile, filebuf);
+    if(ret)
+      return ret;
     store->loaded = TRUE;
   }
 
@@ -151,12 +157,18 @@ static int parsenetrc(struct store_netrc *store,
       tok_end = tok;
       if(!quoted) {
         size_t len = 0;
+        CURLcode result;
         while(!ISSPACE(*tok_end)) {
           tok_end++;
           len++;
         }
-        if(!len || Curl_dyn_addn(&token, tok, len)) {
-          retcode = NETRC_FAILED;
+        if(!len) {
+          retcode = NETRC_SYNTAX_ERROR;
+          goto out;
+        }
+        result = Curl_dyn_addn(&token, tok, len);
+        if(result) {
+          retcode = curl2netrc(result);
           goto out;
         }
       }
@@ -165,6 +177,7 @@ static int parsenetrc(struct store_netrc *store,
         bool endquote = FALSE;
         tok_end++; /* pass the leading quote */
         while(*tok_end) {
+          CURLcode result;
           char s = *tok_end;
           if(escape) {
             escape = FALSE;
@@ -190,15 +203,16 @@ static int parsenetrc(struct store_netrc *store,
             endquote = TRUE;
             break;
           }
-          if(Curl_dyn_addn(&token, &s, 1)) {
-            retcode = NETRC_FAILED;
+          result = Curl_dyn_addn(&token, &s, 1);
+          if(result) {
+            retcode = curl2netrc(result);
             goto out;
           }
           tok_end++;
         }
         if(escape || !endquote) {
           /* bad syntax, get out */
-          retcode = NETRC_FAILED;
+          retcode = NETRC_SYNTAX_ERROR;
           goto out;
         }
       }
@@ -226,7 +240,7 @@ static int parsenetrc(struct store_netrc *store,
         }
         else if(strcasecompare("default", tok)) {
           state = HOSTVALID;
-          retcode = NETRC_SUCCESS; /* we did find our host */
+          retcode = NETRC_OK; /* we did find our host */
         }
         break;
       case MACDEF:
@@ -237,7 +251,7 @@ static int parsenetrc(struct store_netrc *store,
         if(strcasecompare(host, tok)) {
           /* and yes, this is our host! */
           state = HOSTVALID;
-          retcode = NETRC_SUCCESS; /* we did find our host */
+          retcode = NETRC_OK; /* we did find our host */
         }
         else
           /* not our host */
@@ -253,7 +267,7 @@ static int parsenetrc(struct store_netrc *store,
             free(login);
             login = strdup(tok);
             if(!login) {
-              retcode = NETRC_FAILED; /* allocation failed */
+              retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */
               goto out;
             }
           }
@@ -264,7 +278,7 @@ static int parsenetrc(struct store_netrc *store,
           free(password);
           password = strdup(tok);
           if(!password) {
-            retcode = NETRC_FAILED; /* allocation failed */
+            retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */
             goto out;
           }
           if(!specific_login || our_login)
@@ -290,7 +304,7 @@ static int parsenetrc(struct store_netrc *store,
         }
         else if(strcasecompare("default", tok)) {
           state = HOSTVALID;
-          retcode = NETRC_SUCCESS; /* we did find our host */
+          retcode = NETRC_OK; /* we did find our host */
           Curl_safefree(password);
           if(!specific_login)
             Curl_safefree(login);
@@ -321,11 +335,11 @@ out:
       /* success without a password, set a blank one */
       password = strdup("");
       if(!password)
-        retcode = 1; /* out of memory */
+        retcode = NETRC_OUT_OF_MEMORY; /* out of memory */
     }
     else if(!login && !password)
       /* a default with no credentials */
-      retcode = NETRC_FILE_MISSING;
+      retcode = NETRC_NO_MATCH;
   }
   if(!retcode) {
     /* success */
@@ -343,17 +357,34 @@ out:
   return retcode;
 }
 
+const char *Curl_netrc_strerror(NETRCcode ret)
+{
+  switch(ret) {
+  default:
+    return ""; /* not a legit error */
+  case NETRC_FILE_MISSING:
+    return "no such file";
+  case NETRC_NO_MATCH:
+    return "no matching entry";
+  case NETRC_OUT_OF_MEMORY:
+    return "out of memory";
+  case NETRC_SYNTAX_ERROR:
+    return "syntax error";
+  }
+  /* never reached */
+}
+
 /*
  * @unittest: 1304
  *
  * *loginp and *passwordp MUST be allocated if they are not NULL when passed
  * in.
  */
-int Curl_parsenetrc(struct store_netrc *store, const char *host,
-                    char **loginp, char **passwordp,
-                    char *netrcfile)
+NETRCcode Curl_parsenetrc(struct store_netrc *store, const char *host,
+                          char **loginp, char **passwordp,
+                          char *netrcfile)
 {
-  int retcode = 1;
+  NETRCcode retcode = NETRC_OK;
   char *filealloc = NULL;
 
   if(!netrcfile) {
@@ -391,23 +422,23 @@ int Curl_parsenetrc(struct store_netrc *store, const char *host,
     }
 
     if(!home)
-      return retcode; /* no home directory found (or possibly out of
-                         memory) */
+      return NETRC_FILE_MISSING; /* no home directory found (or possibly out
+                                    of memory) */
 
     filealloc = aprintf("%s%s.netrc", home, DIR_CHAR);
     if(!filealloc) {
       free(homea);
-      return -1;
+      return NETRC_OUT_OF_MEMORY;
     }
     retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
     free(filealloc);
 #ifdef _WIN32
-    if((retcode == NETRC_FILE_MISSING) || (retcode == NETRC_FAILED)) {
+    if(retcode == NETRC_FILE_MISSING) {
       /* fallback to the old-style "_netrc" file */
       filealloc = aprintf("%s%s_netrc", home, DIR_CHAR);
       if(!filealloc) {
         free(homea);
-        return -1;
+        return NETRC_OUT_OF_MEMORY;
       }
       retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
       free(filealloc);

+ 12 - 3
Utilities/cmcurl/lib/netrc.h

@@ -34,12 +34,21 @@ struct store_netrc {
   BIT(loaded);
 };
 
+typedef enum {
+  NETRC_OK,
+  NETRC_NO_MATCH,      /* no matching entry in the file */
+  NETRC_SYNTAX_ERROR,  /* in the netrc file */
+  NETRC_FILE_MISSING,  /* the netrc file does not exist */
+  NETRC_OUT_OF_MEMORY, /* while parsing netrc */
+  NETRC_LAST /* never used */
+} NETRCcode;
+
+const char *Curl_netrc_strerror(NETRCcode ret);
 void Curl_netrc_init(struct store_netrc *s);
 void Curl_netrc_cleanup(struct store_netrc *s);
 
-/* returns -1 on failure, 0 if the host is found, 1 is the host is not found */
-int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
-                    char **passwordp, char *filename);
+NETRCcode Curl_parsenetrc(struct store_netrc *s, const char *host,
+                          char **loginp, char **passwordp, 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.

+ 27 - 41
Utilities/cmcurl/lib/pop3.c

@@ -83,10 +83,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 /* Local API functions */
 static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
 static CURLcode pop3_do(struct Curl_easy *data, bool *done);
@@ -192,19 +188,6 @@ static const struct SASLproto saslpop3 = {
   SASL_FLAG_BASE64      /* Configuration flags */
 };
 
-#ifdef USE_SSL
-static void pop3_to_pop3s(struct connectdata *conn)
-{
-  /* Change the connection handler */
-  conn->handler = &Curl_handler_pop3s;
-
-  /* Set the connection's upgraded to TLS flag */
-  conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define pop3_to_pop3s(x) Curl_nop_stmt
-#endif
-
 struct pop3_cmd {
   const char *name;
   unsigned short nlen;
@@ -239,7 +222,7 @@ static const struct pop3_cmd pop3cmds[] = {
 static bool pop3_is_multiline(const char *cmdline)
 {
   size_t i;
-  for(i = 0; i < ARRAYSIZE(pop3cmds); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(pop3cmds); ++i) {
     if(strncasecompare(pop3cmds[i].name, cmdline, pop3cmds[i].nlen)) {
       if(!cmdline[pop3cmds[i].nlen])
         return pop3cmds[i].multiline;
@@ -425,6 +408,7 @@ static CURLcode pop3_perform_starttls(struct Curl_easy *data,
 static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
                                          struct connectdata *conn)
 {
+#ifdef USE_SSL
   /* Start the SSL connection */
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   CURLcode result;
@@ -434,22 +418,27 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
     if(result)
       goto out;
+    /* Change the connection handler */
+    conn->handler = &Curl_handler_pop3s;
+    conn->bits.tls_upgraded = TRUE;
   }
 
+  DEBUGASSERT(!pop3c->ssldone);
   result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-
-  if(!result) {
+  DEBUGF(infof(data, "pop3_perform_upgrade_tls, connect -> %d, %d",
+         result, ssldone));
+  if(!result && ssldone) {
     pop3c->ssldone = ssldone;
-    if(pop3c->state != POP3_UPGRADETLS)
-      pop3_state(data, POP3_UPGRADETLS);
-
-    if(pop3c->ssldone) {
-      pop3_to_pop3s(conn);
-      result = pop3_perform_capa(data, conn);
-    }
+     /* perform CAPA now, changes pop3c->state out of POP3_UPGRADETLS */
+    result = pop3_perform_capa(data, conn);
   }
 out:
   return result;
+#else
+  (void)data;
+  (void)conn;
+  return CURLE_NOT_BUILT_IN;
+#endif
 }
 
 /***********************************************************************
@@ -861,7 +850,7 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
       result = pop3_perform_authentication(data, conn);
   }
   else
-    result = pop3_perform_upgrade_tls(data, conn);
+    pop3_state(data, POP3_UPGRADETLS);
 
   return result;
 }
@@ -1039,8 +1028,12 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
   (void)data;
 
   /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
-  if(pop3c->state == POP3_UPGRADETLS)
-    return pop3_perform_upgrade_tls(data, conn);
+upgrade_tls:
+  if(pop3c->state == POP3_UPGRADETLS) {
+    result = pop3_perform_upgrade_tls(data, conn);
+    if(result || (pop3c->state == POP3_UPGRADETLS))
+      return result;
+  }
 
   /* Flush any data that needs to be sent */
   if(pp->sendleft)
@@ -1067,6 +1060,10 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
 
     case POP3_STARTTLS:
       result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
+      /* During UPGRADETLS, leave the read loop as we need to connect
+       * (e.g. TLS handshake) before we continue sending/receiving. */
+      if(!result && (pop3c->state == POP3_UPGRADETLS))
+        goto upgrade_tls;
       break;
 
     case POP3_AUTH:
@@ -1112,17 +1109,6 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
   struct connectdata *conn = data->conn;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
 
-  /* Issue #16166, STLS seems to stall and time out. Revert to previous
-   * check, but it remains to find out why this is wrong. */
-  /* if(Curl_conn_is_ssl(conn, FIRSTSOCKET) && !pop3c->ssldone) { */
-  if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
-    bool ssldone = FALSE;
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-    pop3c->ssldone = ssldone;
-    if(result || !pop3c->ssldone)
-      return result;
-  }
-
   result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
   *done = (pop3c->state == POP3_STOP);
 

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

@@ -601,8 +601,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
     switch(arg) {
     case CURL_HTTP_VERSION_NONE:
 #ifdef USE_HTTP2
-      /* TODO: this seems an undesirable quirk to force a behaviour on
-       * lower implementations that they should recognize independently? */
+      /* This seems an undesirable quirk to force a behaviour on lower
+       * implementations that they should recognize independently? */
       arg = CURL_HTTP_VERSION_2TLS;
 #endif
       /* accepted */
@@ -1584,10 +1584,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
       if(data->share->hsts == data->hsts)
         data->hsts = NULL;
 #endif
-#ifdef USE_SSL
-      if(data->share->ssl_scache == data->state.ssl_scache)
-        data->state.ssl_scache = data->multi ? data->multi->ssl_scache : NULL;
-#endif
 #ifdef USE_LIBPSL
       if(data->psl == &data->share->psl)
         data->psl = data->multi ? &data->multi->psl : NULL;
@@ -1628,10 +1624,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
         data->hsts = data->share->hsts;
       }
 #endif
-#ifdef USE_SSL
-      if(data->share->ssl_scache)
-        data->state.ssl_scache = data->share->ssl_scache;
-#endif
 #ifdef USE_LIBPSL
       if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
         data->psl = &data->share->psl;
@@ -2425,6 +2417,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
      */
     return Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], ptr);
 
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
     /*
      * Option to allow for the MD5 of the host public key to be checked
@@ -2437,7 +2430,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
      * Store the filename to read known hosts from.
      */
     return Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], ptr);
-
+#endif
   case CURLOPT_SSH_KEYDATA:
     /*
      * Custom client data to pass to the SSH keyfunc callback

+ 9 - 0
Utilities/cmcurl/lib/smb.c

@@ -881,7 +881,16 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
       return CURLE_COULDNT_CONNECT;
     }
     nrsp = msg;
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic push
+/* error: 'memcpy' offset [74, 80] from the object at '<unknown>' is out of
+   the bounds of referenced subobject 'bytes' with type 'char[1]' */
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
     memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic pop
+#endif
     smbc->session_key = smb_swap32(nrsp->session_key);
     result = smb_send_setup(data);
     if(result) {

+ 21 - 32
Utilities/cmcurl/lib/smtp.c

@@ -189,19 +189,6 @@ static const struct SASLproto saslsmtp = {
   SASL_FLAG_BASE64      /* Configuration flags */
 };
 
-#ifdef USE_SSL
-static void smtp_to_smtps(struct connectdata *conn)
-{
-  /* Change the connection handler */
-  conn->handler = &Curl_handler_smtps;
-
-  /* Set the connection's upgraded to TLS flag */
-  conn->bits.tls_upgraded = TRUE;
-}
-#else
-#define smtp_to_smtps(x) Curl_nop_stmt
-#endif
-
 /***********************************************************************
  *
  * smtp_endofresp()
@@ -396,31 +383,38 @@ static CURLcode smtp_perform_starttls(struct Curl_easy *data,
  */
 static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
 {
+#ifdef USE_SSL
   /* Start the SSL connection */
   struct connectdata *conn = data->conn;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
   CURLcode result;
   bool ssldone = FALSE;
 
+  DEBUGASSERT(smtpc->state == SMTP_UPGRADETLS);
   if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
     if(result)
       goto out;
+    /* Change the connection handler and SMTP state */
+    conn->handler = &Curl_handler_smtps;
+    conn->bits.tls_upgraded = TRUE;
   }
 
+  DEBUGASSERT(!smtpc->ssldone);
   result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-  if(!result) {
+  DEBUGF(infof(data, "smtp_perform_upgrade_tls, connect -> %d, %d",
+           result, ssldone));
+  if(!result && ssldone) {
     smtpc->ssldone = ssldone;
-    if(smtpc->state != SMTP_UPGRADETLS)
-      smtp_state(data, SMTP_UPGRADETLS);
-
-    if(smtpc->ssldone) {
-      smtp_to_smtps(conn);
-      result = smtp_perform_ehlo(data);
-    }
+    /* perform EHLO now, changes smpt->state out of SMTP_UPGRADETLS */
+    result = smtp_perform_ehlo(data);
   }
 out:
   return result;
+#else
+  (void)data;
+  return CURLE_NOT_BUILT_IN;
+#endif
 }
 
 /***********************************************************************
@@ -875,7 +869,7 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
       result = smtp_perform_authentication(data);
   }
   else
-    result = smtp_perform_upgrade_tls(data);
+    smtp_state(data, SMTP_UPGRADETLS);
 
   return result;
 }
@@ -1204,8 +1198,11 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
 
   /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
 upgrade_tls:
-  if(smtpc->state == SMTP_UPGRADETLS)
-    return smtp_perform_upgrade_tls(data);
+  if(smtpc->state == SMTP_UPGRADETLS) {
+    result = smtp_perform_upgrade_tls(data);
+    if(result || (smtpc->state == SMTP_UPGRADETLS))
+      return result;
+  }
 
   /* Flush any data that needs to be sent */
   if(pp->sendleft)
@@ -1288,14 +1285,6 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
   struct connectdata *conn = data->conn;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
 
-  if(Curl_conn_is_ssl(conn, FIRSTSOCKET) && !smtpc->ssldone) {
-    bool ssldone = FALSE;
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
-    smtpc->ssldone = ssldone;
-    if(result || !smtpc->ssldone)
-      return result;
-  }
-
   result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
   *done = (smtpc->state == SMTP_STOP);
 

+ 4 - 12
Utilities/cmcurl/lib/telnet.c

@@ -777,22 +777,15 @@ static void printsub(struct Curl_easy *data,
   }
 }
 
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4706) /* assignment within conditional expression */
-#endif
 static bool str_is_nonascii(const char *str)
 {
   char c;
-  while((c = *str++))
+  while((c = *str++) != 0)
     if(c & 0x80)
       return TRUE;
 
   return FALSE;
 }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
 
 static CURLcode check_telnet_options(struct Curl_easy *data)
 {
@@ -1559,10 +1552,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
         /* returned not-zero, this an error */
         if(result) {
           keepon = FALSE;
-          /* TODO: in test 1452, macOS sees a ECONNRESET sometimes?
-           * Is this the telnet test server not shutting down the socket
-           * in a clean way? Seems to be timing related, happens more
-           * on slow debug build */
+          /* In test 1452, macOS sees a ECONNRESET sometimes? Is this the
+           * telnet test server not shutting down the socket in a clean way?
+           * Seems to be timing related, happens more on slow debug build */
           if(data->state.os_errno == ECONNRESET) {
             DEBUGF(infof(data, "telnet_do, unexpected ECONNRESET on recv"));
           }

+ 0 - 6
Utilities/cmcurl/lib/transfer.c

@@ -567,12 +567,6 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 #endif
   data->state.httpreq = data->set.method;
 
-#ifdef USE_SSL
-  if(!data->state.ssl_scache)
-    /* There was no ssl session cache set via a share, use the multi one */
-    data->state.ssl_scache = data->multi->ssl_scache;
-#endif
-
   data->state.requests = 0;
   data->state.followlocation = 0; /* reset the location-follow counter */
   data->state.this_is_a_follow = FALSE; /* reset this */

+ 12 - 16
Utilities/cmcurl/lib/url.c

@@ -125,10 +125,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #ifdef USE_NGHTTP2
 static void data_priority_cleanup(struct Curl_easy *data);
 #else
@@ -566,7 +562,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
 
   DEBUGASSERT(conn);
 
-  for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+  for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
     Curl_conn_cf_discard_all(data, conn, (int)i);
   }
 
@@ -2690,7 +2686,6 @@ static CURLcode override_login(struct Curl_easy *data,
   }
   conn->bits.netrc = FALSE;
   if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
-    int ret;
     bool url_provided = FALSE;
 
     if(data->state.aptr.user &&
@@ -2702,17 +2697,19 @@ static CURLcode override_login(struct Curl_easy *data,
     }
 
     if(!*passwdp) {
-      ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
-                            userp, passwdp,
-                            data->set.str[STRING_NETRC_FILE]);
-      if(ret > 0) {
+      NETRCcode ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
+                                      userp, passwdp,
+                                      data->set.str[STRING_NETRC_FILE]);
+      if(ret && ((ret == NETRC_NO_MATCH) ||
+                 (data->set.use_netrc == CURL_NETRC_OPTIONAL))) {
         infof(data, "Couldn't find host %s in the %s file; using defaults",
               conn->host.name,
               (data->set.str[STRING_NETRC_FILE] ?
                data->set.str[STRING_NETRC_FILE] : ".netrc"));
       }
-      else if(ret < 0) {
-        failf(data, ".netrc parser error");
+      else if(ret) {
+        const char *m = Curl_netrc_strerror(ret);
+        failf(data, ".netrc error: %s", m);
         return CURLE_READ_ERROR;
       }
       else {
@@ -3105,7 +3102,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     DEBUGF(infof(data, "check Alt-Svc for host %s", host));
     if(srcalpnid == ALPN_none) {
       /* scan all alt-svc protocol ids in order or relevance */
-      for(i = 0; !hit && (i < ARRAYSIZE(alpn_ids)); ++i) {
+      for(i = 0; !hit && (i < CURL_ARRAYSIZE(alpn_ids)); ++i) {
         srcalpnid = alpn_ids[i];
         hit = Curl_altsvc_lookup(data->asi,
                                  srcalpnid, host, conn->remote_port, /* from */
@@ -3215,7 +3212,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
 #endif
 
   if(unix_path) {
-    /* TODO, this only works if previous transport is TRNSPRT_TCP. Check it? */
+    /* This only works if previous transport is TRNSPRT_TCP. Check it? */
     conn->transport = TRNSPRT_UNIX;
     return resolve_unix(data, conn, unix_path);
   }
@@ -3313,7 +3310,7 @@ static void reuse_conn(struct Curl_easy *data,
    *   We want to reuse an existing conn to the remote endpoint.
    * Since connection reuse does not match on conn->host necessarily, we
    * switch `existing` conn to `temp` conn's host settings.
-   * TODO: is this correct in the case of TLS connections that have
+   *       Is this correct in the case of TLS connections that have
    *       used the original hostname in SNI to negotiate? Do we send
    *       requests for another host through the different SNI?
    */
@@ -3573,7 +3570,6 @@ static CURLcode create_conn(struct Curl_easy *data,
   if(result)
     goto out;
 
-  /* FIXME: do we really want to run this every time we add a transfer? */
   Curl_cpool_prune_dead(data);
 
   /*************************************************************

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

@@ -395,7 +395,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
 
   /* We will now try to extract the
    * possible login information in a string like:
-   * ftp://user:password@ftp.my.site:8021/README */
+   * ftp://user:[email protected]e.example:8021/README */
   ptr++;
 
   /* if this is a known scheme, get some details */

+ 0 - 2
Utilities/cmcurl/lib/urldata.h

@@ -1108,7 +1108,6 @@ struct Curl_data_prio_node {
 /**
  * Priority information for an easy handle in relation to others
  * on the same connection.
- * TODO: we need to adapt it to the new priority scheme as defined in RFC 9218
  */
 struct Curl_data_priority {
 #ifdef USE_NGHTTP2
@@ -1199,7 +1198,6 @@ struct UrlState {
   curl_prot_t first_remote_protocol;
 
   int retrycount; /* number of retries on a new connection */
-  struct Curl_ssl_scache *ssl_scache; /* TLS session pool */
   int os_errno;  /* filled in with errno whenever an error occurs */
   long followlocation; /* redirect counter */
   int requests; /* request counter: redirects + authentication retakes */

+ 9 - 9
Utilities/cmcurl/lib/vquic/curl_msh3.c

@@ -441,10 +441,10 @@ static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
   CURLcode result;
   bool rv = FALSE;
 
-  /* TODO: we would like to limit the amount of data we are buffer here.
-   * There seems to be no mechanism in msh3 to adjust flow control and
-   * it is undocumented what happens if we return FALSE here or less
-   * length (buflen is an inout parameter).
+  /* We would like to limit the amount of data we are buffer here. There seems
+   * to be no mechanism in msh3 to adjust flow control and it is undocumented
+   * what happens if we return FALSE here or less length (buflen is an inout
+   * parameter).
    */
   (void)Request;
   if(!stream)
@@ -703,8 +703,8 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
       goto out;
     }
 
-    /* TODO - msh3/msquic will hold onto this memory until the send complete
-       event. How do we make sure curl does not free it until then? */
+    /* msh3/msquic will hold onto this memory until the send complete event.
+       How do we make sure curl does not free it until then? */
     *err = CURLE_OK;
     nwritten = len;
   }
@@ -838,7 +838,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
   MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
 
   if(verify && (conn_config->CAfile || conn_config->CApath)) {
-    /* TODO: need a way to provide trust anchors to MSH3 */
+    /* Need a way to provide trust anchors to MSH3 */
 #ifdef DEBUGBUILD
     /* we need this for our test cases to run */
     CURL_TRC_CF(data, cf, "non-standard CA not supported, "
@@ -1006,7 +1006,7 @@ static CURLcode cf_msh3_query(struct Curl_cfilter *cf,
 
   switch(query) {
   case CF_QUERY_MAX_CONCURRENT: {
-    /* TODO: we do not have access to this so far, fake it */
+    /* We do not have access to this so far, fake it */
     (void)ctx;
     *pres1 = 100;
     return CURLE_OK;
@@ -1091,7 +1091,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
 
   (void)data;
   (void)conn;
-  (void)ai; /* TODO: msh3 resolves itself? */
+  (void)ai; /* msh3 resolves itself? */
   ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;

+ 4 - 4
Utilities/cmcurl/lib/vquic/curl_ngtcp2.c

@@ -394,7 +394,7 @@ static void quic_printf(void *user_data, const char *fmt, ...)
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
 
-  (void)ctx;  /* TODO: need an easy handle to infof() message */
+  (void)ctx;  /* need an easy handle to infof() message */
   va_list ap;
   va_start(ap, fmt);
   vfprintf(stderr, fmt, ap);
@@ -1591,7 +1591,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   if(ctx->tls_vrfy_result)
     return ctx->tls_vrfy_result;
 
-  (void)eos; /* TODO: use for stream EOF and block handling */
+  (void)eos; /* use for stream EOF and block handling */
   result = cf_progress_ingress(cf, data, &pktx);
   if(result) {
     *err = result;
@@ -1965,8 +1965,8 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
                               bool pause)
 {
-  /* TODO: there seems right now no API in ngtcp2 to shrink/enlarge
-   * the streams windows. As we do in HTTP/2. */
+  /* There seems to exist no API in ngtcp2 to shrink/enlarge the streams
+   * windows. As we do in HTTP/2. */
   if(!pause) {
     h3_drain_stream(cf, data);
     Curl_expire(data, 0, EXPIRE_RUN_NOW);

+ 3 - 7
Utilities/cmcurl/lib/vquic/curl_osslq.c

@@ -82,10 +82,6 @@
 #define H3_STREAM_SEND_CHUNKS \
           (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
 typedef uint32_t sslerr_t;
 #else
@@ -458,7 +454,7 @@ static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3,
   struct cf_osslq_ctx *ctx = cf->ctx;
   curl_int64_t stream_id = (curl_int64_t)SSL_get_stream_id(stream_ssl);
 
-  if(h3->remote_ctrl_n >= ARRAYSIZE(h3->remote_ctrl)) {
+  if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) {
     /* rejected, we are full */
     CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] rejecting remote stream",
                 stream_id);
@@ -1564,7 +1560,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf,
     bool blocked = FALSE, eos_written = FALSE;
 
     n = nghttp3_conn_writev_stream(ctx->h3.conn, &stream_id, &eos,
-                                   vec, ARRAYSIZE(vec));
+                                   vec, CURL_ARRAYSIZE(vec));
     if(n < 0) {
       failf(data, "nghttp3_conn_writev_stream returned error: %s",
             nghttp3_strerror((int)n));
@@ -1984,7 +1980,7 @@ static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   ssize_t nwritten;
   CURLcode result;
 
-  (void)eos; /* TODO: use to end stream */
+  (void)eos; /* use to end stream */
   CF_DATA_SAVE(save, cf, data);
   DEBUGASSERT(cf->connected);
   DEBUGASSERT(ctx->tls.ossl.ssl);

+ 4 - 4
Utilities/cmcurl/lib/vquic/curl_quiche.c

@@ -926,8 +926,8 @@ static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
   nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id,
                                  (uint8_t *)buf, len, eos);
   if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) {
-    /* TODO: we seem to be blocked on flow control and should HOLD
-     * sending. But when do we open again? */
+    /* Blocked on flow control and should HOLD sending. But when do we open
+     * again? */
     if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
       CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
                   "-> window exhausted", stream->id, len);
@@ -1204,8 +1204,8 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
                               bool pause)
 {
-  /* TODO: there seems right now no API in quiche to shrink/enlarge
-   * the streams windows. As we do in HTTP/2. */
+  /* There seems to exist no API in quiche to shrink/enlarge the streams
+   * windows. As we do in HTTP/2. */
   if(!pause) {
     h3_drain_stream(cf, data);
     Curl_expire(data, 0, EXPIRE_RUN_NOW);

+ 0 - 4
Utilities/cmcurl/lib/vquic/vquic-tls.c

@@ -58,10 +58,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #if defined(USE_WOLFSSL)
 
 #define QUIC_CIPHERS                                                          \

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

@@ -163,7 +163,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
     case EIO:
       if(pktlen > gsolen) {
         /* GSO failure */
-        failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
+        infof(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
               SOCKERRNO);
         qctx->no_gso = TRUE;
         return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);

+ 2 - 35
Utilities/cmcurl/lib/vssh/libssh.c

@@ -342,17 +342,11 @@ static int myssh_is_known(struct Curl_easy *data)
   struct curl_khkey *knownkeyp = NULL;
   curl_sshkeycallback func =
     data->set.ssh_keyfunc;
-
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
   struct ssh_knownhosts_entry *knownhostsentry = NULL;
   struct curl_khkey knownkey;
-#endif
 
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
   rc = ssh_get_server_publickey(sshc->ssh_session, &pubkey);
-#else
-  rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
-#endif
+
   if(rc != SSH_OK)
     return rc;
 
@@ -388,7 +382,6 @@ static int myssh_is_known(struct Curl_easy *data)
 
   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
 
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
     /* Get the known_key from the known hosts file */
     vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
                                                &knownhostsentry);
@@ -446,22 +439,6 @@ static int myssh_is_known(struct Curl_easy *data)
       break;
     }
 
-#else
-    vstate = ssh_is_server_known(sshc->ssh_session);
-    switch(vstate) {
-    case SSH_SERVER_KNOWN_OK:
-      keymatch = CURLKHMATCH_OK;
-      break;
-    case SSH_SERVER_FILE_NOT_FOUND:
-    case SSH_SERVER_NOT_KNOWN:
-      keymatch = CURLKHMATCH_MISSING;
-      break;
-    default:
-      keymatch = CURLKHMATCH_MISMATCH;
-      break;
-    }
-#endif
-
     if(func) { /* use callback to determine action */
       rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
       if(rc != SSH_OK)
@@ -478,18 +455,14 @@ static int myssh_is_known(struct Curl_easy *data)
         foundkey.keytype = CURLKHTYPE_RSA1;
         break;
       case SSH_KEYTYPE_ECDSA:
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
       case SSH_KEYTYPE_ECDSA_P256:
       case SSH_KEYTYPE_ECDSA_P384:
       case SSH_KEYTYPE_ECDSA_P521:
-#endif
         foundkey.keytype = CURLKHTYPE_ECDSA;
         break;
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
       case SSH_KEYTYPE_ED25519:
         foundkey.keytype = CURLKHTYPE_ED25519;
         break;
-#endif
       case SSH_KEYTYPE_DSS:
         foundkey.keytype = CURLKHTYPE_DSS;
         break;
@@ -506,11 +479,7 @@ static int myssh_is_known(struct Curl_easy *data)
 
       switch(rc) {
       case CURLKHSTAT_FINE_ADD_TO_FILE:
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
         rc = ssh_session_update_known_hosts(sshc->ssh_session);
-#else
-        rc = ssh_write_knownhost(sshc->ssh_session);
-#endif
         if(rc != SSH_OK) {
           goto cleanup;
         }
@@ -541,11 +510,9 @@ cleanup:
   if(hash)
     ssh_clean_pubkey_hash(&hash);
   ssh_key_free(pubkey);
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
   if(knownhostsentry) {
     ssh_knownhosts_entry_free(knownhostsentry);
   }
-#endif
   return rc;
 }
 
@@ -1848,7 +1815,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       }
 
       rc = ssh_scp_push_file(sshc->scp_session, protop->path,
-                             data->state.infilesize,
+                             (size_t)data->state.infilesize,
                              (int)data->set.new_file_perms);
       if(rc != SSH_OK) {
         err_msg = ssh_get_error(sshc->ssh_session);

+ 21 - 101
Utilities/cmcurl/lib/vssh/libssh2.c

@@ -83,15 +83,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#if LIBSSH2_VERSION_NUM >= 0x010206
-/* libssh2_sftp_statvfs and friends were added in 1.2.6 */
-#define HAS_STATVFS_SUPPORT 1
-#endif
-
-#define sftp_libssh2_realpath(s,p,t,m)                          \
-  libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)),    \
-                          (t), (m), LIBSSH2_SFTP_REALPATH)
-
 /* Local functions: */
 static const char *sftp_libssh2_strerror(unsigned long err);
 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
@@ -389,8 +380,6 @@ static void state(struct Curl_easy *data, sshstate nowstate)
   sshc->state = nowstate;
 }
 
-
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
 static int sshkeycallback(CURL *easy,
                           const struct curl_khkey *knownkey, /* known */
                           const struct curl_khkey *foundkey, /* found */
@@ -405,37 +394,7 @@ static int sshkeycallback(CURL *easy,
   /* we only allow perfect matches, and we reject everything else */
   return (match != CURLKHMATCH_OK) ? CURLKHSTAT_REJECT : CURLKHSTAT_FINE;
 }
-#endif
-
-/*
- * Earlier libssh2 versions did not have the ability to seek to 64-bit
- * positions with 32-bit size_t.
- */
-#ifdef HAVE_LIBSSH2_SFTP_SEEK64
-#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
-#else
-#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
-#endif
 
-/*
- * Earlier libssh2 versions did not do SCP properly beyond 32-bit sizes on
- * 32-bit architectures so we check of the necessary function is present.
- */
-#ifndef HAVE_LIBSSH2_SCP_SEND64
-#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
-#else
-#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c),            \
-                                             (libssh2_int64_t)d, 0, 0)
-#endif
-
-/*
- * libssh2 1.2.8 fixed the problem with 32-bit ints used for sockets on win64.
- */
-#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
-#define session_startup(x,y) libssh2_session_handshake(x, y)
-#else
-#define session_startup(x,y) libssh2_session_startup(x, (int)y)
-#endif
 static enum curl_khtype convert_ssh2_keytype(int sshkeytype)
 {
   enum curl_khtype keytype = CURLKHTYPE_UNKNOWN;
@@ -477,7 +436,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
   int rc = 0;
   CURLcode result = CURLE_OK;
 
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
     /* we are asked to verify the host against a file */
     struct connectdata *conn = data->conn;
@@ -537,7 +495,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
         /* no check means failure! */
         rc = CURLKHSTAT_REJECT;
       else {
-#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
         keycheck = libssh2_knownhost_checkp(sshc->kh,
                                             conn->host.name,
                                             (conn->remote_port != PORT_SSH) ?
@@ -547,15 +504,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
                                             LIBSSH2_KNOWNHOST_KEYENC_RAW|
                                             keybit,
                                             &host);
-#else
-        keycheck = libssh2_knownhost_check(sshc->kh,
-                                           conn->host.name,
-                                           remotekey, keylen,
-                                           LIBSSH2_KNOWNHOST_TYPE_PLAIN|
-                                           LIBSSH2_KNOWNHOST_KEYENC_RAW|
-                                           keybit,
-                                           &host);
-#endif
 
         infof(data, "SSH host check: %d, key: %s", keycheck,
               (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) ?
@@ -639,9 +587,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
       break;
     }
   }
-#else /* HAVE_LIBSSH2_KNOWNHOST_API */
-  (void)data;
-#endif
   return result;
 }
 
@@ -819,8 +764,6 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
 {
   CURLcode result = CURLE_OK;
 
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
-
 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
   static const char * const hostkey_method_ssh_ed25519
     = "ssh-ed25519";
@@ -916,12 +859,10 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
         break;
 #endif
       case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
-#ifdef HAVE_LIBSSH2_VERSION
         if(libssh2_version(0x010900))
           /* since 1.9.0 libssh2_session_method_pref() works as expected */
           hostkey_method = hostkey_method_ssh_rsa_all;
         else
-#endif
           /* old libssh2 which cannot correctly remove unsupported methods due
            * to bug in src/kex.c or does not support the new methods anyways.
            */
@@ -956,8 +897,6 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
     }
   }
 
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
-
   return result;
 }
 
@@ -1094,12 +1033,10 @@ static CURLcode sftp_quote(struct Curl_easy *data,
     state(data, SSH_SFTP_QUOTE_UNLINK);
     return result;
   }
-#ifdef HAS_STATVFS_SUPPORT
   else if(strncasecompare(cmd, "statvfs ", 8)) {
     state(data, SSH_SFTP_QUOTE_STATVFS);
     return result;
   }
-#endif
 
   failf(data, "Unknown SFTP command");
   Curl_safefree(sshc->quote_path1);
@@ -1264,7 +1201,8 @@ sftp_upload_init(struct Curl_easy *data,
       Curl_pgrsSetUploadSize(data, data->state.infilesize);
     }
 
-    SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+    libssh2_sftp_seek64(sshc->sftp_handle,
+                        (libssh2_uint64_t)data->state.resume_from);
   }
   if(data->state.infilesize > 0) {
     data->req.size = data->state.infilesize;
@@ -1565,7 +1503,7 @@ sftp_download_stat(struct Curl_easy *data,
         size = to - from + 1;
       }
 
-      SFTP_SEEK(sshc->sftp_handle, from);
+      libssh2_sftp_seek64(sshc->sftp_handle, (libssh2_uint64_t)from);
     }
     data->req.size = size;
     data->req.maxdownload = size;
@@ -1598,7 +1536,8 @@ sftp_download_stat(struct Curl_easy *data,
     data->req.maxdownload = attrs.filesize - data->state.resume_from;
     Curl_pgrsSetDownloadSize(data,
                              attrs.filesize - data->state.resume_from);
-    SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+    libssh2_sftp_seek64(sshc->sftp_handle,
+                        (libssh2_uint64_t)data->state.resume_from);
   }
 
   /* Setup the actual download */
@@ -1670,10 +1609,10 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
       return result;
     }
   }
-  else if(rc == 0) {
+  else if(!rc) {
     state(data, SSH_SFTP_READDIR_DONE);
   }
-  else if(rc < 0) {
+  else {
     unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
     result = sftp_libssh2_error_to_CURLE(sftperr);
     sshc->actualcode = result ? result : CURLE_SSH;
@@ -1723,7 +1662,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       FALLTHROUGH();
 
     case SSH_S_STARTUP:
-      rc = session_startup(sshc->ssh_session, conn->sock[FIRSTSOCKET]);
+      rc = libssh2_session_handshake(sshc->ssh_session,
+                                     conn->sock[FIRSTSOCKET]);
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
@@ -1878,7 +1818,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       break;
 
     case SSH_AUTH_AGENT_INIT:
-#ifdef HAVE_LIBSSH2_AGENT_API
       if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
          && (strstr(sshc->authlist, "publickey") != NULL)) {
 
@@ -1908,12 +1847,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
         }
       }
       else
-#endif /* HAVE_LIBSSH2_AGENT_API */
         state(data, SSH_AUTH_KEY_INIT);
       break;
 
     case SSH_AUTH_AGENT_LIST:
-#ifdef HAVE_LIBSSH2_AGENT_API
       rc = libssh2_agent_list_identities(sshc->ssh_agent);
 
       if(rc == LIBSSH2_ERROR_EAGAIN)
@@ -1927,11 +1864,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
         state(data, SSH_AUTH_AGENT);
         sshc->sshagent_prev_identity = NULL;
       }
-#endif
       break;
 
     case SSH_AUTH_AGENT:
-#ifdef HAVE_LIBSSH2_AGENT_API
       /* as prev_identity evolves only after an identity user auth finished we
          can safely request it again as long as EAGAIN is returned here or by
          libssh2_agent_userauth */
@@ -1968,7 +1903,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
         state(data, SSH_AUTH_KEY_INIT);
         rc = 0; /* clear rc and continue */
       }
-#endif
       break;
 
     case SSH_AUTH_KEY_INIT:
@@ -2051,8 +1985,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       /*
        * Get the "home" directory
        */
-      rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
-                                 sshp->readdir_filename, CURL_PATH_MAX);
+      rc = libssh2_sftp_symlink_ex(sshc->sftp_session,
+                                   ".", curlx_uztoui(strlen(".")),
+                                   sshp->readdir_filename, CURL_PATH_MAX,
+                                   LIBSSH2_SFTP_REALPATH);
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
@@ -2288,7 +2224,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       state(data, SSH_SFTP_NEXT_QUOTE);
       break;
 
-#ifdef HAS_STATVFS_SUPPORT
     case SSH_SFTP_QUOTE_STATVFS:
     {
       LIBSSH2_SFTP_STATVFS statvfs;
@@ -2351,7 +2286,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       state(data, SSH_SFTP_NEXT_QUOTE);
       break;
     }
-#endif
+
     case SSH_SFTP_GETINFO:
     {
       if(data->set.get_filetime) {
@@ -2684,8 +2619,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
        * directory in the path.
        */
       sshc->ssh_channel =
-        SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
-                 data->state.infilesize);
+        libssh2_scp_send64(sshc->ssh_session, sshp->path,
+                           (int)data->set.new_file_perms,
+                           (libssh2_int64_t)data->state.infilesize, 0, 0);
       if(!sshc->ssh_channel) {
         int ssh_err;
         char *err_msg = NULL;
@@ -2920,14 +2856,11 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       break;
 
     case SSH_SESSION_FREE:
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
       if(sshc->kh) {
         libssh2_knownhost_free(sshc->kh);
         sshc->kh = NULL;
       }
-#endif
 
-#ifdef HAVE_LIBSSH2_AGENT_API
       if(sshc->ssh_agent) {
         rc = libssh2_agent_disconnect(sshc->ssh_agent);
         if(rc == LIBSSH2_ERROR_EAGAIN) {
@@ -2948,7 +2881,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
         sshc->sshagent_identity = NULL;
         sshc->sshagent_prev_identity = NULL;
       }
-#endif
 
       if(sshc->ssh_session) {
         rc = libssh2_session_free(sshc->ssh_session);
@@ -2970,12 +2902,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
       DEBUGASSERT(sshc->ssh_channel == NULL);
       DEBUGASSERT(sshc->sftp_session == NULL);
       DEBUGASSERT(sshc->sftp_handle == NULL);
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
       DEBUGASSERT(sshc->kh == NULL);
-#endif
-#ifdef HAVE_LIBSSH2_AGENT_API
       DEBUGASSERT(sshc->ssh_agent == NULL);
-#endif
 
       Curl_safefree(sshc->rsa_pub);
       Curl_safefree(sshc->rsa);
@@ -3325,14 +3253,11 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
     conn->send[FIRSTSOCKET] = sftp_send;
   }
 
-  if(data->set.ssh_compression) {
-#if LIBSSH2_VERSION_NUM >= 0x010208
-    if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
-#endif
-      infof(data, "Failed to enable compression for ssh session");
+  if(data->set.ssh_compression &&
+     libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) {
+    infof(data, "Failed to enable compression for ssh session");
   }
 
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
     int rc;
     sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
@@ -3350,7 +3275,6 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
       infof(data, "Failed to read known hosts from %s",
             data->set.str[STRING_SSH_KNOWNHOSTS]);
   }
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
 
 #ifdef CURL_LIBSSH2_DEBUG
   libssh2_trace(sshc->ssh_session, ~0);
@@ -3761,25 +3685,21 @@ static const char *sftp_libssh2_strerror(unsigned long err)
 
 CURLcode Curl_ssh_init(void)
 {
-#ifdef HAVE_LIBSSH2_INIT
   if(libssh2_init(0)) {
     DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
     return CURLE_FAILED_INIT;
   }
-#endif
   return CURLE_OK;
 }
 
 void Curl_ssh_cleanup(void)
 {
-#ifdef HAVE_LIBSSH2_EXIT
   (void)libssh2_exit();
-#endif
 }
 
 void Curl_ssh_version(char *buffer, size_t buflen)
 {
-  (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
+  (void)msnprintf(buffer, buflen, "libssh2/%s", libssh2_version(0));
 }
 
 /* The SSH session is associated with the *CONNECTION* but the callback user

+ 11 - 41
Utilities/cmcurl/lib/vssh/ssh.h

@@ -201,17 +201,10 @@ struct ssh_conn {
   Curl_send *tls_send;
 #endif
 
-#ifdef HAVE_LIBSSH2_AGENT_API
   LIBSSH2_AGENT *ssh_agent;     /* proxy to ssh-agent/pageant */
-  struct libssh2_agent_publickey *sshagent_identity,
-                                 *sshagent_prev_identity;
-#endif
-
-  /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
-     header */
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+  struct libssh2_agent_publickey *sshagent_identity;
+  struct libssh2_agent_publickey *sshagent_prev_identity;
   LIBSSH2_KNOWNHOSTS *kh;
-#endif
 #elif defined(USE_WOLFSSH)
   WOLFSSH *ssh_session;
   WOLFSSH_CTX *ctx;
@@ -221,43 +214,20 @@ struct ssh_conn {
 #endif /* USE_LIBSSH */
 };
 
-#if defined(USE_LIBSSH2)
-
-/* Feature detection based on version numbers to better work with
-   non-configure platforms */
-
-#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000)
-#  error "SCP/SFTP protocols require libssh2 0.16 or later"
+#ifdef USE_LIBSSH
+#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 9, 0)
+#  error "SCP/SFTP protocols require libssh 0.9.0 or later"
 #endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010000
-#define HAVE_LIBSSH2_SFTP_SEEK64 1
 #endif
 
-#if LIBSSH2_VERSION_NUM >= 0x010100
-#define HAVE_LIBSSH2_VERSION 1
-#endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010205
-#define HAVE_LIBSSH2_INIT 1
-#define HAVE_LIBSSH2_EXIT 1
-#endif
-
-#if LIBSSH2_VERSION_NUM >= 0x010206
-#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1
-#define HAVE_LIBSSH2_SCP_SEND64 1
-#endif
+#if defined(USE_LIBSSH2)
 
-#if LIBSSH2_VERSION_NUM >= 0x010208
-#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1
-#endif
+/* Feature detection based on version numbers to better work with
+   non-configure platforms */
 
-#ifdef HAVE_LIBSSH2_VERSION
-/* get it runtime if possible */
-#define CURL_LIBSSH2_VERSION libssh2_version(0)
-#else
-/* use build-time if runtime not possible */
-#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
+#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x010208)
+#  error "SCP/SFTP protocols require libssh2 1.2.8 or later"
+/* 1.2.8 was released on April 5 2011 */
 #endif
 
 #endif /* USE_LIBSSH2 */

+ 1 - 5
Utilities/cmcurl/lib/vtls/gtls.c

@@ -63,10 +63,6 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #define QUIC_PRIORITY \
   "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
   "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
@@ -1223,7 +1219,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
     size_t i, alen = alpn_len;
     unsigned char *salpn = (unsigned char *)alpn;
     unsigned char slen;
-    for(i = 0; (i < ARRAYSIZE(gtls_alpns)) && alen; ++i) {
+    for(i = 0; (i < CURL_ARRAYSIZE(gtls_alpns)) && alen; ++i) {
       slen = salpn[0];
       if(slen >= alen)
         return CURLE_FAILED_INIT;

+ 5 - 9
Utilities/cmcurl/lib/vtls/mbedtls.c

@@ -79,11 +79,8 @@
 #include "memdebug.h"
 
 /* ALPN for http2 */
-#ifdef USE_HTTP2
-#  undef HAS_ALPN
-#  ifdef MBEDTLS_SSL_ALPN
-#    define HAS_ALPN
-#  endif
+#if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN)
+#  define HAS_ALPN_MBEDTLS
 #endif
 
 struct mbed_ssl_backend_data {
@@ -97,7 +94,7 @@ struct mbed_ssl_backend_data {
 #endif
   mbedtls_pk_context pk;
   mbedtls_ssl_config config;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
   const char *protocols[3];
 #endif
   int *ciphersuites;
@@ -931,7 +928,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
   if(connssl->alpn) {
     struct alpn_proto_buf proto;
     size_t i;
@@ -1109,7 +1106,7 @@ pinnedpubkey_error:
     }
   }
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
   if(connssl->alpn) {
     const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
 
@@ -1636,7 +1633,6 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input,
                                   unsigned char *sha256sum,
                                   size_t sha256len UNUSED_PARAM)
 {
-  /* TODO: explain this for different mbedtls 2.x vs 3 version */
   (void)sha256len;
 #if MBEDTLS_VERSION_NUMBER < 0x02070000
   mbedtls_sha256(input, inputlen, sha256sum, 0);

+ 16 - 22
Utilities/cmcurl/lib/vtls/openssl.c

@@ -116,10 +116,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 /* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
    renegotiations when built with BoringSSL. Renegotiating is non-compliant
    with HTTP/2 and "an extremely dangerous protocol feature". Beware.
@@ -1313,7 +1309,9 @@ int cert_stuff(struct Curl_easy *data,
   if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE) ||
      (file_type == SSL_FILETYPE_PROVIDER)) {
     SSL *ssl;
-    X509 *x509;
+    X509 *x509 = NULL;
+    EVP_PKEY *pri = NULL;
+    STACK_OF(X509) *ca = NULL;
     int cert_done = 0;
     int cert_use_result;
 
@@ -1502,8 +1500,6 @@ int cert_stuff(struct Curl_easy *data,
     {
       BIO *cert_bio = NULL;
       PKCS12 *p12 = NULL;
-      EVP_PKEY *pri;
-      STACK_OF(X509) *ca = NULL;
       if(cert_blob) {
         cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len));
         if(!cert_bio) {
@@ -1544,8 +1540,7 @@ int cert_stuff(struct Curl_easy *data,
 
       PKCS12_PBE_add();
 
-      if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
-                       &ca)) {
+      if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) {
         failf(data,
               "could not parse PKCS12 file, check password, " OSSL_PACKAGE
               " error %s",
@@ -2067,8 +2062,6 @@ static CURLcode ossl_set_provider(struct Curl_easy *data, const char *provider)
                         sizeof(error_buffer)));
     /* Do not attempt to load it again */
     data->state.provider_failed = TRUE;
-    /* FIXME not the right error but much less fuss than creating a new
-     * public one */
     return CURLE_SSL_ENGINE_NOTFOUND;
   }
   data->state.provider = TRUE;
@@ -2884,10 +2877,9 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
 /* ====================================================== */
 
 /* Check for OpenSSL 1.0.2 which has ALPN support. */
-#undef HAS_ALPN
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L       \
   && !defined(OPENSSL_NO_TLSEXT)
-#  define HAS_ALPN 1
+#  define HAS_ALPN_OPENSSL
 #endif
 
 /* Check for OpenSSL 1.1.0 which has set_{min,max}_proto_version(). */
@@ -3381,7 +3373,7 @@ static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf,
         "CA"      /* Intermediate Certification Authorities */
       };
       size_t i;
-      for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+      for(i = 0; i < CURL_ARRAYSIZE(storeNames); ++i) {
         bool imported = FALSE;
         result = import_windows_cert_store(data, storeNames[i], store,
                                            &imported);
@@ -3692,7 +3684,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
   ctx_option_t ctx_options = 0;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
-  const long int ssl_version_min = conn_config->version;
+  unsigned int ssl_version_min = conn_config->version;
   char * const ssl_cert = ssl_config->primary.clientcert;
   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
   const char * const ssl_cert_type = ssl_config->cert_type;
@@ -3735,6 +3727,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
     }
     break;
   case TRNSPRT_QUIC:
+    ssl_version_min = CURL_SSLVERSION_TLSv1_3;
     if(conn_config->version_max &&
        (conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) {
       failf(data, "QUIC needs at least TLS version 1.3");
@@ -3875,7 +3868,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
 #endif
 
   if(alpn && alpn_len) {
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
     if(SSL_CTX_set_alpn_protos(octx->ssl_ctx, alpn, (int)alpn_len)) {
       failf(data, "Error setting ALPN");
       return CURLE_SSL_CONNECT_ERROR;
@@ -3898,7 +3891,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
   ciphers = conn_config->cipher_list;
   if(!ciphers && (peer->transport != TRNSPRT_QUIC))
     ciphers = DEFAULT_CIPHER_SELECTION;
-  if(ciphers) {
+  if(ciphers && (ssl_version_min < CURL_SSLVERSION_TLSv1_3)) {
     if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
       failf(data, "failed setting cipher list: %s", ciphers);
       return CURLE_SSL_CIPHER;
@@ -3909,7 +3902,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
 #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
   {
     const char *ciphers13 = conn_config->cipher_list13;
-    if(ciphers13) {
+    if(ciphers13 &&
+       (!conn_config->version_max ||
+        (conn_config->version_max >= CURL_SSLVERSION_MAX_TLSv1_3))) {
       if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) {
         failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
         return CURLE_SSL_CIPHER;
@@ -4213,7 +4208,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
   DEBUGASSERT(octx);
   memset(&proto, 0, sizeof(proto));
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
   if(connssl->alpn) {
     result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
     if(result) {
@@ -4250,7 +4245,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
   SSL_set_bio(octx->ssl, bio, bio);
 #endif
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
   if(connssl->alpn) {
     Curl_alpn_to_proto_str(&proto, connssl->alpn);
     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
@@ -4307,7 +4302,6 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
       servername_type = SSL_get_servername_type(ssl);
       inner = SSL_get_servername(ssl, servername_type);
       SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
-      /* TODO: get the inner from BoringSSL */
       infof(data, "ECH: retry_configs for %s from %s, %d %d",
             inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
 #endif
@@ -4562,7 +4556,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
 # endif  /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
 #endif  /* USE_ECH_OPENSSL */
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_OPENSSL
     /* Sets data and len to negotiated protocol, len is 0 if no protocol was
      * negotiated
      */

+ 7 - 8
Utilities/cmcurl/lib/vtls/schannel.c

@@ -77,7 +77,7 @@
    https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
 */
 #if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)
-#  define HAS_ALPN 1
+#  define HAS_ALPN_SCHANNEL
 #endif
 
 #ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
@@ -888,7 +888,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   SecBufferDesc outbuf_desc;
   SecBuffer inbuf;
   SecBufferDesc inbuf_desc;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
   unsigned char alpn_buffer[128];
 #endif
   SECURITY_STATUS sspi_status = SEC_E_OK;
@@ -908,7 +908,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
           "connect to some servers due to lack of SNI, algorithms, etc.");
   }
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
      Also it does not seem to be supported for WINE, see curl bug #983. */
   backend->use_alpn = connssl->alpn &&
@@ -991,7 +991,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     infof(data, "schannel: using IP address, SNI is not supported by OS.");
   }
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
   if(backend->use_alpn) {
     int cur = 0;
     int list_start_index = 0;
@@ -1039,7 +1039,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
     InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
   }
-#else /* HAS_ALPN */
+#else /* HAS_ALPN_SCHANNEL */
   InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
   InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
 #endif
@@ -1533,7 +1533,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
   CURLcode result = CURLE_OK;
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CERT_CONTEXT *ccert_context = NULL;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
   SecPkgContext_ApplicationProtocol alpn_result;
 #endif
 
@@ -1562,7 +1562,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_SCHANNEL
   if(backend->use_alpn) {
     sspi_status =
       Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle,
@@ -2367,7 +2367,6 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf,
       Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
       if(!result) {
         if(written < (ssize_t)outbuf.cbBuffer) {
-          /* TODO: handle partial sends */
           failf(data, "schannel: failed to send close msg: %s"
                 " (bytes written: %zd)", curl_easy_strerror(result), written);
           result = CURLE_SEND_ERROR;

+ 5 - 3
Utilities/cmcurl/lib/vtls/vtls.c

@@ -915,7 +915,9 @@ static int multissl_init(void)
 {
   if(multissl_setup(NULL))
     return 1;
-  return Curl_ssl->init();
+  if(Curl_ssl->init)
+    return Curl_ssl->init();
+  return 1;
 }
 
 static CURLcode multissl_connect(struct Curl_cfilter *cf,
@@ -1939,8 +1941,8 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
     else {
       *palpn = CURL_HTTP_VERSION_NONE;
       failf(data, "unsupported ALPN protocol: '%.*s'", (int)proto_len, proto);
-      /* TODO: do we want to fail this? Previous code just ignored it and
-       * some vtls backends even ignore the return code of this function. */
+      /* Previous code just ignored it and some vtls backends even ignore the
+       * return code of this function. */
       /* return CURLE_NOT_BUILT_IN; */
       goto out;
     }

+ 52 - 9
Utilities/cmcurl/lib/vtls/vtls_scache.c

@@ -75,13 +75,35 @@ struct Curl_ssl_scache_peer {
   BIT(hmac_set);           /* if key_salt and key_hmac are present */
 };
 
+#define CURL_SCACHE_MAGIC 0x000e1551
+
+#define GOOD_SCACHE(x) ((x) && (x)->magic == CURL_SCACHE_MAGIC)
+
 struct Curl_ssl_scache {
+  unsigned int magic;
   struct Curl_ssl_scache_peer *peers;
   size_t peer_count;
   int default_lifetime_secs;
   long age;
 };
 
+static struct Curl_ssl_scache *cf_ssl_scache_get(struct Curl_easy *data)
+{
+  struct Curl_ssl_scache *scache = NULL;
+  /* If a share is present, its ssl_scache has preference over the multi */
+  if(data->share && data->share->ssl_scache)
+    scache = data->share->ssl_scache;
+  else if(data->multi && data->multi->ssl_scache)
+    scache = data->multi->ssl_scache;
+  if(scache && !GOOD_SCACHE(scache)) {
+    failf(data, "transfer would use an invalid scache at %p, denied",
+          (void *)scache);
+    DEBUGASSERT(0);
+    return NULL;
+  }
+  return scache;
+}
+
 static void cf_ssl_scache_clear_session(struct Curl_ssl_session *s)
 {
   if(s->sdata) {
@@ -306,6 +328,7 @@ CURLcode Curl_ssl_scache_create(size_t max_peers,
     return CURLE_OUT_OF_MEMORY;
   }
 
+  scache->magic = CURL_SCACHE_MAGIC;
   scache->default_lifetime_secs = (24*60*60); /* 1 day */
   scache->peer_count = max_peers;
   scache->peers = peers;
@@ -322,8 +345,9 @@ CURLcode Curl_ssl_scache_create(size_t max_peers,
 
 void Curl_ssl_scache_destroy(struct Curl_ssl_scache *scache)
 {
-  if(scache) {
+  if(scache && GOOD_SCACHE(scache)) {
     size_t i;
+    scache->magic = 0;
     for(i = 0; i < scache->peer_count; ++i) {
       cf_ssl_scache_clear_peer(&scache->peers[i]);
     }
@@ -359,7 +383,7 @@ static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
     char abspath[_MAX_PATH];
     if(_fullpath(abspath, path, _MAX_PATH))
       return Curl_dyn_addf(buf, ":%s-%s", name, abspath);
-#else
+#elif defined(HAVE_REALPATH)
     if(path[0] != '/') {
       char *abspath = realpath(path, NULL);
       if(abspath) {
@@ -588,6 +612,13 @@ cf_ssl_find_peer_by_key(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
 
   *ppeer = NULL;
+  if(!GOOD_SCACHE(scache)) {
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  }
+
+  CURL_TRC_SSLS(data, "find peer slot for %s among %zu slots",
+                ssl_peer_key, scache->peer_count);
+
   /* check for entries with known peer_key */
   for(i = 0; scache && i < scache->peer_count; i++) {
     if(scache->peers[i].ssl_peer_key &&
@@ -792,7 +823,7 @@ CURLcode Curl_ssl_scache_put(struct Curl_cfilter *cf,
                              const char *ssl_peer_key,
                              struct Curl_ssl_session *s)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   CURLcode result;
   DEBUGASSERT(ssl_config);
@@ -801,6 +832,10 @@ CURLcode Curl_ssl_scache_put(struct Curl_cfilter *cf,
     Curl_ssl_session_destroy(s);
     return CURLE_OK;
   }
+  if(!GOOD_SCACHE(scache)) {
+    Curl_ssl_session_destroy(s);
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  }
 
   Curl_ssl_scache_lock(data);
   result = cf_scache_add_session(cf, data, scache, ssl_peer_key, s);
@@ -826,7 +861,7 @@ CURLcode Curl_ssl_scache_take(struct Curl_cfilter *cf,
                               const char *ssl_peer_key,
                               struct Curl_ssl_session **ps)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct Curl_ssl_scache_peer *peer = NULL;
   struct Curl_llist_node *n;
@@ -870,7 +905,7 @@ CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf,
                                  void *sobj,
                                  Curl_ssl_scache_obj_dtor *sobj_free)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct Curl_ssl_scache_peer *peer = NULL;
   CURLcode result;
@@ -878,6 +913,11 @@ CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf,
   DEBUGASSERT(sobj);
   DEBUGASSERT(sobj_free);
 
+  if(!scache) {
+    result = CURLE_BAD_FUNCTION_ARGUMENT;
+    goto out;
+  }
+
   result = cf_ssl_add_peer(data, scache, ssl_peer_key, conn_config, &peer);
   if(result || !peer) {
     CURL_TRC_SSLS(data, "unable to add scache peer: %d", result);
@@ -898,7 +938,7 @@ bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
                              const char *ssl_peer_key,
                              void **sobj)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct Curl_ssl_scache_peer *peer = NULL;
   CURLcode result;
@@ -924,7 +964,7 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
                                 struct Curl_easy *data,
                                 const char *ssl_peer_key)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct Curl_ssl_scache_peer *peer = NULL;
   CURLcode result;
@@ -977,6 +1017,9 @@ cf_ssl_find_peer_by_hmac(struct Curl_ssl_scache *scache,
   CURLcode result = CURLE_OK;
 
   *ppeer = NULL;
+  if(!GOOD_SCACHE(scache))
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
   /* look for an entry that matches salt+hmac exactly or has a known
    * ssl_peer_key which salt+hmac's to the same. */
   for(i = 0; scache && i < scache->peer_count; i++) {
@@ -1021,7 +1064,7 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data,
                                  const unsigned char *shmac, size_t shmac_len,
                                  const unsigned char *sdata, size_t sdata_len)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct Curl_ssl_scache_peer *peer = NULL;
   struct Curl_ssl_session *s = NULL;
   bool locked = FALSE;
@@ -1092,7 +1135,7 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
                                  curl_ssls_export_cb *export_fn,
                                  void *userptr)
 {
-  struct Curl_ssl_scache *scache = data->state.ssl_scache;
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct Curl_ssl_scache_peer *peer;
   struct dynbuf sbuf, hbuf;
   struct Curl_llist_node *n;

+ 1 - 1
Utilities/cmcurl/lib/vtls/wolfssl.c

@@ -770,7 +770,7 @@ wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
   int i;
   char *str;
 
-  for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
+  for(i = 0; (str = wolfSSL_get_cipher_list(i)) != NULL; i++) {
     size_t n;
     if((strncmp(str, "TLS13", 5) == 0) != tls13)
       continue;

+ 4 - 5
Utilities/cmlibarchive/CMakeLists.txt

@@ -887,8 +887,8 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
   IF(OPENSSL_FOUND)
     SET(HAVE_LIBCRYPTO 1)
     INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
-    LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY})
-    SET(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
+    list(APPEND ADDITIONAL_LIBS OpenSSL::Crypto)
+    set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
     SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
     LA_CHECK_INCLUDE_FILE("openssl/evp.h" HAVE_OPENSSL_EVP_H)
     CHECK_FUNCTION_EXISTS(PKCS5_PBKDF2_HMAC_SHA1 HAVE_PKCS5_PBKDF2_HMAC_SHA1)
@@ -1018,9 +1018,8 @@ main(int argc, char **argv)
       # was found on this platform.
       IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
         IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
-          INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
-	  LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_LIBRARIES})
-	   LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
+          LIST(APPEND ADDITIONAL_LIBS OpenSSL::Crypto)
+          LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
         ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
       ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
       ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM})